Compare commits

..

625 Commits

Author SHA1 Message Date
Sarabraj Singh
bd93ac7edd Merge pull request #12505 from sarabrajsingh/bugfix/add-setuptools-scm-dependency-to-workflow
added setuptools-scm dependency to promote.yml workflow
2022-07-12 10:21:10 -04:00
John Westcott IV
37ff9913d3 Adding GOOGLE_APPLICATION_CREDENTIALS env var (#12389)
* Adding GOOGLE_APPLICATION_CREDENTIALS env var
* Updating tests
2022-07-12 08:51:02 -04:00
Sarabraj Singh
9cb44a7e52 added setuptools-scm dependency to promote.yml workflow 2022-07-11 17:10:29 -04:00
John Westcott IV
6279295541 Updating workflow job template collection test (#12468)
Adding additional use case

Fixing error with workflow calling itslef

Adding better cleanup of assets created as part of the test
2022-07-11 17:07:07 -03:00
John Westcott IV
de17cff39c Modified triage replied (#12473)
Split no progress into issue and pr

added community.general standard response
2022-07-11 12:43:30 -04:00
Alex Corey
22ca49e673 Merge pull request #12493 from AlexSCorey/bumpCodeMirror
Bump code mirror
2022-07-11 09:43:54 -04:00
Tom Page
008a4b4d30 Fix workflow job template webhook credential bug - #12324 (#12325)
Signed-off-by: tompage1994@hotmail.co.uk <tpage@redhat.com>
2022-07-11 09:13:44 -03:00
Alex Corey
8d4089c7f3 Bumps code mirror and adds license files 2022-07-08 15:09:54 -04:00
vedaperi
e296d0adad Add Help Text with documentation link to Schedules page (#12448)
* Added help text to schedule form and detail with link to documentation

* Added test cases for help text in schedule form and detail

* Add help text to schedule form and detail with link to documentation

Co-authored-by: Veda Periwal <vperiwal@vperiwal-mac.attlocal.net>
2022-07-08 15:06:50 -04:00
Alex Corey
401b30b3ed Merge pull request #12451 from ansible/dependabot/npm_and_yarn/awx/ui/devel/patternfly/patternfly-4.202.1
Bump @patternfly/patternfly from 4.196.7 to 4.202.1 in /awx/ui
2022-07-08 08:13:30 -04:00
Alex Corey
20cc54694c Merge pull request #12454 from ansible/dependabot/npm_and_yarn/awx/ui/devel/patternfly/react-icons-4.75.1
Bump @patternfly/react-icons from 4.49.19 to 4.75.1 in /awx/ui
2022-07-08 08:12:58 -04:00
dependabot[bot]
e6ec0952fb Bump @patternfly/patternfly from 4.196.7 to 4.202.1 in /awx/ui
Bumps [@patternfly/patternfly](https://github.com/patternfly/patternfly) from 4.196.7 to 4.202.1.
- [Release notes](https://github.com/patternfly/patternfly/releases)
- [Changelog](https://github.com/patternfly/patternfly/blob/main/RELEASE-NOTES.md)
- [Commits](https://github.com/patternfly/patternfly/compare/prerelease-v4.196.7...prerelease-v4.202.1)

---
updated-dependencies:
- dependency-name: "@patternfly/patternfly"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-06 20:03:52 +00:00
dependabot[bot]
db1dec3a98 Bump @patternfly/react-icons from 4.49.19 to 4.75.1 in /awx/ui
Bumps [@patternfly/react-icons](https://github.com/patternfly/patternfly-react) from 4.49.19 to 4.75.1.
- [Release notes](https://github.com/patternfly/patternfly-react/releases)
- [Commits](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-icons@4.49.19...@patternfly/react-icons@4.75.1)

---
updated-dependencies:
- dependency-name: "@patternfly/react-icons"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-06 20:03:40 +00:00
Alex Corey
1853d3850e Merge pull request #12450 from ansible/dependabot/npm_and_yarn/awx/ui/devel/patternfly/react-table-4.93.1
Bump @patternfly/react-table from 4.83.1 to 4.93.1 in /awx/ui
2022-07-06 16:02:18 -04:00
dependabot[bot]
3cf120c6a7 Bump @patternfly/react-table from 4.83.1 to 4.93.1 in /awx/ui
Bumps [@patternfly/react-table](https://github.com/patternfly/patternfly-react) from 4.83.1 to 4.93.1.
- [Release notes](https://github.com/patternfly/patternfly-react/releases)
- [Commits](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-table@4.83.1...@patternfly/react-table@4.93.1)

---
updated-dependencies:
- dependency-name: "@patternfly/react-table"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-01 08:06:59 +00:00
Alan Rominger
fd671ecc9d Give specific messages if job was killed due to SIGTERM or SIGKILL (#12435)
* Reap jobs on dispatcher startup to increase clarity, replace existing reaping logic

* Exit jobs if receiving SIGTERM signal

* Fix unwanted reaping on shutdown, let subprocess close out

* Add some sanity tests for signal module

* Add a log for an unhandled dispatcher error

* Refine wording of error messages

Co-authored-by: Elijah DeLee <kdelee@redhat.com>
2022-06-30 13:20:08 -04:00
Shane McDonald
a0d5f1fb03 Merge pull request #12428 from djyasin/updating_setuppy
Updated setup.py --version to python3 -m setuptools_scm.
2022-06-30 12:17:54 -04:00
Alex Corey
ff882a322b Merge pull request #12412 from AlexSCorey/11994-FailedJobErrorMessage
Adds a failure message to job output when job failed and no events exist
2022-06-29 11:40:44 -04:00
Tom Page
b70231f7d0 Allow modification of schedule if there are two of the same name (#12407) 2022-06-28 20:23:54 -03:00
Alex Corey
93d1aa0a9d Adds a failure message to job output when job failed and no events exist. 2022-06-28 18:30:37 -04:00
Alex Corey
c586f8bbc6 Removes references to Ansible Tower in favor of Ansible Controller (#12422) 2022-06-28 14:35:32 -04:00
Alex Corey
26912a06d1 Merge pull request #12424 from AlexSCorey/11433-UpdateLaunchButtonTest
Updates irrelevant test
2022-06-28 14:31:26 -04:00
Alex Corey
218a3d333b updates test 2022-06-28 14:14:12 -04:00
Seth Foster
d2013bd416 Merge pull request #12366 from fosterseth/remove_update_on_project_update
Remove deprecated field update_on_project_update
2022-06-28 13:15:57 -04:00
Shane McDonald
6a3f9690b0 Remove setup.py entirely 2022-06-27 14:15:32 -04:00
Jeff Bradberry
d59b6f834c Merge pull request #12431 from jbradberry/fix-ugettext-deprecation
Fix a ugettext deprecation that snuck back in
2022-06-27 13:58:07 -04:00
Shane McDonald
cbea36745e Transition from setup.py to setup.cfg 2022-06-27 13:30:01 -04:00
Jeff Bradberry
ae7be525e1 Fix a ugettext deprecation that snuck back in
at some point after the Django 3.2 upgrade.
2022-06-27 13:27:35 -04:00
jainnikhil30
5062ce1e61 add database connection to the metrics endpoint (#12427)
* add database connection to the metrics endpoint

* bump the counts collector version to 1.2

* check for postgresql as database so to not break the tests
2022-06-27 09:37:23 -04:00
Alex Corey
566665ee8c Merge pull request #12417 from ansible/dependabot/npm_and_yarn/awx/ui/devel/patternfly/react-core-4.221.3
Bump @patternfly/react-core from 4.214.1 to 4.221.3 in /awx/ui
2022-06-27 09:36:58 -04:00
Alex Corey
96423af160 Merge pull request #12419 from ansible/dependabot/npm_and_yarn/awx/ui/devel/react-router-dom-5.3.3
Bump react-router-dom from 5.2.0 to 5.3.3 in /awx/ui
2022-06-27 09:36:22 -04:00
Alex Corey
a01bef8d2c Merge pull request #12420 from ansible/dependabot/npm_and_yarn/awx/ui/devel/lingui/react-3.14.0
Bump @lingui/react from 3.13.3 to 3.14.0 in /awx/ui
2022-06-27 09:35:40 -04:00
Seth Foster
0522233892 remove update_on_project_update from InventorySource 2022-06-24 15:27:08 -04:00
Lila
63ea6bb5b3 Updated setup.py --version to python3 -m setuptools_scm. 2022-06-24 10:22:56 -04:00
Sarah Akus
c2715d7c29 Merge pull request #12378 from john-westcott-iv/winrm_debug_5925
Making verbosity list and options a constant and adding WinRM debug
2022-06-24 09:06:14 -04:00
Alan Rominger
783b744bdb Pass combined artifacts from nested workflows into downstream nodes (#12223)
* Track combined artifacts on workflow jobs

* Avoid schema change for passing nested workflow artifacts

* Basic support for nested workflow artifacts, add test

* Forgot that only does not work with polymorphic

* Remove incorrect field

* Consolidate logic and prevent recursion with UJ artifacts method

* Stop trying to do precedence by status, filter for obvious ones

* Review comments about sets

* Fix up bug with convergence node paths and artifacts
2022-06-23 16:54:53 -03:00
Alex Corey
f7982a0d64 Merge pull request #12421 from AlexSCorey/updateAxios
Bumps Axios and Adds license files
2022-06-23 13:07:28 -04:00
Sarabraj Singh
2147ac226e Merge pull request #12408 from sarabrajsingh/feature/new-awx-cli-import-export-error-codes
[new] bubble up an error code when something goes wrong with import/export
2022-06-23 10:58:14 -04:00
Alex Corey
6cc22786bc Adds license files 2022-06-23 09:26:34 -04:00
dependabot[bot]
861a9f581e Bump @lingui/react from 3.13.3 to 3.14.0 in /awx/ui
Bumps [@lingui/react](https://github.com/lingui/js-lingui) from 3.13.3 to 3.14.0.
- [Release notes](https://github.com/lingui/js-lingui/releases)
- [Changelog](https://github.com/lingui/js-lingui/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lingui/js-lingui/compare/v3.13.3...v3.14.0)

---
updated-dependencies:
- dependency-name: "@lingui/react"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-23 12:34:58 +00:00
dependabot[bot]
e57a8183ba Bump react-router-dom from 5.2.0 to 5.3.3 in /awx/ui
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 5.2.0 to 5.3.3.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Commits](https://github.com/remix-run/react-router/commits/v5.3.3/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-23 12:34:20 +00:00
dependabot[bot]
8a7163ffad Bump @patternfly/react-core from 4.214.1 to 4.221.3 in /awx/ui
Bumps [@patternfly/react-core](https://github.com/patternfly/patternfly-react) from 4.214.1 to 4.221.3.
- [Release notes](https://github.com/patternfly/patternfly-react/releases)
- [Commits](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@4.214.1...@patternfly/react-core@4.221.3)

---
updated-dependencies:
- dependency-name: "@patternfly/react-core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-23 12:32:57 +00:00
Alex Corey
439b351c95 Merge pull request #12392 from nixocio/update_bot_user
Update user dependabot
2022-06-23 08:31:16 -04:00
Alex Corey
14afab918e Creates a verbosity select dropdowns and moves options constant into same file 2022-06-23 08:28:37 -04:00
Alex Corey
ef8d4e73ae Creates a verbosity select dropdowns and moves options constant into same file 2022-06-22 14:04:12 -04:00
John Westcott IV
61f483ae32 Fixing UI general test 2022-06-22 14:04:12 -04:00
John Westcott IV
21bed7473d Making verbosity list and options a constant and adding WinRM debug to everything 2022-06-22 14:04:11 -04:00
John Westcott IV
31d8ddcf84 Updating release docs (#12403)
Adding standard subject line to triage_replies.md

Removing PR commit generated change log in favor of github auto-commit log

Updating some images

Adding AWX matrix chanel to IRC notifications

Adding references between operator and AWX releases
2022-06-22 12:36:54 -04:00
Seth Foster
9419270897 Merge pull request #12393 from fosterseth/subsystem_metrics_delete_redis_keys
Subsystem metrics reset_values should remove all redis keys
2022-06-22 11:34:20 -04:00
Alex Corey
f755d93a58 Merge pull request #12373 from AlexSCorey/updateJS-Yaml
Updates js-yaml to 4.x and updates files.
2022-06-22 11:25:52 -04:00
Sarabraj Singh
05df2ebad2 bubble up an error code when something goes wrong with import/export
(cherry picked from commit babd6f0975)
2022-06-22 10:29:01 -04:00
Jeff Bradberry
b44442c460 Merge pull request #12351 from AlexSCorey/5673-t-importExportSchedules
Adds import export to awx cli for schedules as a top level object
2022-06-22 10:13:56 -04:00
Shane McDonald
989b389ba4 Merge pull request #12397 from sean-m-sullivan/awx_license_delete
add state to awx license module
2022-06-22 09:20:29 -04:00
Sarabraj Singh
5bd4aade0e Merge pull request #12404 from ansible/revert-12335-feature/awx-cli-import-export-error-codes
Revert "import/export error codes when something bad happens"
2022-06-21 22:01:46 -04:00
Jessica Steurer
470910b612 Merge pull request #12309 from jbradberry/cli-multiple-extra-vars
Allow for multiple --extra_vars or --variables flags in awx-cli
2022-06-21 19:34:25 -03:00
Sarabraj Singh
dbb81551c8 Revert "import/export error codes when something bad happens" 2022-06-21 17:36:21 -04:00
Sarabraj Singh
f7c5cb2979 Merge pull request #12335 from sarabrajsingh/feature/awx-cli-import-export-error-codes
import/export error codes when something bad happens
2022-06-21 16:49:03 -04:00
Sarabraj Singh
babd6f0975 bubble up an error code when something goes wrong with import/export 2022-06-21 15:53:59 -04:00
sean-m-sullivan
7bcceb7e98 add state to awx license module 2022-06-21 13:07:16 -04:00
Seth Foster
c92619a2dc Subsystem metrics reset_values should remove all redis keys 2022-06-16 16:54:37 -04:00
Alan Rominger
923cc671db Merge pull request #12391 from AlanCoding/compose_graphs
Do the grafana thing in docker-compose templating itself
2022-06-16 16:23:36 -04:00
Alan Rominger
db105c21e4 Set default false values 2022-06-16 15:46:42 -04:00
Alan Rominger
372aa36207 Make the prometheus config file ignored by git 2022-06-16 15:42:10 -04:00
Alan Rominger
173318764b Remove existing yml file for prometheus 2022-06-16 15:37:18 -04:00
Alan Rominger
1dd535a859 Remove old way of doing grafana graphs 2022-06-16 15:31:45 -04:00
nixocio
e7d37b26f3 Update user dependabot
Update user dependabot
2022-06-16 15:31:39 -04:00
Alan Rominger
f4ef7d6927 Add volumes to the clean command 2022-06-16 14:03:22 -04:00
Elijah DeLee
7cbe112e4e possible work around for 500 on /api/v2/metrics (#12376)
we've observed this in development and some users have reported experiencing 500's on /api/v2/metrics because of a key error here where a metric is missing from a certain instance
2022-06-16 13:15:25 -04:00
Alan Rominger
c441db2aab docs workding edits and depends_on 2022-06-16 12:07:26 -04:00
Alan Rominger
fb292d9706 Move visualization containers into docker-compose 2022-06-16 10:25:02 -04:00
Sarah Akus
35a5f93182 Merge pull request #12323 from AlexSCorey/5857-t-SanitizeLoginHTML
Removes Sanatize html in favor of dom purify library
2022-06-16 09:59:21 -04:00
Jessica Steurer
116dc0c480 Merge pull request #12340 from john-westcott-iv/shedule_timezone_12255
Add documentation around schedule timezone change
2022-06-15 15:34:49 -03:00
Alex Corey
b87ba1c53d Merge pull request #12382 from nixocio/ui_close_css
Update css var
2022-06-15 11:56:47 -04:00
Alex Corey
59691b71bb Merge pull request #12360 from nixocio/ui_issue_5012
Add column to display resource related to a schedule
2022-06-15 11:53:33 -04:00
Alex Corey
cc0bb3e401 Merge pull request #12365 from ansible/dependabot/npm_and_yarn/awx/ui/devel/ace-builds-1.6.0
Bump ace-builds from 1.5.1 to 1.6.0 in /awx/ui
2022-06-15 11:46:53 -04:00
nixocio
7ef90bd9f4 Update css var
Update css var
2022-06-15 11:37:04 -04:00
John Westcott IV
f820c49b82 Fixing typo in ISSUE_TEMPLATE.md (#12381) 2022-06-15 10:34:22 -04:00
Jessica Steurer
ac62d86f2a Merge pull request #12361 from kialam/refresh-data-lookup-modal
Allow lookup modals to refresh when opened.
2022-06-15 09:40:40 -03:00
John Westcott IV
b9e67e7972 Allowing blank issues with a template for testing purposes only (#12377) 2022-06-14 17:17:07 -04:00
Jeff Bradberry
48a2ebd48c Merge pull request #12271 from HampusLundqvist/gitlab-webhooks-fixes-#12268
return event_status on push, tag push, and merge gitlab webhook events
2022-06-14 17:12:27 -04:00
Sarah Akus
ee13ddd87d Merge pull request #12332 from nixocio/ui_issue_8097
Add typeahed for single choice surveys
2022-06-14 15:20:38 -04:00
Seth Foster
3fcf7429a3 Merge pull request #12246 from fosterseth/fix_haproxy_startup_error
use haproxy 2.3 with maxconn set to avoid startup failures
2022-06-14 14:41:14 -04:00
Sarah Akus
51a8790d56 Merge pull request #12348 from nixocio/ui_issue_111987
Update project status to reflect project sync related to job template
2022-06-14 14:41:01 -04:00
Jessica Steurer
c231e4d05e Merge pull request #12370 from nixocio/ui_issue_11795
Add column org to template list
2022-06-14 14:28:56 -03:00
Seth Foster
987e5a084d use haproxy 2.3 with maxconn set to avoid startup failures 2022-06-14 13:09:40 -04:00
Seth Foster
70ac7b2920 Merge pull request #12352 from fosterseth/docs_subsystem_metrics
Add docs for subsystem metrics
2022-06-14 13:05:21 -04:00
Alex Corey
bda335cb19 Updates js-yaml to 4.x and updates files. 2022-06-14 12:24:40 -04:00
Seth Foster
30c060cb27 Merge pull request #12235 from fosterseth/subsystem_metrics_task_manager
Subsystem metrics for task manager
2022-06-14 12:02:54 -04:00
Kersom
9b0a2b0b76 Merge pull request #12312 from nixocio/ui_issue_11167_rebased
Update logout/login redirect for different users
2022-06-14 11:55:05 -04:00
Seth Foster
2f82b75748 Add subsystem metrics for task manager 2022-06-14 11:00:11 -04:00
Sarah Akus
84fcd2ff00 Merge pull request #12363 from nixocio/ui_issue_5195
Modify position of tooltip for management job list
2022-06-14 10:29:49 -04:00
Jeff Bradberry
3bc0c53e37 Merge pull request #12368 from jbradberry/narrower-autoreload
Narrow down the inotifywait criteria for reloading the dev environment
2022-06-14 10:13:41 -04:00
Alex Corey
bc2dbcfce8 Merge pull request #12344 from ansible/dependabot/npm_and_yarn/awx/ui/devel/patternfly/patternfly-4.196.7
Bump @patternfly/patternfly from 4.194.4 to 4.196.7 in /awx/ui
2022-06-13 16:58:48 -04:00
nixocio
876edf54a3 Modify position of tooltip for management job list
Modify position of tooltip for management job list. Also, remove
duplicated tooltip.
2022-06-13 16:42:43 -04:00
nixocio
b31bf8fab1 Add column org to template list
Add column org to template list

See: https://github.com/ansible/awx/issues/11795
2022-06-13 16:37:32 -04:00
Jeff Bradberry
e8b2998578 Narrow down the inotifywait criteria for reloading the dev environment
- listen specifically within awx/awx, so that changes in awxkit or
  awx_collection don't trigger spurious reloads
- expand the exclude pattern to ignore the test directories
2022-06-13 16:08:20 -04:00
nixocio
8a92a01652 Add column to display resource related to a schedule
Add column to display what resource is related to a schedule

See: https://github.com/ansible/awx/issues/5012
2022-06-13 14:28:44 -04:00
Seth Foster
705f86f8cf Merge pull request #12287 from fosterseth/fix_children_summary_not_tree
detect if job events are tree-like and collapsible
2022-06-13 14:27:39 -04:00
Alex Corey
9ab6a6d57e Merge pull request #11429 from akelling/patch-1
Update README.md
2022-06-13 14:19:16 -04:00
Sarah Akus
791eb4c1e1 Merge pull request #12349 from nixocio/ui_issue_12092
Add loading state when saving a visualizer
2022-06-13 14:06:34 -04:00
dependabot[bot]
870ca29388 Bump ace-builds from 1.5.1 to 1.6.0 in /awx/ui
Bumps [ace-builds](https://github.com/ajaxorg/ace-builds) from 1.5.1 to 1.6.0.
- [Release notes](https://github.com/ajaxorg/ace-builds/releases)
- [Changelog](https://github.com/ajaxorg/ace-builds/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ajaxorg/ace-builds/compare/v1.5.1...v1.6.0)

---
updated-dependencies:
- dependency-name: ace-builds
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 18:00:10 +00:00
Kersom
816518cfab Merge pull request #12302 from ansible/dependabot/npm_and_yarn/awx/ui/devel/react-ace-10.1.0
Bump react-ace from 9.4.0 to 10.1.0 in /awx/ui
2022-06-13 13:58:55 -04:00
Alex Corey
9e981583a6 Merge branch 'devel' into patch-1 2022-06-13 13:55:02 -04:00
Alex Corey
d6fb8d6cd7 Update tools/docker-compose/README.md
Co-authored-by: Shane McDonald <me@shanemcd.com>
2022-06-13 13:53:48 -04:00
Sarah Akus
7dbf5f7138 Merge pull request #12358 from nixocio/ui_issue_5883
Hide add access button based on the user profile for credentials
2022-06-13 13:38:36 -04:00
dependabot[bot]
aaec9487e6 Bump react-ace from 9.4.0 to 10.1.0 in /awx/ui
Bumps [react-ace](https://github.com/securingsincity/react-ace) from 9.4.0 to 10.1.0.
- [Release notes](https://github.com/securingsincity/react-ace/releases)
- [Changelog](https://github.com/securingsincity/react-ace/blob/main/CHANGELOG.md)
- [Commits](https://github.com/securingsincity/react-ace/compare/v9.4.0...v10.1.0)

---
updated-dependencies:
- dependency-name: react-ace
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 17:37:54 +00:00
Kia Lam
96fa881df1 Fix unit test. 2022-06-13 08:59:31 -07:00
Seth Foster
b7057fdc3e Add docs for subsystem metrics 2022-06-13 11:49:56 -04:00
nixocio
2679c99cad Add loading state when saving a visualizer
Add loading state when saving a visualizer

See: https://github.com/ansible/awx/issues/12092
2022-06-13 10:47:27 -04:00
Jessica Steurer
ea3a8d4912 Merge pull request #12306 from ansible/10961-webhook-notification-does-not-allow-for-use-of-jinja-statements
Duplication of PR of Jinga 2 Rendering
2022-06-13 09:38:42 -03:00
John Westcott IV
63d9cd7b57 .github folder maintaince (#12327)
* Removing old awxbot files
* Removing security bug report as GitHub now shows the security piolicy from /SECURITY.md
* Changing feature_request from md to yml
* Adding additional options to bug report components andinstall method
* Removing old ISSUE_TEMPLATE.md
* Changing issue type and adding additional components
* Removing auto-generated change log
* Adding awx_collection and cli components
* Changing content search pattern for type labels
* Changing from collection to awx_collection tag and adding dependencies tag
* Adding unicode bug to bug repot to match feature unicode character
* Changing bug to bug or docs
* Remove docker on * and boot2docker infavor of docker development environmnet
* Create top level issue with: CoC, Enterprise, Top level help
* Remove old CODEOWNERS file
2022-06-13 07:44:15 -04:00
Kia Lam
b692bbaa12 Allow lookup modals to refresh when opened. 2022-06-10 14:44:53 -07:00
John Westcott IV
186af73e5d Fixing slashes for copy/paste of links (#12359) 2022-06-10 14:29:12 -04:00
John Westcott IV
fddf292d47 Additional changes from review 2022-06-10 10:26:24 -04:00
John Westcott IV
1180634ba7 Fixing UI checks 2022-06-10 10:26:23 -04:00
John Westcott IV
9abdafe101 Removing read_only as its the default setting 2022-06-10 10:26:23 -04:00
John Westcott IV
48ebcd5918 Fixing assertion of schedule_zoneinfo 2022-06-10 10:26:23 -04:00
John Westcott IV
fe6d0ce9cc Adding help text to until and timezone fields 2022-06-10 10:26:23 -04:00
John Westcott IV
62dabcae63 Removing unneeded function 2022-06-10 10:26:23 -04:00
Keith J. Grant
0b63af8d4d add schedules timezone link warning to UI 2022-06-10 10:26:23 -04:00
John Westcott IV
b05ebe9623 Starting UI change to warn if linked TZ is selected 2022-06-10 10:26:23 -04:00
John Westcott IV
c836fafb61 modifying schedules API to return a list of links 2022-06-10 10:26:23 -04:00
nixocio
96330f608d Hide add access based on the user profile for credentials
* Show add access button if it is a system admin
* Hide access button if the user is credential admin, org admin, but the
  credential does not belong to any org.
* Show access button if the user is a credential admin, org admin, and
  the credential is associated to an org.
* Show access button if the user is an org admin and the credential is
  associated to the org.

All those permutations are allowed by the API RBAC.
This PR update UX to not allow the user to attempt to perform any
action that will raise an error when modifying access to the
credentials.
2022-06-10 10:09:18 -04:00
Kersom
23aaf5b3ad Add cancel button to workflow job output (#12338)
Add cancel button to workflow job output

See: https://github.com/ansible/awx/issues/10514
2022-06-09 20:16:07 -04:00
Kersom
a3e86dcd73 Hide management job for non system admin as node choice (#12341)
Hide management job for non system admin as node type choice. Also, fix
related uni-tests related to this change.

See: https://github.com/ansible/awx/issues/12334
Also: https://github.com/ansible/awx/pull/10572
2022-06-09 20:15:03 -04:00
Alan Rominger
81b8028ea2 Merge pull request #12355 from AlanCoding/autoreload_once
Make awx-autoreloader work faster for large code changes
2022-06-09 15:19:17 -04:00
Alan Rominger
a4bfb032ff Make awx-autoreloader work faster for large code changes 2022-06-09 14:52:03 -04:00
Keith J. Grant
2704b202bf check for is_tree flag from children summary response 2022-06-09 14:25:39 -04:00
Seth Foster
550d9d5e42 detect if job events are tree-like and collapsable in the UI 2022-06-09 14:25:39 -04:00
John Westcott IV
ab2d05a07d Update replies documentation (#12305)
Adding heads and a couple standard replies and rewording other replies.
2022-06-09 13:41:53 -04:00
Alan Rominger
4543f6935f Only do substitutions for container path conversions with resolved paths (#12313)
* Resolve paths as much as possible before doing replacements

* Move unused method out of main code, test symlink
2022-06-09 11:36:29 -04:00
Alan Rominger
78d3d6dc94 Merge pull request #12219 from AlanCoding/really_skip
Change Demo Project status to successful
2022-06-09 11:19:57 -04:00
Alex Corey
02e7424f51 Adds import export to awx cli for schedules as a top level object 2022-06-09 09:47:50 -04:00
Andrea Decorte
2d6ca4cbb1 Update role module example (#12295)
Update example to use current parameter for workflows
instead of the deprecated one.

Signed-off-by: Andrea Decorte <adecorte@redhat.com>
2022-06-09 09:38:55 -04:00
Aine Riordan
e244644a1d Fix typo in application module example (#12187) 2022-06-09 09:38:34 -04:00
Jessica Steurer
d216457c09 Merge pull request #12320 from nixocio/ui_issue_2899
Pre-fill project for job template from query params
2022-06-09 10:24:29 -03:00
nixocio
20a1da61c0 Update project status to reflect project sync related to job template
Update project status to reflect project update sync related to job
template that was launched with branch override.

We were displaying status of project sync itself, not from the project
update job as expected.

Also, rename `Project Status` to be `Project Update Status`.

See: https://github.com/ansible/awx/issues/11987
2022-06-08 13:41:45 -04:00
Jessica Steurer
bf7ab1ede7 Merge pull request #12315 from djyasin/job_tag_characters
Job tag characters
2022-06-08 12:09:18 -03:00
Alex Corey
3b6b449545 Removes unneeded license files 2022-06-08 10:04:25 -04:00
Alex Corey
781cf531e6 Removes Sanatize html in favor of dom purify library 2022-06-08 10:04:25 -04:00
dependabot[bot]
9b7475247c Bump @patternfly/patternfly from 4.194.4 to 4.196.7 in /awx/ui
Bumps [@patternfly/patternfly](https://github.com/patternfly/patternfly) from 4.194.4 to 4.196.7.
- [Release notes](https://github.com/patternfly/patternfly/releases)
- [Changelog](https://github.com/patternfly/patternfly/blob/main/RELEASE-NOTES.md)
- [Commits](https://github.com/patternfly/patternfly/compare/prerelease-v4.194.4...prerelease-v4.196.7)

---
updated-dependencies:
- dependency-name: "@patternfly/patternfly"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-08 14:00:52 +00:00
Alex Corey
44dc7f8d1d Merge pull request #12333 from ansible/dependabot/npm_and_yarn/awx/ui/devel/rrule-2.7.0
Bump rrule from 2.6.4 to 2.7.0 in /awx/ui
2022-06-08 09:59:39 -04:00
Kersom
60eaf9e235 Provide feedback when a health check is being performed (#12330)
Provide feedback when a health check is being performed
2022-06-07 16:27:46 -04:00
Jessica Steurer
f5102ed24d Merge pull request #12102 from john-westcott-iv/allow_fqcn
Respect optional fully qualified collection name (ansible.builtin.) for playbook identification
2022-06-07 16:44:36 -03:00
Jessica Steurer
309178e4e2 Merge pull request #12331 from kialam/fix-worker-json-404
Allow worker files to be loaded as blob objects.
2022-06-07 16:33:59 -03:00
Rebeccah Hunter
76ffdbb993 Merge pull request #12308 from rebeccahhh/job_event_lag
Metrics for callback receiver job event lag
2022-06-07 11:50:17 -04:00
nixocio
d8037618c8 Update logout/login redirect for different users
* Logout as User A and Login as User B redirects to `/home'
* Logout as User A and Login as User A redirects to `/home'
* Allow session to timeout as User A and Login as User A redirects to User A's last location

See: https://github.com/ansible/awx/issues/11167
2022-06-07 09:48:41 -04:00
Alex Corey
e94e15977c Merge pull request #12328 from ansible/dependabot/npm_and_yarn/awx/ui/async-2.6.4
Bump async from 2.6.3 to 2.6.4 in /awx/ui
2022-06-07 09:13:47 -04:00
John Westcott IV
f37951249f Adding options fqcn (ansible.builtin.) to playbook identification 2022-06-06 17:32:37 -04:00
Jeff Bradberry
9191079dda Merge pull request #11921 from jbradberry/fix-export-reconstruct-endpoint
Look up the correct top-level resource name when reconstructing foreign keys
2022-06-06 17:08:02 -04:00
Keith Grant
fdd560747d Persistent list filters (#12229)
* add PersistentFilters component

* add PersistentFilters test

* add persistent filters to all list pages

* update tests

* clear sessionStorage on logout

* fix persistent filter on wfjt detail; cleanup
2022-06-06 16:56:45 -04:00
Jeff Bradberry
faa5df19ca Merge pull request #12252 from jbradberry/fix-analytics-unicode
Double escape all unicode escape sequences in job events data
2022-06-06 16:41:06 -04:00
Rebeccah
5f9326b131 added average event processing metric (in seconds) that can be served to
grafana via prometheus.

This metric is a good indicator of how far behind the callback receiver
is. The higher the load the further behind/the greater the number of
seconds the metric will display.

This number being high may indicate the need for horizontal scaling in
the control plane or vertically scaling the number of callback
receivers.
2022-06-06 15:14:56 -04:00
dependabot[bot]
8e389d40b4 Bump rrule from 2.6.4 to 2.7.0 in /awx/ui
Bumps [rrule](https://github.com/jakubroztocil/rrule) from 2.6.4 to 2.7.0.
- [Release notes](https://github.com/jakubroztocil/rrule/releases)
- [Changelog](https://github.com/jakubroztocil/rrule/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jakubroztocil/rrule/commits)

---
updated-dependencies:
- dependency-name: rrule
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 18:58:46 +00:00
nixocio
e62c77e783 Add typeahed for single choice surveys
Add typeahed for single choice surveys, also fix a couple of missing
translations for Select component.

See: https://github.com/ansible/awx/issues/8097
2022-06-06 13:57:00 -04:00
Kia Lam
48b3a43ec2 Allow worker files to be loaded as blob objects. 2022-06-06 10:47:30 -07:00
Lila
5f783fd5ee Revised job_tags to handle more than 1024 characters. 2022-06-06 13:28:22 -04:00
dependabot[bot]
e112cf93c2 Bump async from 2.6.3 to 2.6.4 in /awx/ui
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

---
updated-dependencies:
- dependency-name: async
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 13:51:52 +00:00
Alex Corey
d9f26a411e Merge pull request #12318 from ansible/dependabot/npm_and_yarn/awx/ui/node-forge-1.3.1
Bump node-forge from 1.2.1 to 1.3.1 in /awx/ui
2022-06-05 14:25:42 -04:00
Kersom
ea84e7a491 Merge pull request #12322 from nixocio/fix_typo
Fix typo
2022-06-03 22:46:06 -04:00
Alex Corey
7fab619fed Merge pull request #12317 from ansible/dependabot/npm_and_yarn/awx/ui/ejs-3.1.8
Bump ejs from 3.1.6 to 3.1.8 in /awx/ui
2022-06-03 16:13:35 -04:00
nixocio
699a35b88a Fix typo
Fix typo on triage replies
2022-06-03 15:22:49 -04:00
nixocio
8095adb945 Pre-fill project for job template from query params
Pre-fill project when creating JT from Project -> Job Templates
List
2022-06-03 11:32:01 -04:00
Hampus Lundqvist
8d36712860 return status on event types defined in ref_keys 2022-06-03 16:10:44 +02:00
dependabot[bot]
0db34d0498 Bump node-forge from 1.2.1 to 1.3.1 in /awx/ui
Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.2.1 to 1.3.1.
- [Release notes](https://github.com/digitalbazaar/forge/releases)
- [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md)
- [Commits](https://github.com/digitalbazaar/forge/compare/v1.2.1...v1.3.1)

---
updated-dependencies:
- dependency-name: node-forge
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-03 14:06:45 +00:00
dependabot[bot]
7ab254e5e3 Bump ejs from 3.1.6 to 3.1.8 in /awx/ui
Bumps [ejs](https://github.com/mde/ejs) from 3.1.6 to 3.1.8.
- [Release notes](https://github.com/mde/ejs/releases)
- [Changelog](https://github.com/mde/ejs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mde/ejs/compare/v3.1.6...v3.1.8)

---
updated-dependencies:
- dependency-name: ejs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-03 14:06:14 +00:00
Alex Corey
dd7ab459e2 Merge pull request #12196 from AlexSCorey/popoversInventoryAndInventorySource
Adds popover text for Inventory and InventorySources
2022-06-03 10:01:36 -04:00
Alex Corey
33df2e8aa4 Adds popover text for Inventory and InventorySources 2022-06-03 09:38:45 -04:00
Jessica Steurer
39b8fd433b Merge pull request #12251 from nixocio/ui_issue_11196
Add controller_node to job details page
2022-06-03 08:57:29 -03:00
Kersom
c31d74100d Add host description in a couple of screens (#12292)
Add host description in a couple of screens

See:https://github.com/ansible/awx/issues/3348
Also: https://github.com/ansible/awx/issues/9363
2022-06-02 15:40:41 -04:00
Alan Rominger
3af89c1e2b Merge pull request #12307 from AlanCoding/twilio
Upgrade twilio dependency to pick up fix
2022-06-02 13:48:34 -04:00
John Westcott IV
1d35bba8c3 Variablizing the awx_template_version for building to allow release process to update the version in the module_util (#12248) 2022-06-02 12:28:57 -04:00
djyasin
c3c3e24875 Merge pull request #12314 from john-westcott-iv/add_irc_msg_to_release
Adding irc bullhorn to release process
2022-06-02 11:57:32 -04:00
John Westcott IV
ab9c97b158 Adding irc bullhorn to release process 2022-06-02 11:30:57 -04:00
nixocio
5e700c992d Add controller_node to job details page
Add controller_node to job details page. Modify serializers to make
controller_node available to the UI.

See: https://github.com/ansible/awx/issues/11196
Also: https://github.com/ansible/awx/issues/12132
2022-06-02 11:21:06 -04:00
Seth Foster
b548ad21a9 Merge pull request #12240 from fosterseth/make_prometheus_grafana
Add prometheus and grafana make commands for local environment
2022-06-01 17:55:43 -04:00
Jeff Bradberry
127016d36b Allow for multiple --extra_vars or --variables flags in awx-cli
This is particularly useful when you are using the @filepath version
of the flag, since otherwise there would be no way to issue the
command with multiple vars files.

Also, add `-e` as an alias to `--extra_vars`
2022-06-01 13:24:24 -04:00
kialam
3d0391173b Add popover help text to job details and ad hoc job details (#12261)
* Add popover text to Job Details page.

* Add module documentation links to ad hoc job detail page.

* Add forks help text to job details.
2022-06-01 13:00:59 -04:00
kialam
ce560bcd5f Cleanup some text strings files to return object literals (#12269)
* Cleanup some text strings files to return object literals instead of arrow functions.

* Fix render.

* Fix unit tests.
2022-06-01 12:10:55 -04:00
Alan Rominger
d553c37d7d Upgrade twilio dependency to pick up fix 2022-06-01 11:35:43 -04:00
John Maynard
8a5e89e24b Switch Jinja2 environment for rendering before testing JSON to ImmutableSandboxedEnvironment
Render Jinja template before checking for valid JSON
2022-06-01 11:10:15 -04:00
Kersom
8c3e289170 Merge pull request #12178 from Tioborto/feat/add-token-description-column
feat: add token description column
2022-06-01 10:17:28 -04:00
Seth Foster
9364c8e562 typo 2022-05-31 17:18:45 -04:00
Seth Foster
5831949ebf maxconn 2022-05-31 17:16:27 -04:00
Seth Foster
7fe98a670f haproxy 2022-05-31 17:12:19 -04:00
Seth Foster
6f68f3cba6 Add make prometheus and make grafana commands to dev environment 2022-05-31 17:07:15 -04:00
Alex Corey
4dc956c76f Merge pull request #12275 from ansible/dependabot/npm_and_yarn/awx/ui/devel/ace-builds-1.5.1
Bump ace-builds from 1.4.12 to 1.5.1 in /awx/ui
2022-05-31 10:32:25 -04:00
Alex Corey
11a56117eb Merge pull request #12284 from ansible/dependabot/npm_and_yarn/awx/ui/devel/codemirror-5.65.4
Bump codemirror from 5.61.0 to 5.65.4 in /awx/ui
2022-05-31 10:31:51 -04:00
Alex Corey
10eed6286a Merge pull request #12285 from ansible/dependabot/npm_and_yarn/awx/ui/devel/styled-components-5.3.5
Bump styled-components from 5.3.0 to 5.3.5 in /awx/ui
2022-05-31 10:31:09 -04:00
Jessica Steurer
d36befd9ce Merge pull request #12283 from jainnikhil30/add_forks_to_job_details
add forks to the job details
2022-05-26 18:03:29 -03:00
Jessica Steurer
0c4ddc7f6f Merge pull request #12280 from nixocio/ui_issue_12279
Allow to copy entity within the minute
2022-05-26 14:09:35 -03:00
nixocio
3ef9679de3 Allow to copy entity within the minute
Allow to copy entity within the minute - add seconds, and miliseconds as part of the name
of copied entity.

See: https://github.com/ansible/awx/issues/12279
2022-05-25 16:35:22 -04:00
dependabot[bot]
d36441489a Bump styled-components from 5.3.0 to 5.3.5 in /awx/ui
Bumps [styled-components](https://github.com/styled-components/styled-components) from 5.3.0 to 5.3.5.
- [Release notes](https://github.com/styled-components/styled-components/releases)
- [Changelog](https://github.com/styled-components/styled-components/blob/main/CHANGELOG.md)
- [Commits](https://github.com/styled-components/styled-components/compare/v5.3.0...v5.3.5)

---
updated-dependencies:
- dependency-name: styled-components
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-25 18:46:16 +00:00
Alex Corey
d26c12dd7c Merge pull request #12243 from ansible/dependabot/npm_and_yarn/awx/ui/devel/patternfly/patternfly-4.194.4
Bump @patternfly/patternfly from 4.192.1 to 4.194.4 in /awx/ui
2022-05-25 14:44:27 -04:00
dependabot[bot]
7fa7ed3658 Bump @patternfly/patternfly from 4.192.1 to 4.194.4 in /awx/ui
Bumps [@patternfly/patternfly](https://github.com/patternfly/patternfly) from 4.192.1 to 4.194.4.
- [Release notes](https://github.com/patternfly/patternfly/releases)
- [Changelog](https://github.com/patternfly/patternfly/blob/main/RELEASE-NOTES.md)
- [Commits](https://github.com/patternfly/patternfly/compare/prerelease-v4.192.1...prerelease-v4.194.4)

---
updated-dependencies:
- dependency-name: "@patternfly/patternfly"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-25 18:16:48 +00:00
Jessica Steurer
2c68e7a3d2 Merge pull request #12247 from nixocio/ui_issue_12129
Add job_explanation job details page
2022-05-25 14:45:39 -03:00
Alex Corey
0c9b1c3c79 Merge pull request #12274 from ansible/dependabot/npm_and_yarn/awx/ui/devel/lingui/react-3.13.3
Bump @lingui/react from 3.9.0 to 3.13.3 in /awx/ui
2022-05-25 12:09:01 -04:00
dependabot[bot]
e10b0e513e Bump @lingui/react from 3.9.0 to 3.13.3 in /awx/ui
Bumps [@lingui/react](https://github.com/lingui/js-lingui) from 3.9.0 to 3.13.3.
- [Release notes](https://github.com/lingui/js-lingui/releases)
- [Changelog](https://github.com/lingui/js-lingui/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lingui/js-lingui/compare/v3.9.0...v3.13.3)

---
updated-dependencies:
- dependency-name: "@lingui/react"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-25 15:49:56 +00:00
dependabot[bot]
68c66edada Bump ace-builds from 1.4.12 to 1.5.1 in /awx/ui
Bumps [ace-builds](https://github.com/ajaxorg/ace-builds) from 1.4.12 to 1.5.1.
- [Release notes](https://github.com/ajaxorg/ace-builds/releases)
- [Changelog](https://github.com/ajaxorg/ace-builds/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ajaxorg/ace-builds/compare/v1.4.12...v1.5.1)

---
updated-dependencies:
- dependency-name: ace-builds
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-25 15:49:30 +00:00
dependabot[bot]
6eb17e7af7 Bump codemirror from 5.61.0 to 5.65.4 in /awx/ui
Bumps [codemirror](https://github.com/codemirror/CodeMirror) from 5.61.0 to 5.65.4.
- [Release notes](https://github.com/codemirror/CodeMirror/releases)
- [Changelog](https://github.com/codemirror/CodeMirror/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codemirror/CodeMirror/compare/5.61.0...5.65.4)

---
updated-dependencies:
- dependency-name: codemirror
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-25 15:49:11 +00:00
Alex Corey
9a24da3098 Merge pull request #12281 from ansible/dependabot/npm_and_yarn/awx/ui/devel/patternfly/react-table-4.83.1
Bump @patternfly/react-table from 4.75.2 to 4.83.1 in /awx/ui
2022-05-25 11:48:18 -04:00
Nikhil
8ed0543b8b add forks to the job details 2022-05-25 20:07:38 +05:30
dependabot[bot]
73a84444d1 Bump @patternfly/react-table from 4.75.2 to 4.83.1 in /awx/ui
Bumps [@patternfly/react-table](https://github.com/patternfly/patternfly-react) from 4.75.2 to 4.83.1.
- [Release notes](https://github.com/patternfly/patternfly-react/releases)
- [Commits](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-table@4.75.2...@patternfly/react-table@4.83.1)

---
updated-dependencies:
- dependency-name: "@patternfly/react-table"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-24 19:40:54 +00:00
Alex Corey
451767c179 Merge pull request #12207 from ansible/dependabot/npm_and_yarn/awx/ui/devel/eslint-plugin-i18next-5.2.1
Bump eslint-plugin-i18next from 5.1.2 to 5.2.1 in /awx/ui
2022-05-24 15:39:40 -04:00
Alan Rominger
8366386126 Merge pull request #12260 from AlanCoding/callback_status
Fix the callback receiver --status command
2022-05-24 15:26:02 -04:00
Alex Corey
997686a2ea Merge pull request #12257 from AlexSCorey/updateDependabot
Dependabot runs monthly and only makes prs for production dependencies
2022-05-24 09:35:09 -04:00
HampusLundqvist
f02212b1fe return event_status on all gitlab webhook types 2022-05-23 22:13:00 +02:00
Jessica Steurer
2ba68ef5d0 Merge pull request #12249 from keithjgrant/filter-ws-jobs
use qs params when fetching new/updated jobs to preserve filters
2022-05-19 17:24:52 -03:00
djyasin
2041665880 Merge pull request #12227 from ansible/vaultcredentialsbug
Prevent edit of  vault ID once credential is created.
2022-05-19 15:13:41 -04:00
Alan Rominger
1e6ca01686 Fix the callback receiver --status command 2022-05-19 15:00:49 -04:00
Alex Corey
e15a76e7aa Dependabot runs monthly and only makes prs for production dependencies 2022-05-19 11:16:51 -04:00
Alex Corey
64db44acef Adds popover for Notification Templates and Instance group details (#12197) 2022-05-18 19:04:21 -04:00
Keith J. Grant
9972389a8d fetch relevant jobs based on WS events 2022-05-18 14:40:18 -07:00
Seth Foster
e0b1274eee Merge pull request #12094 from sean-m-sullivan/wait
update awx collection wait interval to 2
2022-05-18 15:00:24 -04:00
Jeff Bradberry
973facebba Double escape all unicode escape sequences in job events data
when collecting it for analytics.
2022-05-18 12:00:03 -04:00
sean-m-sullivan
df649e2c56 update awx collection wait interval to 2 2022-05-18 09:57:40 -04:00
nixocio
a778017efb Add job_explanation job details page
Add job_explanation job details page

See: https://github.com/ansible/awx/issues/12129
2022-05-18 09:16:39 -04:00
Keith J. Grant
6a9305818e use qs params when fetching new/updated jobs to preserve filters 2022-05-17 14:57:57 -07:00
Alexandre Bortoluzzi
2669904c72 fix: header row style 2022-05-17 23:04:34 +02:00
Kersom
35529b5eeb Add help text popovers to /#/applications details fields (#12222)
Add help text popovers to /#/applications details fields

See: https://github.com/ansible/awx/issues/11873
2022-05-17 20:11:51 +00:00
Sarah Akus
d55ed8713c Merge pull request #12239 from kialam/fix-12228-edit-deleted-wf-node
Fix on save error message for wf approval nodes.
2022-05-17 12:07:45 -04:00
Kersom
7973f28bed Merge pull request #12237 from ansible/dependabot/npm_and_yarn/awx/ui/devel/mock-socket-9.1.3
Bump mock-socket from 9.0.3 to 9.1.3 in /awx/ui
2022-05-17 11:31:45 -04:00
dependabot[bot]
8189964cce Bump mock-socket from 9.0.3 to 9.1.3 in /awx/ui
Bumps [mock-socket](https://github.com/thoov/mock-socket) from 9.0.3 to 9.1.3.
- [Release notes](https://github.com/thoov/mock-socket/releases)
- [Changelog](https://github.com/thoov/mock-socket/blob/master/CHANGELOG.md)
- [Commits](https://github.com/thoov/mock-socket/commits)

---
updated-dependencies:
- dependency-name: mock-socket
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-17 14:24:27 +00:00
Sarah Akus
ee4c901dc7 Merge pull request #12210 from ansible/dependabot/npm_and_yarn/awx/ui/devel/react-error-boundary-3.1.4
Bump react-error-boundary from 3.1.3 to 3.1.4 in /awx/ui
2022-05-17 10:17:44 -04:00
Lila
78220cad82 Disables ability to edit vault ID on the UI side. 2022-05-16 16:56:29 -04:00
Lila
40279bc6c0 Wrote corresponding tests.
Updated verbiage to be more in line with existing messages.
2022-05-16 16:55:49 -04:00
Lila
f6fb46d99e Prevent edit of vault ID once credential is created and added check to ensure user is actually trying to change vault id. 2022-05-16 16:54:03 -04:00
Kia Lam
954b32941e Fix on save error message for wf approval nodes. 2022-05-16 11:17:23 -07:00
Seth Foster
48b016802c Merge pull request #12049 from fosterseth/awxkit_import_help_text
Improve awxkit import -h
2022-05-16 11:59:44 -04:00
Alex Corey
35aa5dd79f Merge pull request #12212 from ansible/dependabot/npm_and_yarn/awx/ui/devel/luxon-2.4.0
Bump luxon from 2.0.1 to 2.4.0 in /awx/ui
2022-05-16 09:44:09 -04:00
JST
237402068c Merge pull request #12073 from fosterseth/scm_invsrc_project_update
SCM inv source should trigger project update
2022-05-16 09:17:45 -03:00
Kersom
31dda6e9d6 Add help text popovers to /#/execution_environments details fields (#12224)
Add help text popovers to /#/execution_environments details fields

See: https://github.com/ansible/awx/issues/11874
2022-05-13 14:53:36 -04:00
Alan Rominger
bca6e00e37 Change Demo Project status to successful 2022-05-12 16:14:09 -04:00
Sarah Akus
1c9b4af61d Merge pull request #12213 from nixocio/ui_issue_5727
Add details related workflow job on the workflow approval details
2022-05-12 16:02:25 -04:00
Seth Foster
eba4a3f1c2 in case we fail a job in task manager, we need to add the project update to the inventoryupdate.source_project field 2022-05-12 15:21:17 -04:00
Seth Foster
0ae9fe3624 if dependency fails, fail job in task manager 2022-05-12 14:00:13 -04:00
Seth Foster
1b662fcca5 SCM inv source trigger project update
- scm based inventory sources should launch project updates prior to
running inventory updates for that source.
- fixes scenario where a job is based on projectA, but the inventory
source is based on projectB. Running the job will likely trigger a
sync for projectA, but not projectB.

comments
2022-05-12 14:00:12 -04:00
John Westcott IV
cfdba959dd Falling back to project.status if the last project sync job was deleted (#12215) 2022-05-12 12:22:04 -04:00
John Westcott IV
78660ad0a2 Updated dependencies to reduce issues with dependabot and container scanning (#12180)
Modify updater.sh to remove the local path references.
2022-05-12 09:25:36 -04:00
kialam
70697869d7 Merge pull request #12220 from kialam/add-popover-detail-job-templates
Fix pop over text for job template details page.
2022-05-11 18:34:42 -07:00
Kia Lam
10e55108ef Fix pop over text for job template details page. 2022-05-11 16:14:58 -07:00
JST
d4223b8877 Merge pull request #12204 from kialam/add-popover-detail-job-templates
Add popover text to JT and WJT details pages.
2022-05-11 17:39:47 -03:00
Shane McDonald
9537d148d7 Merge pull request #12175 from TheRealHaoLiu/change-ee-container-volume-selinux-label
change SELinux label for EE volume mount
2022-05-11 16:00:02 -04:00
Kia Lam
a133a14b70 Fix unit tests. 2022-05-11 12:29:32 -07:00
Jeff Bradberry
4ca9e9577b Merge pull request #12216 from jangel97/devel
add param all_pages to method export_assets
2022-05-11 14:51:50 -04:00
Jose Angel Morena
44986fad36 set all_pages to True by default in get_method 2022-05-11 19:54:26 +02:00
Jose Angel Morena
eb2fca86b6 set all_pages to True by default in get_method 2022-05-11 19:52:32 +02:00
nixocio
458a1fc035 Add details related workflow job on the workflow approval details
Add details related workflow job on the work flow approval details

Remove not used prop isLoading, fix, and expand unit-tests related to
workflow approval details.
2022-05-11 13:32:59 -04:00
Kia Lam
6e87b29e92 Add help text to JT and WJT forms. 2022-05-11 09:10:22 -07:00
Kia Lam
be1d0c525c Add popover text to JT and WJT details pages. 2022-05-11 09:10:21 -07:00
Alex Corey
0787cb4fc2 Merge pull request #12185 from AlexSCorey/8690-SortSchedulesByType
Adds sorting by type on the schedules list
2022-05-11 10:57:10 -04:00
dependabot[bot]
19063a2d90 Bump luxon from 2.0.1 to 2.4.0 in /awx/ui
Bumps [luxon](https://github.com/moment/luxon) from 2.0.1 to 2.4.0.
- [Release notes](https://github.com/moment/luxon/releases)
- [Changelog](https://github.com/moment/luxon/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moment/luxon/compare/2.0.1...2.4.0)

---
updated-dependencies:
- dependency-name: luxon
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-11 14:40:47 +00:00
Alex Corey
e8e2f820d2 Merge pull request #12153 from ansible/dependabot/npm_and_yarn/awx/ui/devel/d3-7.4.4
Bump d3 from 7.1.1 to 7.4.4 in /awx/ui
2022-05-11 10:35:29 -04:00
Alan Rominger
aaad634483 Only use in-memory cache for database settings, set ttl=5 (#12166)
* Only use in-memory cache for database settings

Make necessary adjustments to monkeypatch
  as it is very vunerable to recursion
  Remove migration exception that is now redundant

Clear cache if a setting is changed

* Use dedicated middleware for setting cache stuff
  Clear cache for each request

* Add tests for in-memory cache
2022-05-10 21:58:22 -04:00
dependabot[bot]
dfa4127bae Bump react-error-boundary from 3.1.3 to 3.1.4 in /awx/ui
Bumps [react-error-boundary](https://github.com/bvaughn/react-error-boundary) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/bvaughn/react-error-boundary/releases)
- [Changelog](https://github.com/bvaughn/react-error-boundary/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bvaughn/react-error-boundary/compare/v3.1.3...v3.1.4)

---
updated-dependencies:
- dependency-name: react-error-boundary
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-10 21:14:25 +00:00
Jeff Bradberry
f3725c714a Merge pull request #12119 from kimbernator/devel
Remove hardcoded public schema in cleanup_jobs.py
2022-05-10 17:14:11 -04:00
dependabot[bot]
cef3ed01ac Bump eslint-plugin-i18next from 5.1.2 to 5.2.1 in /awx/ui
Bumps [eslint-plugin-i18next](https://github.com/edvardchen/eslint-plugin-i18next) from 5.1.2 to 5.2.1.
- [Release notes](https://github.com/edvardchen/eslint-plugin-i18next/releases)
- [Changelog](https://github.com/edvardchen/eslint-plugin-i18next/blob/main/CHANGELOG.md)
- [Commits](https://github.com/edvardchen/eslint-plugin-i18next/compare/v5.1.2...v5.2.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-i18next
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-10 21:12:30 +00:00
Alex Corey
fc1a3f46f9 Merge pull request #12154 from ansible/dependabot/npm_and_yarn/awx/ui/devel/patternfly/react-table-4.75.2
Bump @patternfly/react-table from 4.67.19 to 4.75.2 in /awx/ui
2022-05-10 17:10:16 -04:00
Sarabraj Singh
bfa5feb51b Merge pull request #12205 from sarabrajsingh/revert-and-fix-12186
Revert and fix 12186
2022-05-10 15:29:56 -04:00
Sarabraj Singh
4c0813bd69 deleting folder contents using find command 2022-05-10 14:43:27 -04:00
Sarabraj Singh
9b0b0f2a5f Revert "fixing rm -Rf logic to delete contents of folder but leave parent folder intact"
This reverts commit df2d303ab0.
2022-05-10 14:06:09 -04:00
JST
e87c121f8f Merge pull request #12156 from mabashian/large-workflow-crash
Don't repeatedly traverse workflow nodes when finding ancestors
2022-05-10 14:41:49 -03:00
Seth Foster
65dfc424bc Improve help text for import and export 2022-05-10 13:18:40 -04:00
Sarabraj Singh
dfea9cc526 Merge pull request #12186 from sarabrajsingh/bugfix-delete-on-update-11733
fixing rm -Rf logic to delete contents of folder
2022-05-09 16:08:39 -04:00
Rebeccah Hunter
0d97a0364a Merge pull request #12170 from ansible/give_us_the_deets
Update triage_replies give us more info
2022-05-09 15:22:57 -04:00
kialam
1da57a4a12 Merge pull request #12191 from kialam/fix-12188-undefined-wf-approval-list
Fix deleted wf approval node name.
2022-05-09 11:16:21 -07:00
Rebeccah Hunter
b73078e9db Merge pull request #11373 from rebeccahhh/fix-settings_cache_threading_awx
add lock to cachetools usage
2022-05-09 13:56:16 -04:00
Kia Lam
b17f22cd38 Fix unit tests. 2022-05-09 10:55:51 -07:00
Alex Corey
7b225057ce Merge pull request #12198 from AlexSCorey/fixPRLabeler
Prevents the api label from being added to UI only PRs
2022-05-09 13:25:51 -04:00
Alex Corey
8242078c06 Prevents the api label from being added to UI only PRs 2022-05-09 11:17:22 -04:00
John Westcott IV
a86740c3c9 Adding ability to start and plumb splunk instance (#12183) 2022-05-09 09:50:28 -04:00
Kia Lam
cbde56549d Fix deleted wf approval node name. 2022-05-06 13:51:16 -07:00
CWollinger
385a94866c add tooltip for checkbox in DataListToolbar (#12133)
Signed-off-by: CWollinger <CWollinger@web.de>
2022-05-06 16:36:07 -04:00
chris meyers
21972c91dd add lock to cachetools usage
* We observed daphne giving tracebacks when accessing logging settings.
  Originally, configure tower in tower settings was no a suspect because
  daphne is not multi-process. We've had issues with configure tower in
  tower settings and multi-process before. We later learned that Daphne
  is multi-threaded. Configure tower in tower was back to being a
  suspect. We constructed a minimal reproducer to show that multiple
  threads accessing settings can cause the same traceback that we saw in
  daphne. See
  https://gist.github.com/chrismeyersfsu/7aa4bdcf76e435efd617cb078c64d413
  for that recreator. These fixes stop the recreation.
2022-05-06 16:24:36 -04:00
JST
36d3f9afdb Merge pull request #12184 from marshmalien/2912-prefill-playbook
Autopopulate playbook field when there is one resource
2022-05-06 17:18:18 -03:00
Sarabraj Singh
df2d303ab0 fixing rm -Rf logic to delete contents of folder but leave parent folder intact 2022-05-06 15:41:34 -04:00
Alex Corey
05eba350b7 Adds sorting by type on the schedules list. Also adds functionality for bulk_data command to create schedules 2022-05-06 09:45:45 -04:00
Alexandre Bortoluzzi
1e12e12578 style: prettier file 2022-05-06 14:32:54 +02:00
Alexandre Bortoluzzi
bbdab82433 fix: user token list item tests 2022-05-06 14:26:10 +02:00
kialam
f7be6b6423 Remove timezone formatting for date picker entry. (#12163) 2022-05-05 16:46:38 -04:00
Marliana Lara
ba358eaa4f Autopopulate playbook field when there is one resource 2022-05-05 16:12:26 -04:00
JST
162e09972f Merge pull request #12172 from keithjgrant/11869-users-help-text
Add help text to user token detail
2022-05-05 15:35:14 -03:00
JST
2cfccdbe16 Merge pull request #12158 from nixocio/ui_issue_11862
Add help text popovers to /#/credentials details fields
2022-05-05 14:00:15 -03:00
Kersom
434fa7b7be Merge pull request #12161 from nixocio/ui_css_details
Adding popover for details is showing breaking of words
2022-05-05 16:34:49 +03:00
Sarah Akus
2f8bdf1eab Merge pull request #12173 from kialam/fix-12167-unresponsive-datepicker
Upgrade @patternfly/react-core.
2022-05-05 09:16:13 -04:00
Alexandre Bortoluzzi
e1705738a1 fix: french vocabulary 2022-05-05 12:51:35 +02:00
Alexandre Bortoluzzi
4cfb8fe482 feat: display token description on user tokens list page 2022-05-05 12:51:17 +02:00
Hao Liu
d52d2af4b4 change SELinux label for EE volume mount
- The `z` option indicates that the bind mount content is shared among multiple containers.
- The `Z` option indicates that the bind mount content is private and unshared.

If multiple container attempt to mount the same directory `Z` option will cause a raise condition where only the last container started will have access to the file.

Ref: https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label
Signed-off-by: Hao Liu <haoli@redhat.com>
2022-05-04 21:31:34 -04:00
Kia Lam
97fd3832d4 Upgrade @patternfly/react-core. 2022-05-04 14:19:21 -07:00
Keith J. Grant
3cedd0e0bd add help text to user token detail 2022-05-04 13:23:28 -07:00
Rebeccah Hunter
507b1898ce Update triage_replies.md 2022-05-04 15:28:28 -04:00
Kersom
e3fe9010b7 Merge pull request #12152 from ansible/dependabot/npm_and_yarn/awx/ui/devel/testing-library/react-12.1.5
Bump @testing-library/react from 12.1.4 to 12.1.5 in /awx/ui
2022-05-04 20:58:20 +03:00
Kersom
2c350b8b90 Merge pull request #12151 from ansible/dependabot/npm_and_yarn/awx/ui/devel/patternfly/patternfly-4.192.1
Bump @patternfly/patternfly from 4.183.1 to 4.192.1 in /awx/ui
2022-05-04 11:04:25 -04:00
nixocio
d74e258079 Add help text popovers to /#/credentials details fields
Add help text popovers to /#/credentials details fields

See: https://github.com/ansible/awx/issues/11862
2022-05-04 09:29:39 -04:00
nixocio
b03cabd314 Adding popover for details is showing breaking of words
Now that we are adding popovers for details pages, I noticed a couple of
strings wrapping in odd places, update css to avoid that.

Also `word-break: break-word` was deprecated.
2022-05-03 16:54:32 -04:00
Keith Grant
6a63af83c0 Merge pull request #12150 from keithjgrant/add-old-version-message-to-triage-replies
add old version message to triage replies
2022-05-03 11:47:07 -07:00
Alan Rominger
452744b67e Delay update of artifacts and error fields until final job save (#11832)
* Delay update of artifacts until final job save

Save tracebacks from receptor module to callback object

Move receptor traceback check up to be more logical

Use new mock_me fixture to avoid DB call with me method

Update the special runner message to the delay_update pattern

* Move special runner message into post-processing of callback fields
2022-05-03 14:42:50 -04:00
mabashian
703a68d4fe Don't repeatedly traverse workflow nodes when finding ancestors 2022-05-03 13:39:03 -04:00
dependabot[bot]
557893e4b0 Bump @patternfly/react-table from 4.67.19 to 4.75.2 in /awx/ui
Bumps [@patternfly/react-table](https://github.com/patternfly/patternfly-react) from 4.67.19 to 4.75.2.
- [Release notes](https://github.com/patternfly/patternfly-react/releases)
- [Commits](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-table@4.67.19...@patternfly/react-table@4.75.2)

---
updated-dependencies:
- dependency-name: "@patternfly/react-table"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-03 16:39:23 +00:00
dependabot[bot]
d7051fb6ce Bump d3 from 7.1.1 to 7.4.4 in /awx/ui
Bumps [d3](https://github.com/d3/d3) from 7.1.1 to 7.4.4.
- [Release notes](https://github.com/d3/d3/releases)
- [Changelog](https://github.com/d3/d3/blob/main/CHANGES.md)
- [Commits](https://github.com/d3/d3/compare/v7.1.1...v7.4.4)

---
updated-dependencies:
- dependency-name: d3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-03 16:38:37 +00:00
dependabot[bot]
867c50da19 Bump @testing-library/react from 12.1.4 to 12.1.5 in /awx/ui
Bumps [@testing-library/react](https://github.com/testing-library/react-testing-library) from 12.1.4 to 12.1.5.
- [Release notes](https://github.com/testing-library/react-testing-library/releases)
- [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/react-testing-library/compare/v12.1.4...v12.1.5)

---
updated-dependencies:
- dependency-name: "@testing-library/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-03 16:38:14 +00:00
dependabot[bot]
e8d76ec272 Bump @patternfly/patternfly from 4.183.1 to 4.192.1 in /awx/ui
Bumps [@patternfly/patternfly](https://github.com/patternfly/patternfly) from 4.183.1 to 4.192.1.
- [Release notes](https://github.com/patternfly/patternfly/releases)
- [Changelog](https://github.com/patternfly/patternfly/blob/main/RELEASE-NOTES.md)
- [Commits](https://github.com/patternfly/patternfly/compare/prerelease-v4.183.1...prerelease-v4.192.1)

---
updated-dependencies:
- dependency-name: "@patternfly/patternfly"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-03 16:37:37 +00:00
Keith J. Grant
c102c61532 add old version message to triage replies 2022-05-03 08:20:45 -07:00
John Westcott IV
adb2b0da89 Adding standard message for AWX release (#12105) 2022-05-03 09:24:48 -04:00
JST
3610008699 Merge pull request #12145 from marshmalien/4057-project-scm-type-details
Add SCM Type detail to job detail view
2022-05-03 10:09:35 -03:00
kialam
3b44838dde Merge pull request #12146 from nixocio/ui_all
Update dependabot
2022-05-02 14:46:58 -07:00
nixocio
0205d7deab Update dependabot
dependency-type to be direct
2022-05-02 17:15:54 -04:00
Marliana Lara
dd47829bdb Add SCM Type detail to job details 2022-05-02 16:25:46 -04:00
JST
e7e72d13a9 Merge pull request #12137 from keithjgrant/10831-inventory-source-project-validation
remove incorrect form error message in inv source
2022-05-02 17:00:15 -03:00
kialam
4bbdf1ec8a Merge pull request #12138 from kialam/add-directory-dependabot
Add directory destination to dependabot yaml file
2022-05-02 12:30:53 -07:00
Kia Lam
4596df449e Add directory. 2022-05-02 12:07:50 -07:00
Kersom
ecbb636ba1 Merge pull request #12136 from nixocio/ui_fix_css_schedules
Align items on schedule form
2022-05-02 14:29:57 -04:00
Keith J. Grant
e3aed9dad4 remove incorrect form error message in inv source 2022-05-02 10:34:33 -07:00
JST
213983a322 Merge pull request #12078 from AlexSCorey/12058-CleanUpReactWarnings
Cleans up some console warnings.
2022-05-02 13:13:20 -03:00
nixocio
2977084787 Align items on schedule form
Align items on schedule form
2022-05-02 11:11:34 -04:00
Sarah Akus
b6362a63cc Merge pull request #12134 from ansible/add-deleted-inventory-locator-for-JT-detail
add new locator for deleted inventory in JT detail screen
2022-04-29 16:18:45 -04:00
akus062381
7517ba820b add new locator for deleted inventory 2022-04-29 15:57:32 -04:00
Alan Rominger
29d60844a8 Fix notification timing issue by sending in the latter of 2 events (#12110)
* Track host_status_counts and use that to process notifications

* Remove now unused setting

* Back out changes to callback class not needed after all

* Skirt the need for duck typing by leaning on the cached field

* Delete tests for deleted task

* Revert "Back out changes to callback class not needed after all"

This reverts commit 3b8ae350d218991d42bffd65ce4baac6f41926b2.

* Directly hardcode stats_event_type for callback class

* Fire notifications if stats event was never sent

* Remove test content for deleted methods

* Add placeholder for when no hosts matched

* Make field default be None, denote events processed with empty dict

* Make UI process null value for host_status_counts

* Fix tracking of EOF dispatch for system jobs

* Reorganize EVENT_MAP into class properties

* Consolidate conditional I missed from EVENT_MAP refactor

* Give up on the null condition, also applies for empty hosts

* Remove cls position argument not being used

* Move wrapup method out of class, add tests
2022-04-29 13:54:31 -04:00
Alex Corey
41b0607d7e Merge pull request #12108 from marshmalien/org-host-credTypes-helpText
Add organization, host, and credential type detail view help text
2022-04-29 13:13:41 -04:00
John Westcott IV
13f7166a30 Fixing write location of ssh_key-data-cert.pub (#12122) 2022-04-29 12:22:09 -04:00
Sarah Akus
0cc9b84ead Merge pull request #11998 from mabashian/344-host-count
Adds total host count to inv and smart inv details views
2022-04-29 10:37:26 -04:00
JST
68ee4311bf Merge pull request #12128 from mabashian/11990-schedule-prompt-tags-v2
Add tags/skip tags to the list of things that will cause the Prompt button to be displayed on the schedule form
2022-04-28 17:23:13 -03:00
Alex Corey
6e6c3f676e Merge pull request #12120 from AlexSCorey/addDependabot
Add dependabot for ui
2022-04-28 15:43:03 -04:00
John Westcott IV
c67f50831b Modifying schedules API to allow for rrulesets #5733 (#12043)
* Added schedule_rruleset lookup plugin for awx.awx
* Added DB migration for rrule size
* Updated schedule docs
* The schedule API endpoint will now return an array of errors on rule validation to try and inform the user of all errors instead of just the first
2022-04-28 15:38:20 -04:00
Alex Corey
50ef234bd6 Update .github/dependabot.yml
Co-authored-by: Marliana Lara <marliana.lara@gmail.com>
2022-04-28 15:14:08 -04:00
Jeff Bradberry
2bef5ce09b Merge pull request #12099 from jbradberry/add-content-type-option-header
Add the X-Content-Type-Options nosniff header
2022-04-28 14:41:02 -04:00
Seth Foster
a49c4796f4 Merge pull request #12115 from sean-m-sullivan/workflow_node_updates
update workflow nodes to allow workflows and system jobs
2022-04-28 14:12:33 -04:00
Seth Foster
9eab9586e5 Merge pull request #12114 from sean-m-sullivan/awx_collection_alias
update awx collection workflow module
2022-04-28 13:42:30 -04:00
mabashian
cd35787a86 Adds total host count to inv and smart inv details views 2022-04-28 11:40:27 -04:00
mabashian
cbe84ff4f3 Add tags/skip tags to the list of things that will cause the Prompt button to be displayed on the schedule form 2022-04-28 11:33:46 -04:00
Alex Corey
410f38eccf add dependabot for ui 2022-04-28 09:30:54 -04:00
Sarah Akus
b885fc2d86 Merge pull request #12123 from marshmalien/12109-fix-user-role-association
Fix user role association in access modal
2022-04-27 19:23:53 -04:00
JST
4c93f5794a Merge pull request #12098 from nixocio/ui_work_flow
Fix broken job WFJT details when related JT is deleted
2022-04-27 17:47:28 -03:00
sean-m-sullivan
456bb75dcb update awx collection workflow module 2022-04-27 16:32:37 -04:00
sean-m-sullivan
02fd8b0d20 update workflow nodes 2022-04-27 16:18:00 -04:00
Marliana Lara
fbe6c80f86 Fix user role association in access modal 2022-04-27 16:01:15 -04:00
Jeremy Kimber
3d5f302d10 remove hardcoded public schema in cleanup_jobs.py 2022-04-27 12:45:15 -05:00
Sarah Akus
856a2c1734 Merge pull request #12107 from keithjgrant/12101-job-output-single-item-pagination
fix off-by-one error in job output pagination
2022-04-27 10:43:20 -04:00
John Westcott IV
4277b73438 Adding /etc/supervisord.conf to sosreports (#12104) 2022-04-27 10:34:45 -04:00
Alex Corey
2888f9f8d0 Cleans up some console warnings. 2022-04-26 17:17:41 -04:00
Jeff Bradberry
68221cdcbe Merge pull request #12106 from jbradberry/django-bump
Bump Django to 3.2.13
2022-04-26 15:07:52 -04:00
Sean Sullivan
f50501cc2a update awx.awx collection to allow remote project. (#12093) 2022-04-26 15:07:29 -04:00
Marliana Lara
c84fac65e0 Add organization, host, and credential type detail view help text. 2022-04-26 11:50:36 -04:00
Jeff Bradberry
d64c457b3d Bump Django to 3.2.13 2022-04-26 10:34:28 -04:00
Keith J. Grant
1bd5a880dc fix off-by-one error in job output pagination 2022-04-25 13:09:44 -07:00
Jeff Bradberry
47d5a89f40 Add the X-Content-Type-Options nosniff header 2022-04-25 13:45:16 -04:00
nixocio
6060e7e29f Fix broken job WFJT details when related JT is deleted
Fix broken job WFJT details when related JT is deleted
2022-04-25 12:33:12 -04:00
Christian Adams
677187a43e Merge pull request #12096 from rooftopcellist/localization-devel-4-24
Localization Update & Add KO to supported languages
2022-04-25 10:24:49 -04:00
Christian M. Adams
972cb82d16 Fix Localization syntax errors 2022-04-24 01:18:37 -04:00
Christian M. Adams
3102df0bf6 Update Localization Strings & Add KO 2022-04-24 00:52:12 -04:00
Alan Rominger
cb63d92bbf Remove committed_capacity field, delete supporting code (#12086)
* Remove committed_capacity field, delete supporting code

* Track consumed capacity to solve the negatives problem

* Use more verbose name for IG queryset
2022-04-22 13:41:32 -04:00
John Westcott IV
c43424ed09 Refactoring release_process docs and updating images (#11981) 2022-04-22 12:42:12 -04:00
John Westcott IV
a0ccc8c925 Merge pull request #5784 from ansible/runner_changes_42 (#12083) 2022-04-22 10:46:35 -04:00
Sarah Akus
47160f0118 Merge pull request #12067 from ansible/dependabot/npm_and_yarn/awx/ui/minimist-1.2.6
Bump minimist from 1.2.5 to 1.2.6 in /awx/ui
2022-04-22 09:54:38 -04:00
Alan Rominger
44f0609314 Merge pull request #11996 from AlanCoding/blockhead
Remove unnecessary blocks from project update playbook
2022-04-21 13:58:48 -04:00
Elijah DeLee
689a216726 move static methods used by task manager (#12050)
* move static methods used by task manager

These static methods were being used to act on Instance-like objects
that were SimpleNamespace objects with the necessary attributes.

This change introduces dedicated classes to replace the SimpleNamespace
objects and moves the formerlly staticmethods to a place where they are
more relevant instead of tacked onto models to which they were only
loosly related.

Accept in-memory data structure in init methods for tests

* initialize remaining capacity AFTER we built map of instances
2022-04-21 13:05:06 -04:00
Alan Rominger
4b45148614 Merge pull request #12016 from Ladas/analytics_collector_should_collect_full_license_data
Analytics collector should collect full license data
2022-04-21 11:12:33 -04:00
Alan Rominger
c84e603ac5 Remove unnecessary blocks from project update playbook 2022-04-21 10:04:14 -04:00
Kersom
c7049e1a0e Merge pull request #12077 from nixocio/ui_fix_typo
Update strings
2022-04-21 08:48:33 -04:00
nixocio
0b4c3e3046 Update strings
Update strings
2022-04-20 14:51:08 -04:00
Sarah Akus
8a5fd11506 Merge pull request #12062 from nixocio/ui_issue_11770
Fix notification template details for system auditors
2022-04-20 14:14:43 -04:00
Alan Rominger
b565038fdf Merge pull request #12066 from AlanCoding/resolved_role
Ship the resolved_role event data to analytics
2022-04-20 11:00:21 -04:00
Keith Grant
526b1e692a remove output/stderr tabs from host detail modals when not present (#12064) 2022-04-19 17:17:37 -04:00
Seth Foster
c93155132a Merge pull request #12031 from fosterseth/awxkit_import_more_verbose_error
awxkit log which resource failed to import
2022-04-19 15:44:37 -04:00
Alex Corey
ae7960e9d7 Adds popover help text to project details, and unifies those strings (used in the form and the details view) into 1 file (#12039) 2022-04-19 14:35:51 -04:00
Jeff Bradberry
3a1268de1e Merge pull request #12068 from jbradberry/fix-event-partition-alignment-devel
Fix the job event partition alignment
2022-04-19 10:36:48 -04:00
Alex Corey
10042df309 Merge pull request #12069 from nixocio/ui_fix_code_details
Fix rows type for CodeDetails
2022-04-19 10:01:27 -04:00
Alan Rominger
2530ada9d7 Bump analytics event_table version 2022-04-18 16:49:53 -04:00
Jeff Bradberry
11890f0eee Fix the job event partition alignment
it really should be always aligned to the hour, so that real job
events don't slip through the cracks.
2022-04-18 14:54:06 -04:00
nixocio
5cb3f31df0 Fix rows type for CodeDetails
Fix rows type for CodeDetails
2022-04-18 14:42:51 -04:00
dependabot[bot]
ac0624236e Bump minimist from 1.2.5 to 1.2.6 in /awx/ui
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-18 18:41:38 +00:00
nixocio
13eb174c9f Fix notification template details for system auditors
Fix notification template details for system auditors

See: https://github.com/ansible/awx/issues/11770
2022-04-18 14:02:44 -04:00
Rebeccah Hunter
a3e29317c5 default saved replies for triages (#12047)
* create a singular page with listed replies that can be copy and pasted for mailing list and bug scrub purposes

Co-authored-by: Alicia Cozine <879121+acozine@users.noreply.github.com>
2022-04-18 16:28:22 +00:00
Alan Rominger
75d7cb5bca Merge pull request #11989 from AlanCoding/deprecate_uopu
Mark inventory source field for deprecation
2022-04-18 11:59:05 -04:00
Alan Rominger
9059dce8af Merge pull request #12041 from AlanCoding/commitment_problems
Mark committed_capacity field for removal
2022-04-18 11:58:47 -04:00
Alan Rominger
1676c02611 Ship the resolved_role event data to analytics 2022-04-18 11:42:19 -04:00
Kersom
86a888f0d0 Merge pull request #12063 from nixocio/ui_remove_dupe_css
Remove duplicate CSS rules
2022-04-14 16:11:18 -04:00
nixocio
816652a8e2 Remove duplicate CSS rules
Remove duplicate CSS rules
2022-04-14 15:19:29 -04:00
Sarah Akus
c1817ab19e Merge pull request #12048 from nixocio/ui_issue_12046
Disable isCreatable on Advanced Search
2022-04-14 15:01:46 -04:00
Sarah Akus
b2dcc0d7e9 Merge pull request #12029 from nixocio/ui_issue_12008
Update when deleted is shown on job details
2022-04-14 14:44:13 -04:00
Shane McDonald
ba5361b25e Merge pull request #12056 from anxstj/doc_ansible_runner
Update file path in docs/ansible_runner_integration.md
2022-04-14 12:24:07 -04:00
Amol Gautam
ae826ed19d Merge pull request #12021 from amolgautam25/ctit_db
removed 'check_migrations' condition in _citi_db_wrapper
2022-04-14 08:59:48 -07:00
Elijah DeLee
e24fc43a45 Revert "Only fetch fields we need in task manager"
This reverts commit 868e811b3f.

Turns out this does not play well with polymorphic models.

Will try again with .defer()
2022-04-14 11:55:33 -04:00
Stefan Jakobs
b719e5771c Update file path 2022-04-14 17:31:10 +02:00
Shane McDonald
778862fe51 Merge pull request #12054 from shanemcd/new-autoreloader
Alternative code reloader for dev env
2022-04-14 11:18:13 -04:00
Shane McDonald
30d185a67f Make dev env reload faster 2022-04-14 10:40:07 -04:00
Shane McDonald
89c2a4c6ed Alternative code reloader for dev env
I verified what Seth found in https://github.com/ansible/awx/pull/12052, but would really hate to lose this functionality. Curious if folks on the API team can try this and see if it works for them.
2022-04-14 09:42:17 -04:00
Elijah DeLee
868e811b3f Only fetch fields we need in task manager
By using .only we select fewer columns, avoiding potentially large
fields that we never reference.

Also, small tweak to eliminate what was a duplicate dictionary of
hostname:instance, because we don't need build and carry two copies of
the same data.
2022-04-13 17:24:33 -04:00
nixocio
f6496c28fe Disable isCreatable on Advanced Search
Disable isCreatable on Advanced Search

See: https://github.com/ansible/awx/issues/12046
2022-04-13 15:34:13 -04:00
Sarah Akus
81cda0ba74 Merge pull request #12038 from keithjgrant/survey-array
Add array support to survey multiple choice questions
2022-04-13 15:00:49 -04:00
Elijah DeLee
2e9974133a calculate remaining capacity in static method
this is to avoid additional queries when we allready have all
the active jobs fetched in the task manager
2022-04-13 11:56:07 -04:00
Sarah Akus
49051c4aaf Merge pull request #12026 from AlexSCorey/11396-ofWordTranslation
Fixes pagination translation failure
2022-04-13 11:43:05 -04:00
Kersom
e2a89ad8a2 Add saved replies dir and default reply (#12028)
Add saved replies dir and default reply
2022-04-13 10:59:18 -04:00
Keith J. Grant
f4b0bd68bd add tests for array/string survey multi-select 2022-04-12 15:14:09 -07:00
Alan Rominger
5a304db840 Mark inventory source field for deprecation 2022-04-12 16:24:35 -04:00
Alan Rominger
e3044298bf Mark committed_capacity field for removal 2022-04-12 16:18:05 -04:00
John Mitchell
bbb9770a97 change back to Automation Analytics name (#12022) 2022-04-12 14:23:13 -04:00
Elijah DeLee
4328b4cb67 drop call that queries all running and waiting jobs
this is to fix one more place in the task manager where we end up
querying all running and waiting jobs.

Partial fix for https://github.com/ansible/awx/issues/11671
2022-04-12 10:31:47 -04:00
Keith J. Grant
a324753180 support survey choices in array format 2022-04-11 14:28:01 -07:00
Seth Foster
1462af61b0 awxkit log which resource failed to import 2022-04-11 17:03:13 -04:00
Alex Corey
8478a0f70b Fixes pagination translation failure 2022-04-11 14:45:11 -04:00
nixocio
8288655b30 Update when deleted is shown on job details
Update when deleted is show on job details.

Some job types should not display inventory or projects, update when
showing those fields.

Also, update when displaying information when
those fields where deleted.

See: https://github.com/ansible/awx/issues/12008
2022-04-11 14:20:42 -04:00
Rebeccah Hunter
ac8204427e Merge pull request #11914 from ansible/instances_list_filtering
add ID as default filter if no other filtering criteria is provided as well as some tests that should cover order integrity for future scenarios
2022-04-08 18:24:41 -04:00
Rebeccah
f6b8ce18d0 I don't think these tests actually add anything, so I am removing them even though I wrote them in the first place. 2022-04-08 18:04:34 -04:00
Amol Gautam
dc42946ff3 Removed migration check conditions in citi_db_wrapper 2022-04-08 17:53:02 -04:00
Rebeccah
44cc934c2b add projects to test that ordering functions correctly and when it gets a value it cannot order by it falls back to ID
add tests that check ordering for projects, organizations, inventories, groups, and hosts
2022-04-08 17:18:57 -04:00
Rebeccah
933956eccb have instances be filtered by ID in case of no filtering criteria passed in
and then switch from using order by ID as a fallback for all ordering and instead
just set instances ordering to ID as default to prevent
OrderedManyToMany fields ordering from being interrupted.
2022-04-08 17:01:58 -04:00
Kersom
27dc8caabd Do not truncate strings on activity stream dropdown (#12020)
Do not truncate strings on activity stream dropdown

See: https://github.com/ansible/awx/issues/11399
2022-04-08 16:45:32 -04:00
Sarah Akus
4b98df237e Merge pull request #12009 from nixocio/ui_issue_12006
Do not show inventory for project update on job details
2022-04-08 15:12:19 -04:00
Sarah Akus
0fa3ca8dc0 Merge pull request #12007 from marshmalien/11778-search-labels-placeholder
Add placeholder text when user selects a fuzzy search on labels
2022-04-08 14:48:05 -04:00
Kersom
0712affa9b Escape name__regex and name__iregex (#11964)
Escape name__regex and name__iregex. Escaping the value for those
keys when creating a smart inventory is a work around for the
pyparsing code on the API side for special characters. This will just
display an extra escape when showing the host_filter on details page.
2022-04-08 13:08:32 -04:00
Sarah Akus
b646aa03f8 Merge pull request #11920 from AlexSCorey/5210-t-WorkflowApprovalListRefactor
Improves UX of workflow approval list
2022-04-08 12:07:35 -04:00
Alex Corey
4beea35d9e Refactors workflow approval list toolbar and details acttions to add clarity. 2022-04-08 10:34:44 -04:00
Kersom
e8948a9d6e Merge pull request #12004 from nixocio/ui_downgrade_node
Downgrade min required node LTS
2022-04-07 15:33:44 -04:00
nixocio
28f25d5aba Downgrade min required node LTS
Downgrade min required node LTS
2022-04-07 14:56:52 -04:00
Keith Grant
7cbb783b2c Use new children-summary endpoint data to traverse job event tree (#11944)
* use new children-summary endpoint data to traverse job event tree

* update job output tests for new children summary data

* force flat mode if event child summary fails to load

* update childrenSummary data for endpoint changes

* don't add jobs to job tree until children summary loaded

* force job output into flat mode if job processing not complete
2022-04-06 13:10:04 -04:00
Ladislav Smola
1793f94f27 Analytics collector should collect full license data
Analytics collector should collect full license data
2022-04-06 14:09:19 +02:00
nixocio
0b7c9cd8ad Do not show inventory for project update on job details
Do not show inventory for project update on job details

See: https://github.com/ansible/awx/issues/12006
2022-04-05 13:26:19 -04:00
Marliana Lara
51b5b78084 Add placeholder text when user selects a fuzzy search on labels 2022-04-05 12:56:40 -04:00
Satoe Imaishi
bea924ddc6 Merge pull request #11983 from simaishi/update_cryptography
Update cryptography to >=35 for openssl 3 support
2022-04-05 17:09:46 +09:00
Sarah Akus
b5fcc6e541 Merge pull request #11963 from AlexSCorey/11467-RevertDraagandDrop
Revert "updated patternfly"
2022-04-04 21:44:08 -04:00
Alex Corey
ffb46fec52 Fixes test failure 2022-04-04 21:28:18 -04:00
Alex Corey
4190cf126c Reverts the code from 8b47106c63d7081b0cd9450694427ca9e92b2815 while keeping the depenedency upgrade 2022-04-04 21:16:43 -04:00
Seth Foster
58721098d5 Merge pull request #11928 from fosterseth/job_event_children_summary
Add JobJobEventsChildrenSummary endpoint
2022-04-04 17:23:28 -04:00
Seth Foster
cfd6df7a3b Add JobJobEventsChildrenSummary endpoint
- returns a special view to output the total number of children (and
grandchildren) events for all parents events for a job
value is the number of total children of that event
- intended to be consumed by the UI, as an efficient way to get the
number of children for a particular event
- see api/templates/api/job_job_events_children_summary.md for more info
2022-04-04 14:25:18 -04:00
Björn Pedersen
9f6fa4cf97 Grafana notifications: Fix panel/dashboardId type (#11083)
* Grafana notifications: Fix panel/dashboardId type

Latest grafana fails with
  Error sending notification grafana: 400
  [{"classification":"DeserializationError",
    "message":"json: cannot unmarshal string into Go struct
        field PostAnnotationsCmd.dashboardId of type int64"}]

So ensure the IDs are really int and not strings.

* Fix the dashboard/panelId=0 case

0 is avlaid valid for the ID's, so ensure to allow them.

* Update tests to new behavior

Panel/Dashboard Id fields are not sent if they where not requested.
Alos add tests for the ID=0 case.
2022-04-01 16:08:01 -04:00
Alan Rominger
7822da03fb Merge pull request #11865 from AlanCoding/galaxy_task_env
Add user-defined environment variables to ansible-galaxy commands
2022-04-01 15:24:54 -04:00
Alan Rominger
58cb3d5bdc Change indent to standard pattern 2022-04-01 13:46:00 -04:00
Sarah Akus
a3c97a51be Merge pull request #11988 from nixocio/ui_issue_11982
Fix notification template details
2022-04-01 13:40:02 -04:00
Elijah DeLee
202dc00f4c cast bool to str for runner env
It appears this was causing a fatal error for runner
2022-04-01 13:37:36 -04:00
Satoe Imaishi
309e58b6d7 Update cryptography to >=35 for openssl 3 support 2022-04-01 00:29:57 -04:00
Sarah Akus
34b20e26fa Merge pull request #11939 from marshmalien/8474-output-search-clear-all
Fix search toolbar clear all filters
2022-03-31 15:41:56 -04:00
Marliana Lara
1de2487e8f Fix search toolbar clear all filters 2022-03-31 13:52:56 -04:00
Sarah Akus
8d95b72527 Merge pull request #11846 from AlexSCorey/11203-WFToolbarIssues
Fixes Workflow visualizer toolbar disappearing.
2022-03-31 12:35:38 -04:00
nixocio
a920c9cc20 Fix notification template details
Fix notification template details

See: https://github.com/ansible/awx/issues/11982
2022-03-31 11:12:00 -04:00
Alex Corey
427f6d1687 Merge pull request #11791 from AlexSCorey/11713-PreventDisassociateHybridNodeFromControlplan
Prevents disassociate hybrid node on controlplane instance group
2022-03-31 10:34:21 -04:00
Alex Corey
dc64168ed4 Disallows disassociate of hubrid type instances from controlplane instance group
Introduce new pattern for is_valid_removal

Makes disassociate error message a bit more dynamic
2022-03-30 17:24:24 -04:00
Alan Rominger
4b913a0ae8 Merge pull request #11980 from AlanCoding/provision_cleanup
Delete dead code from get_or_register, move, and test
2022-03-30 15:44:44 -04:00
Kersom
dac26e5e91 Merge pull request #11979 from nixocio/ui_move_boolean
Move AWX_MOUNT_ISOLATED_PATHS_ON_K8S to be closer to other booleans
2022-03-30 14:14:40 -04:00
Alan Rominger
6c56f2b35b Delete dead code from get_or_register, move, and test 2022-03-30 13:35:42 -04:00
nixocio
3b1a626fa9 Move AWX_MOUNT_ISOLATED_PATHS_ON_K8S to be closer to other booleans
Move AWX_MOUNT_ISOLATED_PATHS_ON_K8S to be closer to other booleans on
the layout.
2022-03-30 13:27:20 -04:00
Shane McDonald
35907fdf51 Merge pull request #11977 from shanemcd/handle-missing-devel-images
Tweaks to devel_images workflow
2022-03-30 09:45:35 -04:00
Shane McDonald
3513956cd6 Merge pull request #11972 from JoelKle/patch-1
[bugfix] credential_plugin tss.py (Thycotic Secret Server) return only value of secret
2022-03-30 09:33:54 -04:00
Shane McDonald
3ed65ce39e Only run devel_images workflow for devel branch in awx repo 2022-03-30 09:24:22 -04:00
Alan Rominger
73e02e745a Patches to make jobs robust to database restarts (#11905)
* Simple patches to make jobs robust to database restarts

* Add some wait time before retrying loop due to DB error

* Apply dispatcher downtime setting to job updates, fix dispatcher bug

This resolves a bug where the pg_is_down property
  never had the right value
  the loop is normally stuck in the conn.events() iterator
  so it never recognized successful database interactions
  this lead to serial database outages terminating jobs

New setting for allowable PG downtime is shared with task code
  any calls to update_model will use _max_attempts parameter
  to make it align with the patience time that the dispatcher
  respects when consuming new events

* To avoid restart loops, handle DB errors on startup with prejudice

* If reconnect consistently fails, exit with non-zero code
2022-03-30 09:14:20 -04:00
Shane McDonald
91df8ab0f7 Do not fail devel_images workflow if initial images are missing 2022-03-30 09:10:50 -04:00
Shane McDonald
ef0f6ca248 Merge pull request #11955 from shanemcd/fail-better
Increase resiliency when application crashes
2022-03-30 08:58:26 -04:00
Satoe Imaishi
4ecce81c51 Merge pull request #11971 from simaishi/add_setuptools_scm_toml
Add setuptools_scm[toml] and pkgconfig to requirements file
2022-03-30 06:51:18 +09:00
Satoe Imaishi
823e4cb11a Add license files for pkgconfig, setuptools-scm and tomli 2022-03-29 16:57:12 -04:00
Alan Rominger
28fa90e9e5 Only allow provision_instances without options to be used on k8s 2022-03-29 16:24:06 -04:00
Alan Rominger
3d22c8ae91 Merge pull request #11968 from AlanCoding/cleanup_tweaks
Minor tweaks to ansible-runner cleanup task arguments
2022-03-29 15:00:33 -04:00
John Westcott IV
e2135b8d68 Collection meta runtime updates (#11952)
* Update runtime.yml
* Extending test_completness to include meta/runtime.yml and adding remaining missing modules from runtime.yml

Co-authored-by: quasd <quasd@users.noreply.github.com>
2022-03-29 14:24:06 -04:00
Alan Rominger
fe5736dc7f Specifically abort the reaper if instance not registered 2022-03-29 14:08:58 -04:00
Shane McDonald
b36af5dfb3 Update help text for provision_instance command 2022-03-29 14:08:58 -04:00
Shane McDonald
4446434e5b Ensure stop signals are forwarded to the correct processes 2022-03-29 14:08:56 -04:00
Shane McDonald
39905b33cd Replace tini with dumb-init
dumb-init is more actively maintained, available on pypi, and already used for both upstream and downstream EEs
2022-03-29 14:08:09 -04:00
Shane McDonald
dbdc529d4a Fix race condition causing rsyslog to crash 2022-03-29 14:08:07 -04:00
Shane McDonald
0cbc802cf4 Use the same settings on each supervisor entry
I didnt see a reason for the weird inconsistencies here.
2022-03-29 14:07:54 -04:00
Shane McDonald
b04747676c Provision the instance before booting anything
There was a race condition because the callback reciever tried to run this code:

  File "/awx_devel/awx/main/management/commands/run_callback_receiver.py", line 31, in handle
    CallbackBrokerWorker(),
  File "/awx_devel/awx/main/dispatch/worker/callback.py", line 49, in __init__
    self.subsystem_metrics = s_metrics.Metrics(auto_pipe_execute=False)
  File "/awx_devel/awx/main/analytics/subsystem_metrics.py", line 156, in __init__
    self.instance_name = Instance.objects.me().hostname

Before get_or_register was being called by the dispatcher.
2022-03-29 14:07:49 -04:00
Alex Corey
5297a87ad4 Merge pull request #11970 from jtmelhorn/devel
Joboutput Search: Put Event Dropdown Options in Alpha Order #11807
2022-03-29 13:10:25 -04:00
nixocio
be6657239d Add UI changes to JobsEdit
Add UI changes to JobsEdit
2022-03-29 10:25:29 -04:00
Alan Rominger
0caf263508 yaml cleanup 2022-03-29 09:57:40 -04:00
Alan Rominger
c77667788a Add user-defined environment variables to ansible-galaxy commands 2022-03-29 09:57:40 -04:00
Joel
bd907425a9 return only value of secret 2022-03-29 10:33:53 +02:00
Satoe Imaishi
229ed53c0e Add setuptools_scm[toml] and pkgconfig, xmlsec's build dep 2022-03-29 01:57:44 -04:00
Alan Rominger
f17ceca7a0 Add in default value to unit tests 2022-03-28 22:39:59 -04:00
Alan Rominger
deac08ba8a Add regression test for overly agressive cleanup behavior 2022-03-28 22:23:33 -04:00
Seth Foster
e0082f4c76 Merge pull request #11945 from fosterseth/fix_create_partition_already_exists_error
Handle error for create_partition
2022-03-28 18:13:29 -04:00
Justin
bed0443b18 Joboutput Search: Put Event Dropdown Options in Alpha Order #11807
Put Event Options in Alpha order.

Signed-off-by: Justin Melhorn <jtmelhorn@gmail.com>
2022-03-28 16:50:44 -04:00
Seth Foster
24152555c5 Handle error for create_partition
Occasionally the create_partition will error with,
relation "main_projectupdateevent_20220323_19" already exists

This change wraps the db command into a try except block with its
own transaction
2022-03-28 16:37:50 -04:00
Amol Gautam
56f51eebce Merge pull request #11956 from amolgautam25/credential_plugin
setting environment variables for credential plugins
2022-03-28 13:02:19 -04:00
Jeff Bradberry
6c1adade25 Merge pull request #11947 from jbradberry/django-3.2-upgrade
Remove the out-of-band JSONField migration
2022-03-28 12:02:53 -04:00
kialam
ec5e677635 Merge pull request #11938 from kialam/mesh-viz-unit-tests
Mesh viz unit tests
2022-03-28 08:44:19 -07:00
Alex Corey
327cae056e Merge pull request #11829 from AlexSCorey/11478-StartofJobOutputDevDocs
Adds outline for JobOutput documentation.
2022-03-28 11:22:21 -04:00
Alex Corey
7a11470817 Adds outline for JobOutput documentation. 2022-03-28 10:58:05 -04:00
Alex Corey
efb01f3c36 Fixes Workflow visualizer toolbar disappearing. 2022-03-28 10:55:23 -04:00
Alan Rominger
85ec83c3fd Minor tweaks to ansible-runner cleanup task arguments 2022-03-28 10:52:09 -04:00
Alex Corey
1679102204 Merge pull request #11946 from nixocio/ui_cred_type
Add credential type filter
2022-03-28 10:03:56 -04:00
Kersom
7601531d82 Merge pull request #11965 from nixocio/ui_b_style
Small style update
2022-03-28 10:02:59 -04:00
Sarah Akus
56ab1c2f0a Merge pull request #11958 from AlexSCorey/UpdatesPF
Updates PF to bring in the DrownActionToggle component
2022-03-25 20:27:25 -04:00
nixocio
f309054637 Small style update
Small style update to make a bit more consistent.
2022-03-25 15:39:22 -04:00
Amol Gautam
8efed4ef62 Adding awx_task_env as wrapper while invoking backend 2022-03-25 10:16:30 -04:00
Shane McDonald
e4c85a5790 Merge pull request #11957 from lucas-benedito/fix_hardcode_tmp_models_ha
fixed hardcode tmp ha.py
2022-03-25 09:57:02 -04:00
lucas-benedito
8af2214979 Merge branch 'ansible:devel' into fix_hardcode_tmp_models_ha 2022-03-25 14:28:29 +01:00
Lucas Dias
01ce3440eb added os.path and module import 2022-03-25 14:26:00 +01:00
Shane McDonald
b6573ec2e2 Merge pull request #11961 from shanemcd/respect-system-tmp
Respect system configured tmp directory
2022-03-25 08:13:53 -04:00
Jeff Bradberry
d54838cd94 Remove the out-of-band migration
that was turning all old JSONFields into a jsonb type database column.
The use of JSONBlob makes this unnecessary.
2022-03-24 15:21:59 -04:00
Jeff Bradberry
e3f3ab224a Replace all previously text-based json fields with JSONBlob
This JSONBlob field type is a wrapper around Django's new generic
JSONField, but with the database column type forced to be text.  This
should behave close enough to our old wrapper around
django-jsonfield's JSONField and will avoid needing to do the
out-of-band database migration.
2022-03-24 15:21:54 -04:00
Shane McDonald
c06ced93f7 Merge pull request #11933 from AlanCoding/settingify
Add setting for notification job status retry loop
2022-03-24 13:55:39 -04:00
Shane McDonald
ea59e895af Respect system configured tmp directory 2022-03-24 13:51:02 -04:00
Alex Corey
fb7a8dfd16 Updates PF to bring in the DrownActionToggle component 2022-03-24 13:17:25 -04:00
Lucas Dias
18b1440d7c fixed hardcode tmp ha.py 2022-03-24 17:59:43 +01:00
John Westcott IV
593eebf062 Adding awx_ as well as tower_ variable names for webhooks (#11925)
Adding utility to ease testing webhooks from command line
Modifying all variables to use a constants list of variable names
2022-03-24 11:58:15 -04:00
John Westcott IV
fcdff8bdfb Fixing pre-commit.sh for OS X (#11953) 2022-03-24 11:39:29 -04:00
John Westcott IV
b9cdd6f2c8 Adding ability to run user level pre-commit hooks (#11923)
* Adding ability to run user level pre-commit hooks
* Adding pre-commit docs in CONTRIBUTING.md
2022-03-24 10:58:14 -04:00
Shane McDonald
270497eda1 Kill all control plane processes if one of them fails to boot 2022-03-23 18:40:23 -04:00
Shane McDonald
dbcdb825b0 Remove awx-config-watcher from kube dev env 2022-03-23 18:37:16 -04:00
nixocio
6c28f4b204 Add credential type filter
Add credential type filter

See: https://github.com/ansible/awx/issues/11930
2022-03-23 16:44:50 -04:00
Shane McDonald
7b2b979c1b Merge pull request #11941 from shanemcd/update-devel-image-refs
Update some references to our development images
2022-03-23 15:57:18 -04:00
Shane McDonald
e87c9d8811 Fix command in build_awx_image.md 2022-03-23 15:40:49 -04:00
Alex Corey
7d04737a65 Merge pull request #11934 from mabashian/5707-proj-field-label
Fix Source Control Type label in project form
2022-03-23 11:32:30 -04:00
Shane McDonald
99056e3697 Update some references to our development images 2022-03-23 11:31:11 -04:00
Shane McDonald
c110101cb1 Merge pull request #11787 from liortamari/hashicorp-vault-kubernetes-auth
Add Hashicorp Vault Kubernetes authentication method
2022-03-23 11:02:38 -04:00
Shane McDonald
aa6129fda0 Merge pull request #11932 from shanemcd/gha-devel-images
Migrate all development image builds to GHA
2022-03-23 10:28:48 -04:00
Shane McDonald
1d181757e8 Migrate all development image builds to GHA
- This also moves the development image from quay.io to ghcr.io.
- These changes will need to be backported to all of our supported branches.
2022-03-23 10:03:55 -04:00
Sarah Akus
4fa8b6ded8 Merge pull request #11788 from AlexSCorey/10281-OutputHostFilters
Fixes search drop down items for job output search
2022-03-23 09:45:01 -04:00
Alex Corey
79afdfd1a6 Fixes search drop down items for job output search 2022-03-23 09:26:49 -04:00
Kia Lam
7702abb368 Add unit tests for Topology View. 2022-03-22 15:31:27 -07:00
Shane McDonald
3d6a49ce7c Merge pull request #11937 from ansible/shanemcd-patch-1
Stop adding needs_triage label every time an issue is edited
2022-03-22 14:04:46 -04:00
Shane McDonald
f823049f55 Stop adding needs_triage label every time an issue is edited 2022-03-22 13:08:34 -04:00
Seth Foster
b608b73110 Merge pull request #11927 from fosterseth/fix_subsystem_metrics_sync_in_async
Fix subsystem metrics sync-only operation in async context
2022-03-22 11:55:05 -04:00
mabashian
12c36d279e Fix Source Control Type label in project form 2022-03-22 09:35:37 -04:00
Chris Meyers
59bd73bff8 add setting for notification job status retry loop
* We trigger notifications when the callback receiver processes the
playbook_on_stats event. This is the last event in ansible-playbook and
the process should exist very shortly after this event is emitted. The
trouble comes in with the isolated node feature. There is a management
playbook that runs periodically that pulls the events from the remote
node. It's possible that the management playbooks runs, gets the
playbook_on_stats event, but does not see that the playbook is finished
running. Therefore the job status is still seen as 'running' BUT we have
kicked of the notification for the job. The notification worker will
enter a loop waiting on the job to enter the finished state. In this
case the time it takes for the job to enter the finished state can be
long, roughly 2 * the management playbook run time.
* This new setting allows the user to increase the time that the
notification spends waiting for the job to enter the finished state.
2022-03-22 09:20:14 -04:00
Shane McDonald
afbd9f04d7 Merge pull request #11748 from john-westcott-iv/github_workflows_on_all_releases
Chaning workflow to run on all release branches
2022-03-22 09:06:50 -04:00
liortamari
26fb5a0bd7 Merge branch 'ansible:devel' into hashicorp-vault-kubernetes-auth 2022-03-22 14:07:15 +02:00
Seth Foster
acebff7be1 Fix sync-only operation in async context 2022-03-21 14:37:10 -04:00
John Westcott IV
45bd143c07 Fixing import of projects issue due to local_path (#11889) 2022-03-21 14:04:47 -04:00
Jeff Bradberry
aa46a7fe06 Merge pull request #11924 from jbradberry/awxkit-support-inventory-labels
Support the new Inventory.labels in awxkit / awx-cli
2022-03-21 10:19:42 -04:00
Shane McDonald
07d0eedb0a Merge pull request #11875 from shanemcd/url-prefixing-collection
Make our collection work with prefixed API endpoints
2022-03-21 08:09:08 -04:00
Kersom
9aae2a11f2 Add related job templates to a couple of screens (#11890)
Add related job templates to a couple of screens. Credential and
Inventory.

Also refactor the component already in place for Projects to be in sync
with the Job Templates screen.

See: https://github.com/ansible/awx/issues/5867
2022-03-18 20:52:50 +00:00
Jeff Bradberry
51021f380b Support the new Inventory.labels in awxkit / awx-cli 2022-03-18 14:24:49 -04:00
Shane McDonald
7818a479ee Merge pull request #11880 from kurokobo/operator_version
fix: add OPERATOR_VERSION as build-arg to pass the version to operator
2022-03-18 11:20:20 -04:00
Alan Rominger
799bac4066 Merge pull request #11860 from AlanCoding/hybrid_artifacts
Do not remove artifacts for local work
2022-03-18 10:37:06 -04:00
Jeff Bradberry
b562d5cc88 Look up the correct top-level resource name when reconstructing foreign keys
during an awx-cli export.
2022-03-18 10:32:33 -04:00
Tiago Góes
41b3ad1b83 Merge pull request #11917 from nixocio/ui_survey_issue
Fix credential encrypted
2022-03-18 10:44:39 -03:00
nixocio
c912dd4e76 Fix credential encrypted
Display credential as encrypted.

See: https://github.com/ansible/awx/issues/11915
2022-03-17 16:37:44 -04:00
Tiago Góes
3ec9bacb30 Merge pull request #11913 from keithjgrant/9041-page-titles
display current page name in document title
2022-03-17 17:32:00 -03:00
Keith J. Grant
13db49aab7 display current page name in document title 2022-03-17 11:26:20 -07:00
Jeff Bradberry
ac6a82eee4 Merge pull request #11654 from jbradberry/django-3.2-upgrade
Django 3.2 upgrade
2022-03-17 10:34:22 -04:00
Tiago Góes
546fc24a0a Merge pull request #11839 from nixocio/ui_issue_11718_backup
Add several changes to Instance Groups
2022-03-15 18:11:01 -03:00
Alan Rominger
f99820a391 Merge pull request #11898 from AlanCoding/hop_node_lost_found
Only clear hop node errors if they were lost before, not lost now
2022-03-15 13:03:33 -04:00
Shane McDonald
873875af84 Merge pull request #11909 from JamieSlome/patch-1
Create SECURITY.md
2022-03-15 10:38:54 -04:00
Jamie Slome
fcb1c4823e Create SECURITY.md 2022-03-15 13:59:42 +00:00
Kersom
a1203e6fec Merge pull request #11902 from keithjgrant/error-detail-formatting
add line wrap formatting to ErrorDetail
2022-03-15 08:30:12 -04:00
Alan Rominger
2321f06c8a Only clear hop node errors if they were lost before, not lost now 2022-03-14 16:04:55 -04:00
nixocio
ce8b9750c9 Add several changes to Instance Groups
Add several changes to API and UI related to Instance Groups.

* Update summary_fields for DEFAULT_CONTROL_PLANE_QUEUE_NAME, and
  DEFAULT_EXECUTION_QUEUE_NAME. Rely on API validation for those fields.

* Fix Instance Group list RBAC

* Add validation for a couple of fields on the Instance Groups endpoint
	1. is_container_group
	2. policy_instance_percentage
	3. policy_instance_list

See: https://github.com/ansible/awx/issues/11130
Also: https://github.com/ansible/awx/issues/11718
2022-03-14 14:55:59 -04:00
Jeff Bradberry
574e3ed6ef Fix the signature of RADIUSBackend.get_django_user
to match what django-radius is now expecting.
2022-03-14 13:19:57 -04:00
Jeff Bradberry
584514766d Disable our wrapping of the Django settings during migrations
This will hopefully get us past the unfortunate check against the
HostMetric table, which doesn't exist when you are upgrading from 3.8
to 4.x.

Additionally, guard against AUTH_LDAP_GROUP_TYPE not being in settings
for conf migration 0006.
2022-03-14 13:19:57 -04:00
Jeff Bradberry
eb8a1fec49 Make API queries involving json fields cast the fields to text
This restores compatibility with the way it previously worked -- we
never supported proper json operator queries through the API.
2022-03-14 13:19:57 -04:00
Jeff Bradberry
38ccea0f1f Fix up warnings
- the default auto-increment primary key field type is now
  configurable, and Django's check command issues a warning if you are
  just assuming the historical behavior of using AutoField.

- Django 3.2 brings in automatic AppConfig discovery, so all of our
  explicit `default_app_config = ...` assignments in __init__.py
  modules are no longer needed, and raise a RemovedInDjango41Warning.
2022-03-14 13:19:57 -04:00
Jeff Bradberry
5d000c37d6 Deal with breaking tests for 3.2
- Instantiating an abstract model raises a TypeError
2022-03-14 13:19:57 -04:00
Jeff Bradberry
1803c5bdb4 Fix up usage of django-guid
It has replaced the class-based middleware, everything is
function-based now.
2022-03-14 13:19:57 -04:00
Jeff Bradberry
23e700a1ef Upgrade to Django 3.2
- upgrades
  - Django 3.2.12
  - pytz 2021.3 (from 2019.3)
  - oauthlib 3.2.0 (from 3.1.0)
  - requests-oauthlib 1.3.1 (from 1.3.0)
  - django-guid 3.2.1 (from 2.2.1)
  - django-solo 2.0.0 (from 1.1.3)
  - django-taggit 2.1.0 (from 1.2.0)
  - netaddr 0.8.0 (from 0.7.19)
  - pyrad 2.4 (from 2.3)
  - django-radius devel (from 1.3.3)
  - future devel (from 0.16.0)

- django-guid, django-solo, and django-taggit are upgraded to fix the
  AppConfig deprecation warning.  FIXME: django-guid devel has the
  fix, but it hasn't been released yet.

- Released versions of django-radius have a hard-coded pin to
  future==0.16.0, which has a Python warning due to an improperly
  escaped character.  This is fixed in future devel, so for now we are
  pinning to references to the git repos.

- netaddr had a bunch of Python syntax and deprecation warnings
2022-03-14 13:19:53 -04:00
Keith J. Grant
7114b9fa11 add line wrap formatting to ErrorDetail 2022-03-14 09:29:02 -07:00
Tiago Góes
2e4d866f69 Merge pull request #11897 from kialam/add-csp-for-web-worker
Add d3 to CSP.
2022-03-14 11:43:13 -03:00
Tiago Góes
f1cc808429 Merge pull request #11882 from nixocio/api_issue_11622
Add validation for hop nodes
2022-03-14 11:15:26 -03:00
Sarah Akus
30a39e1d1b Merge pull request #11885 from marshmalien/11729-job-details-deleted-text
Add deleted details to job detail view
2022-03-14 10:14:08 -04:00
Sarah Akus
22ad7244fa Merge pull request #11896 from AlanCoding/pod1_standup
Move location of AWX_ISOLATION_SHOW_PATHS so it is editable
2022-03-11 15:39:28 -05:00
Tiago
5be901c044 fix CSP rules 2022-03-11 15:51:35 -03:00
Kia Lam
2c073ae488 Add d3 to CSP. 2022-03-11 08:50:28 -08:00
Alan Rominger
d4a4ba7fdb Move location of AWX_ISOLATION_SHOW_PATHS so it is editable 2022-03-11 11:08:04 -05:00
Sarah Akus
3b8a0fcd95 Merge pull request #11858 from keithjgrant/11409-empty-job-output
add JobOutput screens for empty content
2022-03-11 09:14:53 -05:00
kialam
d02cef9d92 Merge pull request #11501 from kialam/add-mesh-viz
Add mesh visualizer
2022-03-10 11:48:03 -08:00
John Westcott IV
bc783b8f94 Enabling export of applications through awxkit (#11887) 2022-03-10 13:49:18 -05:00
John Westcott IV
4de27117e8 Adding option to enable and configure an OpenLDAP server next to AWX (#11843) 2022-03-10 10:29:04 -05:00
Sarah Akus
49bcf2e211 Merge pull request #11693 from AlexSCorey/5576-host_count_case_sensitivity
Fixes case sensitive host count
2022-03-09 15:55:48 -05:00
Alex Corey
f52ef6e967 Fixes case sensitive host count 2022-03-09 15:36:05 -05:00
Alan Rominger
99bbc347ec Fill in errors for hop nodes when Last Seen is out of date, and clear them when not (#11714)
* Process unresponsive and newly responsive hop nodes

* Use more natural way to zero hop node capacity, add test

* Use warning as opposed to warn for log messages
2022-03-09 13:21:32 -05:00
nixocio
53185a4ea5 Add validation for hop nodes
Add validation for hop nodes

See: https://github.com/ansible/awx/issues/11622
2022-03-09 11:04:12 -05:00
Kia Lam
23f6fae27a Add data-cy to content loader; move simulatioWorker to /util directory. 2022-03-09 07:36:04 -08:00
Marliana Lara
4b7e3620ca Add deleted details to job detail view 2022-03-09 10:25:21 -05:00
Kia Lam
e4f0153a7d Remove import statements from web worker file. 2022-03-09 06:58:43 -08:00
kurokobo
80947e2b32 fix: add OPERATOR_VERSION as build-arg to pass the version to operator 2022-03-09 22:32:38 +09:00
Kia Lam
8bf9dd038e Address review feedback. 2022-03-08 12:58:04 -08:00
Keith J. Grant
4080007ced JobOutput: add 'waiting for job' and 'no results found' messages 2022-03-08 12:35:47 -08:00
Kia Lam
7a6fd2623e Move web worker out of /screens directory. 2022-03-08 12:34:05 -08:00
Kia Lam
079eed2b9e Mock web worker. 2022-03-08 10:13:47 -08:00
Shane McDonald
bd5c304a50 Make our collection work with prefixed API endpoints
I caught this when trying to add test coverage for https://github.com/ansible/awx/pull/11342
2022-03-08 12:05:50 -05:00
Alan Rominger
cd86310562 Do not remove artifacts for local work 2022-03-08 09:07:09 -05:00
Jeff Bradberry
676b8f6d8f Implement an out-of-band migration to change the json fields 2022-03-07 18:11:36 -05:00
Jeff Bradberry
028f09002f Fix the cleanup_jobs management command
It previously depended on a private Django internal class that changed
with Django 3.1.

I've switched here instead to disabling the django-polymorphic
accessors to get the underlying UnifiedJob object for a Job, which due
to the way they implement those was resulting in N+1 behavior on
deletes.  This gets us back most of the way to the performance gains
we achieved with the custom collector class.  See
https://github.com/django-polymorphic/django-polymorphic/issues/198.
2022-03-07 18:11:36 -05:00
Jeff Bradberry
0500512c3c Fix up deprecation warning about get_response for middleware
It will no longer be allowed to be None by Django 4.0
2022-03-07 18:11:36 -05:00
Jeff Bradberry
1e625ed58b Fix up deprecation warning about re_path() replacing urls() 2022-03-07 18:11:36 -05:00
Jeff Bradberry
e620bef2a5 Fix Django 3.1 deprecation removal problems
- FieldDoesNotExist now has to be imported from django.core.exceptions
- Django docs specifically say not to import
  django.conf.global_settings, which now has the side-effect of
  triggering one of the check errors
2022-03-07 18:11:36 -05:00
Jeff Bradberry
05142a779d Replace all usage of customized json fields with the Django builtin
The event_data field on event models, however, is getting an
overridden version that retains the underlying text data type for the
column, to avoid a heavy data migration on those tables.

Also, certain of the larger tables are getting these fields with the
NOT NULL constraint turned off, to avoid a long migration.

Remove the django.utils.six monkey patch we did at the beginning of
the upgrade.
2022-03-07 18:11:36 -05:00
Jeff Bradberry
65d17fb316 Upgrade to Django 3.1
- upgrades
  - Django 3.1.14
  - djangorestframework 3.13.1 (from 3.12.1)
  - djangorestframework-yaml 2.0.0 (from 1.0.3)
  - django-polymorphic 3.1.0 (from 2.1.2)
  - social-auth-core 4.2.0 (from 3.3.1)
  - social-auth-app-django 5.0.0 (from 3.1.0)
  - django-auth-ldap 4.0.0 (from 2.1.0)
  - django-crum 0.7.9 (from 0.7.5)

- django-jsonfield is removed
2022-03-07 18:11:36 -05:00
Jeff Bradberry
faa12880a9 Squash a few deprecation warnings
- inspect.getargspec() -> inspect.getfullargspec()
- register pytest.mark.fixture_args
- replace use of DRF's deprecated NullBooleanField
- fix some usage of naive datetimes in the tests
- fix some strings with backslashes that ought to be raw strings
2022-03-07 18:11:36 -05:00
Jeff Bradberry
9b6fa55433 Deal with breaking tests for 3.1
- Django's PostgreSQL JSONField wraps values in a JsonAdapter, so deal
  with that when it happens.  This goes away in Django 3.1.
- Setting related *_id fields clears the actual relation field, so
  trying to fake objects for tests is a problem
- Instance.objects.me() was inappropriately creating stub objects
  every time while running tests, but some of our tests now create
  real db objects. Ditch that logic and use a proper fixture where needed.
- awxkit tox.ini was pinned at Python 3.8
2022-03-07 18:11:36 -05:00
Jeff Bradberry
b852baaa39 Fix up logger .warn() calls to use .warning() instead
This is a usage that was deprecated in Python 3.0.
2022-03-07 18:11:36 -05:00
Jeff Bradberry
a3a216f91f Fix up new Django 3.0 deprecations
Mostly text based: force/smart_text, ugettext_*
2022-03-07 18:11:36 -05:00
Bill Nottingham
efff85bc1f Fix wsbroadcast for django 3.0+ async
From https://docs.djangoproject.com/en/3.0/topics/async/#asgiref.sync.sync_to_async
2022-03-07 18:11:36 -05:00
Jeff Bradberry
df61d1a59c Upgrade to Django 3.0
- upgrades
  - Django 3.0.14
  - django-jsonfield 1.4.1 (from 1.2.0)
  - django-oauth-toolkit 1.4.1 (from 1.1.3)
    - Stopping here because later versions have changes to the
      underlying model to support OpenID Connect.  Presumably this can
      be dealt with via a migration in our project.
  - django-guid 2.2.1 (from 2.2.0)
  - django-debug-toolbar 3.2.4 (from 1.11.1)
  - python3-saml 1.13.0 (from 1.9.0)
  - xmlsec 1.3.12 (from 1.3.3)

- Remove our project's use of django.utils.six in favor of directly
  using six, in awx.sso.fields.

- Temporarily monkey patch six back in as django.utils.six, since
  django-jsonfield makes use of that import, and is no longer being
  updated.  Hopefully we can do away with this dependency with the new
  generalized JSONField brought in with Django 3.1.

- Force a json decoder to be used with all instances of JSONField
  brought in by django-jsonfield.  This deals with the 'cast to text'
  problem noted previously in our UPGRADE_BLOCKERS.

- Remove the validate_uris validator from the OAuth2Application in
  migration 0025, per the UPGRADE_BLOCKERS, and remove that note.

- Update the TEMPLATES setting to satisfy Django Debug Toolbar.  It
  requires at least one entry that has APP_DIRS=True, and as near as I
  can tell our custom OPTIONS.loaders setting was effectively doing
  the same thing as Django's own machinery if this setting is set.
2022-03-07 18:11:36 -05:00
Kia Lam
4040e09cb8 Remove setTimeout and old comment from MeshGraph.js. 2022-03-01 16:25:12 -08:00
liortamary
bbf6484e89 fix code review comments: Add support for Kubernetes authentication method in Hashicorp Vault secret lookup 2022-03-01 21:21:28 +02:00
liortamary
b870659fd9 run black: Add support for Kubernetes authentication method in Hashicorp Vault secret lookup 2022-02-26 18:33:36 +02:00
Kia Lam
fd135caed5 Offload simulation calculation to web worker. 2022-02-23 18:54:18 -08:00
Kia Lam
7fbab6760e Small layout adjustment. 2022-02-23 12:37:20 -08:00
Kia Lam
7ebf6b77e5 Disable zoom controls until mesh layout is finalized. 2022-02-22 13:45:30 -08:00
Kia Lam
fee47fe347 Vertically center node type symbols on Firefox. 2022-02-22 09:36:57 -08:00
Kia Lam
039c038cd7 Move zoom methods into a hook. 2022-02-22 09:36:43 -08:00
liortamary
dd99a25db0 unittest: Add support for Kubernetes authentication method in Hashicorp Vault secret lookup
Signed-off-by: liortamary <lior.tamary@houzz.com>
2022-02-22 17:53:34 +02:00
liortamary
85791f730c Add support for Kubernetes authentication method in Hashicorp Vault secret lookup
Signed-off-by: liortamary <lior.tamary@houzz.com>
2022-02-22 13:04:58 +02:00
liortamary
e0ce4c49f3 Add support for Kubernetes authentication method in Hashicorp Vault secret lookup
Signed-off-by: liortamary <lior.tamary@houzz.com>
2022-02-21 17:41:14 +02:00
Kia Lam
ef5cd66494 Excise disable-lint rules. 2022-02-17 13:58:16 -08:00
Kia Lam
0d1898e72d Add error screen. 2022-02-17 13:26:31 -08:00
Kia Lam
8993dc706a Redirect to Instances/{nodeId}/details page. 2022-02-17 10:53:27 -08:00
Kia Lam
af18453691 Use 100% height. 2022-02-17 10:21:48 -08:00
kialam
c102bf05af Update awx/ui/src/screens/TopologyView/MeshGraph.js
Co-authored-by: Tiago Góes <tiago.goes2009@gmail.com>
2022-02-17 10:21:48 -08:00
Kia Lam
b1570302bc Refactor: move constants and helper functions into their own files. 2022-02-17 10:21:48 -08:00
Kia Lam
69a42b1a89 Some lint fixes; fix routesConfig unit test. 2022-02-17 10:21:48 -08:00
Kia Lam
272e012626 Add new loading screen placeholder. 2022-02-17 10:21:47 -08:00
Kia Lam
d785f30c5f Fix JSX errors. 2022-02-17 10:21:47 -08:00
Kia Lam
9854f8a6ab Use alpha decay percentage instead of absolute value for loading screen. 2022-02-17 10:21:47 -08:00
Kia Lam
4235bf67f8 Truncate long host names in graph, show full name in tooltip. 2022-02-17 10:21:47 -08:00
Kia Lam
a6bc0d4222 Add loading screen. 2022-02-17 10:21:47 -08:00
Kia Lam
b859c3360d Add zoom to fit. 2022-02-17 10:21:47 -08:00
Kia Lam
391907c41e Add reset zoom button. 2022-02-17 10:21:47 -08:00
Kia Lam
04a550cc67 Hook up zoom in, zoom out buttons. 2022-02-17 10:21:46 -08:00
Kia Lam
cf459dc4e8 Remove placeholder label text. 2022-02-17 10:21:46 -08:00
Kia Lam
afebcc574d Add icons to header; randomly generate data. 2022-02-17 10:21:46 -08:00
Kia Lam
f3474f0811 Add legend toggle to header. 2022-02-17 10:21:46 -08:00
Kia Lam
7378952a8b Add opaque bg to tooltip and legend. 2022-02-17 10:21:46 -08:00
Kia Lam
3cfab418d1 Fix zoom on scroll. 2022-02-17 10:21:46 -08:00
Kia Lam
8090cd3032 WIP new mesh layout based on QE feedback. 2022-02-17 10:21:46 -08:00
Kia Lam
cd54d560b3 Update layout; fix multiple renders happening on page load. 2022-02-17 10:21:46 -08:00
Tiago
9fc92ccc52 add data-cy attr 2022-02-17 10:21:46 -08:00
Kia Lam
b8674a3f8c Use PF colors for nodes. 2022-02-17 10:21:46 -08:00
Kia Lam
07ccce9845 Zoom in/out on entire SVG canvas. 2022-02-17 10:21:46 -08:00
Kia Lam
0c8c69f04a Add RBAC for /topology_view endpoint. 2022-02-17 10:21:46 -08:00
Kia Lam
5856f805fc Add debounce to resize event; link to node details. 2022-02-17 10:21:46 -08:00
Kia Lam
73a5802c11 Lint. 2022-02-17 10:21:45 -08:00
Kia Lam
826a069be0 Highlight immediate siblings on hover. 2022-02-17 10:21:45 -08:00
Kia Lam
1246b14e7e WIP add network visualizer to Controller UI. 2022-02-17 10:21:45 -08:00
John Westcott IV
50d52c31e2 Chaning workflow to run on all release branches 2022-02-15 15:32:27 -05:00
Andrew Kelling
dfde30798e Update README.md
Cleaned up wording
2021-12-07 11:59:11 -07:00
815 changed files with 58260 additions and 29871 deletions

17
.github/BOTMETA.yml vendored
View File

@@ -1,17 +0,0 @@
---
files:
awx/ui/:
labels: component:ui
maintainers: $team_ui
awx/api/:
labels: component:api
maintainers: $team_api
awx/main/:
labels: component:api
maintainers: $team_api
installer/:
labels: component:installer
macros:
team_api: wwitzel3 matburt chrismeyersfsu cchurch AlanCoding ryanpetrello rooftopcellist
team_ui: jlmitch5 jaredevantabor mabashian marshmalien benthomasson jakemcdermott

1
.github/CODEOWNERS vendored
View File

@@ -1 +0,0 @@
workflows/e2e_test.yml @tiagodread @shanemcd @jakemcdermott

View File

@@ -6,17 +6,37 @@ practices regarding responsible disclosure, see
https://www.ansible.com/security
-->
<!--
PLEASE DO NOT USE A BLANK TEMPLATE IN THE AWX REPO.
This is a legacy template used for internal testing ONLY.
Any issues opened will this template will be automatically closed.
Instead use the bug or feature request.
-->
##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
- Bug Report
- Feature Idea
- Documentation
- Breaking Change
- New or Enhanced Feature
- Bug or Docs Fix
##### COMPONENT NAME
<!-- Pick the area of AWX for this issue, you can have multiple, delete the rest: -->
- API
- UI
- Collection
- Docs
- CLI
- Other
##### SUMMARY
<!-- Briefly describe the problem. -->

View File

@@ -1,13 +1,12 @@
---
name: Bug Report
description: Create a report to help us improve
description: "🐞 Create a report to help us improve"
body:
- type: markdown
attributes:
value: |
Issues are for **concrete, actionable bugs and feature requests** only. For debugging help or technical support, please use:
- The #ansible-awx channel on irc.libera.chat
- The awx project mailing list, https://groups.google.com/forum/#!forum/awx-project
Bug Report issues are for **concrete, actionable bugs** only.
For debugging help or technical support, please see the [Get Involved section of our README](https://github.com/ansible/awx#get-involved)
- type: checkboxes
id: terms
@@ -24,7 +23,7 @@ body:
- type: textarea
id: summary
attributes:
label: Summary
label: Bug Summary
description: Briefly describe the problem.
validations:
required: false
@@ -45,6 +44,9 @@ body:
- label: UI
- label: API
- label: Docs
- label: Collection
- label: CLI
- label: Other
- type: dropdown
id: awx-install-method
@@ -57,9 +59,8 @@ body:
- minikube
- openshift
- minishift
- docker on linux
- docker for mac
- boot2docker
- docker development environment
- N/A
validations:
required: true

12
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
---
blank_issues_enabled: true
contact_links:
- name: For debugging help or technical support
url: https://github.com/ansible/awx#get-involved
about: For general debugging or technical support please see the Get Involved section of our readme.
- name: 📝 Ansible Code of Conduct
url: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html?utm_medium=github&utm_source=issue_template_chooser
about: AWX uses the Ansible Code of Conduct; ❤ Be nice to other members of the community. ☮ Behave.
- name: 💼 For Enterprise
url: https://www.ansible.com/products/engine?utm_medium=github&utm_source=issue_template_chooser
about: Red Hat offers support for the Ansible Automation Platform

View File

@@ -1,17 +0,0 @@
---
name: "✨ Feature request"
about: Suggest an idea for this project
---
<!-- Issues are for **concrete, actionable bugs and feature requests** only - if you're just asking for debugging help or technical support, please use:
- http://web.libera.chat/?channels=#ansible-awx
- https://groups.google.com/forum/#!forum/awx-project
We have to limit this because of limited volunteer time to respond to issues! -->
##### ISSUE TYPE
- Feature Idea
##### SUMMARY
<!-- Briefly describe the problem or desired enhancement. -->

View File

@@ -0,0 +1,42 @@
---
name: ✨ Feature request
description: Suggest an idea for this project
body:
- type: markdown
attributes:
value: |
Feature Request issues are for **feature requests** only.
For debugging help or technical support, please see the [Get Involved section of our README](https://github.com/ansible/awx#get-involved)
- type: checkboxes
id: terms
attributes:
label: Please confirm the following
options:
- label: I agree to follow this project's [code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).
required: true
- label: I have checked the [current issues](https://github.com/ansible/awx/issues) for duplicates.
required: true
- label: I understand that AWX is open source software provided for free and that I might not receive a timely response.
required: true
- type: textarea
id: summary
attributes:
label: Feature Summary
description: Briefly describe the desired enhancement.
validations:
required: true
- type: checkboxes
id: components
attributes:
label: Select the relevant components
options:
- label: UI
- label: API
- label: Docs
- label: Collection
- label: CLI
- label: Other

View File

@@ -1,9 +0,0 @@
Bug Report: type:bug
Bugfix Pull Request: type:bug
Feature Request: type:enhancement
Feature Pull Request: type:enhancement
UI: component:ui
API: component:api
Installer: component:installer
Docs Pull Request: component:docs
Documentation: component:docs

View File

@@ -1,11 +1,3 @@
<!--- changelog-entry
# Fill in 'msg' below to have an entry automatically added to the next release changelog.
# Leaving 'msg' blank will not generate a changelog entry for this PR.
# Please ensure this is a simple (and readable) one-line string.
---
msg: ""
-->
##### SUMMARY
<!--- Describe the change, including rationale and design decisions -->
@@ -17,15 +9,18 @@ the change does.
##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
- Feature Pull Request
- Bugfix Pull Request
- Docs Pull Request
- Breaking Change
- New or Enhanced Feature
- Bug or Docs Fix
##### COMPONENT NAME
<!--- Name of the module/plugin/module/task -->
- API
- UI
- Collection
- CLI
- Docs
- Other
##### AWX VERSION
<!--- Paste verbatim output from `make VERSION` between quotes below -->

19
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/awx/ui"
schedule:
interval: "monthly"
open-pull-requests-limit: 5
allow:
- dependency-type: "production"
reviewers:
- "AlexSCorey"
- "keithjgrant"
- "kialam"
- "mabashian"
- "marshmalien"
labels:
- "component:ui"
- "dependencies"
target-branch: "devel"

View File

@@ -1,12 +1,16 @@
needs_triage:
- '.*'
"type:bug":
- "Please confirm the following"
- "Bug Summary"
"type:enhancement":
- "Feature Idea"
- "Feature Summary"
"component:ui":
- "\\[X\\] UI"
"component:api":
- "\\[X\\] API"
"component:docs":
- "\\[X\\] Docs"
"component:awx_collection":
- "\\[X\\] Collection"
"component:cli":
- "\\[X\\] awxkit"

View File

@@ -1,14 +1,19 @@
"component:api":
- any: ['awx/**/*', '!awx/ui/*']
- any: ["awx/**/*", "!awx/ui/**"]
"component:ui":
- any: ['awx/ui/**/*']
- any: ["awx/ui/**/*"]
"component:docs":
- any: ['docs/**/*']
- any: ["docs/**/*"]
"component:cli":
- any: ['awxkit/**/*']
- any: ["awxkit/**/*"]
"component:collection":
- any: ['awx_collection/**/*']
"component:awx_collection":
- any: ["awx_collection/**/*"]
"dependencies":
- any: ["awx/ui/package.json"]
- any: ["awx/requirements/*.txt"]
- any: ["awx/requirements/requirements.in"]

111
.github/triage_replies.md vendored Normal file
View File

@@ -0,0 +1,111 @@
## General
- For the roundup of all the different mailing lists available from AWX, Ansible, and beyond visit: https://docs.ansible.com/ansible/latest/community/communication.html
- Hello, we think your question is answered in our FAQ. Does this: https://www.ansible.com/products/awx-project/faq cover your question?
- You can find the latest documentation here: https://docs.ansible.com/automation-controller/latest/html/userguide/index.html
## PRs/Issues
### Visit our mailing list
- Hello, this appears to be less of a bug report or feature request and more of a question. Could you please ask this on our mailing list? See https://github.com/ansible/awx/#get-involved for information for ways to connect with us.
### Denied Submission
- Hi! \
\
Thanks very much for your submission to AWX. It means a lot to us that you have taken time to contribute. \
\
At this time we do not want to merge this PR. Our reasons for this are: \
\
(A) INSERT ITEM HERE \
\
Please know that we are always up for discussion but this project is very active. Because of this, we're unlikely to see comments made on closed PRs, and we lock them after some time. If you or anyone else has any further questions, please let us know by using any of the communication methods listed in the page below: \
\
https://github.com/ansible/awx/#get-involved \
\
In the future, sometimes starting a discussion on the development list prior to implementing a feature can make getting things included a little easier, but it is not always necessary. \
\
Thank you once again for this and your interest in AWX!
### No Progress Issue
- Hi! \
\
Thank you very much for for this issue. It means a lot to us that you have taken time to contribute by opening this report. \
\
On this issue, there were comments added but it has been some time since then without response. At this time we are closing this issue. If you get time to address the comments we can reopen the issue if you can contact us by using any of the communication methods listed in the page below: \
\
https://github.com/ansible/awx/#get-involved \
\
Thank you once again for this and your interest in AWX!
### No Progress PR
- Hi! \
\
Thank you very much for your submission to AWX. It means a lot to us that you have taken time to contribute. \
\
On this PR, changes were requested but it has been some time since then. We think this PR has merit but without the requested changes we are unable to merge it. At this time we are closing your PR. If you get time to address the changes you are welcome to open another PR or we can reopen this PR upon request if you contact us by using any of the communication methods listed in the page below: \
\
https://github.com/ansible/awx/#get-involved \
\
Thank you once again for this and your interest in AWX!
## Common
### Give us more info
- Hello, we'd love to help, but we need a little more information about the problem you're having. Screenshots, log outputs, or any reproducers would be very helpful.
### Code of Conduct
- Hello. Please keep in mind that Ansible adheres to a Code of Conduct in its community spaces. The spirit of the code of conduct is to be kind, and this is your friendly reminder to be so. Please see the full code of conduct here if you have questions: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html
### EE Contents / Community General
- Hello. The awx-ee contains the collections and dependencies needed for supported AWX features to function. Anything beyond that (like the community.general package) will require you to build your own EE. For information on how to do that, see https://ansible-builder.readthedocs.io/en/stable/ \
\
The Ansible Community is looking at building an EE that corresponds to all of the collections inside the ansible package. That may help you if and when it happens; see https://github.com/ansible-community/community-topics/issues/31 for details.
## Mailing List Triage
### Create an issue
- Hello, thanks for reaching out on list. We think this merits an issue on our Github, https://github.com/ansible/awx/issues. If you could open an issue up on Github it will get tagged and integrated into our planning and workflow. All future work will be tracked there. Issues should include as much information as possible, including screenshots, log outputs, or any reproducers.
### Create a Pull Request
- Hello, we think your idea is good! Please consider contributing a PR for this following our contributing guidelines: https://github.com/ansible/awx/blob/devel/CONTRIBUTING.md
### Receptor
- You can find the receptor docs here: https://receptor.readthedocs.io/en/latest/
- Hello, your issue seems related to receptor. Could you please open an issue in the receptor repository? https://github.com/ansible/receptor. Thanks!
### Ansible Engine not AWX
- Hello, your question seems to be about Ansible development, not about AWX. Try asking on the Ansible-devel specific mailing list: https://groups.google.com/g/ansible-devel
- Hello, your question seems to be about using Ansible, not about AWX. https://groups.google.com/g/ansible-project is the best place to visit for user questions about Ansible. Thanks!
### Ansible Galaxy not AWX
- Hey there. That sounds like an FAQ question. Did this: https://www.ansible.com/products/awx-project/faq cover your question?
### Contributing Guidelines
- AWX: https://github.com/ansible/awx/blob/devel/CONTRIBUTING.md
- AWX-Operator: https://github.com/ansible/awx-operator/blob/devel/CONTRIBUTING.md
### AWX Release
Subject: Announcing AWX X.Y.z
- Hi all, \
\
We're happy to announce that the next release of AWX, version <X> is now available! \
In addition AWX Operator version <Y> has also been release! \
\
Please see the releases pages for more details: \
AWX: https://github.com/ansible/awx/releases/tag/<X> \
Operator: https://github.com/ansible/awx-operator/releases/tag/<Y> \
\
The AWX team.
## Try latest version
- Hello, this issue pertains to an older version of AWX. Try upgrading to the latest version and let us know if that resolves your issue.

View File

@@ -113,7 +113,7 @@ jobs:
- name: Install playbook dependencies
run: |
python3 -m pip install docker
python3 -m pip install docker setuptools_scm
- name: Build AWX image
working-directory: awx

View File

@@ -1,11 +1,13 @@
---
name: Push Development Image
name: Build/Push Development Images
on:
push:
branches:
- devel
- release_*
jobs:
push:
if: endsWith(github.repository, '/awx') || startsWith(github.ref, 'refs/heads/release_')
runs-on: ubuntu-latest
permissions:
packages: write
@@ -27,12 +29,15 @@ jobs:
- name: Pre-pull image to warm build cache
run: |
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${GITHUB_REF##*/}
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${GITHUB_REF##*/} || :
docker pull ghcr.io/${{ github.repository_owner }}/awx_kube_devel:${GITHUB_REF##*/} || :
- name: Build image
- name: Build images
run: |
DEV_DOCKER_TAG_BASE=ghcr.io/${{ github.repository_owner }} COMPOSE_TAG=${GITHUB_REF##*/} make docker-compose-build
DEV_DOCKER_TAG_BASE=ghcr.io/${{ github.repository_owner }} COMPOSE_TAG=${GITHUB_REF##*/} make awx-kube-dev-build
- name: Push image
run: |
docker push ghcr.io/${{ github.repository_owner }}/awx_devel:${GITHUB_REF##*/}
docker push ghcr.io/${{ github.repository_owner }}/awx_kube_devel:${GITHUB_REF##*/}

View File

@@ -5,7 +5,6 @@ on:
types:
- opened
- reopened
- edited
jobs:
triage:

View File

@@ -21,7 +21,7 @@ jobs:
- name: Install dependencies
run: |
python${{ env.py_version }} -m pip install wheel twine
python${{ env.py_version }} -m pip install wheel twine setuptools-scm
- name: Set official collection namespace
run: echo collection_namespace=awx >> $GITHUB_ENV
@@ -33,7 +33,7 @@ jobs:
- name: Build collection and publish to galaxy
run: |
COLLECTION_NAMESPACE=${{ env.collection_namespace }} make build_collection
COLLECTION_TEMPLATE_VERSION=true COLLECTION_NAMESPACE=${{ env.collection_namespace }} make build_collection
ansible-galaxy collection publish \
--token=${{ secrets.GALAXY_TOKEN }} \
awx_collection_build/${{ env.collection_namespace }}-awx-${{ github.event.release.tag_name }}.tar.gz
@@ -70,4 +70,4 @@ jobs:
docker tag ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }} quay.io/${{ github.repository }}:latest
docker push quay.io/${{ github.repository }}:${{ github.event.release.tag_name }}
docker push quay.io/${{ github.repository }}:latest

View File

@@ -65,7 +65,7 @@ jobs:
- name: Install playbook dependencies
run: |
python3 -m pip install docker
python3 -m pip install docker setuptools_scm
- name: Build and stage AWX
working-directory: awx
@@ -83,7 +83,8 @@ jobs:
- name: Build and stage awx-operator
working-directory: awx-operator
run: |
BUILD_ARGS="--build-arg DEFAULT_AWX_VERSION=${{ github.event.inputs.version }}" \
BUILD_ARGS="--build-arg DEFAULT_AWX_VERSION=${{ github.event.inputs.version }} \
--build-arg OPERATOR_VERSION=${{ github.event.inputs.operator_version }}" \
IMAGE_TAG_BASE=ghcr.io/${{ github.repository_owner }}/awx-operator \
VERSION=${{ github.event.inputs.operator_version }} make docker-build docker-push
@@ -99,23 +100,10 @@ jobs:
AWX_TEST_IMAGE: ${{ github.repository }}
AWX_TEST_VERSION: ${{ github.event.inputs.version }}
- name: Generate changelog
uses: shanemcd/simple-changelog-generator@v1
id: changelog
with:
repo: "${{ github.repository }}"
- name: Write changelog to file
run: |
cat << 'EOF' > /tmp/awx-changelog
${{ steps.changelog.outputs.changelog }}
EOF
- name: Create draft release for AWX
working-directory: awx
run: |
ansible-playbook -v tools/ansible/stage.yml \
-e changelog_path=/tmp/awx-changelog \
-e repo=${{ github.repository }} \
-e awx_image=ghcr.io/${{ github.repository }} \
-e version=${{ github.event.inputs.version }} \

View File

@@ -4,7 +4,7 @@ on:
push:
branches:
- devel
- release_4.1
- release_**
jobs:
push:
runs-on: ubuntu-latest

7
.gitignore vendored
View File

@@ -7,6 +7,9 @@ reference-schema.json
.tags
.tags1
# User level pre-commit hooks
pre-commit-user
# Tower
awx-dev
awx/settings/local_*.py*
@@ -35,7 +38,6 @@ awx/ui/build
awx/ui/.env.local
awx/ui/instrumented
rsyslog.pid
tools/prometheus/data
tools/docker-compose/ansible/awx_dump.sql
tools/docker-compose/Dockerfile
tools/docker-compose/_build
@@ -151,6 +153,9 @@ use_dev_supervisor.txt
/sanity/
/awx_collection_build/
# Setup for metrics gathering
tools/prometheus/prometheus.yml
.idea/*
*.unison.tmp
*.#

View File

@@ -17,6 +17,7 @@ Have questions about this document or anything not covered here? Come chat with
- [Building API Documentation](#building-api-documentation)
- [Accessing the AWX web interface](#accessing-the-awx-web-interface)
- [Purging containers and images](#purging-containers-and-images)
- [Pre commit hooks](#pre-commit-hooks)
- [What should I work on?](#what-should-i-work-on)
- [Submitting Pull Requests](#submitting-pull-requests)
- [PR Checks run by Zuul](#pr-checks-run-by-zuul)
@@ -104,6 +105,14 @@ When necessary, remove any AWX containers and images by running the following:
(host)$ make docker-clean
```
### Pre commit hooks
When you attempt to perform a `git commit` there will be a pre-commit hook that gets run before the commit is allowed to your local repository. For example, python's [black](https://pypi.org/project/black/) will be run to test the formatting of any python files.
While you can use environment variables to skip the pre-commit hooks GitHub will run similar tests and prevent merging of PRs if the tests do not pass.
If you would like to add additional commit hooks for your own usage you can create a directory in the root of the repository called `pre-commit-user`. Any executable file in that directory will be executed as part of the pre-commit hooks. If any of the pre-commit checks fail the commit will be halted. For your convenience in user scripts, a variable called `CHANGED_FILES` will be set with any changed files present in the commit.
## What should I work on?
For feature work, take a look at the current [Enhancements](https://github.com/ansible/awx/issues?q=is%3Aissue+is%3Aopen+label%3Atype%3Aenhancement).

View File

@@ -5,18 +5,26 @@ NPM_BIN ?= npm
CHROMIUM_BIN=/tmp/chrome-linux/chrome
GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
MANAGEMENT_COMMAND ?= awx-manage
VERSION := $(shell $(PYTHON) setup.py --version)
COLLECTION_VERSION := $(shell $(PYTHON) setup.py --version | cut -d . -f 1-3)
VERSION := $(shell $(PYTHON) tools/scripts/scm_version.py)
COLLECTION_VERSION := $(shell $(PYTHON) tools/scripts/scm_version.py | cut -d . -f 1-3)
# NOTE: This defaults the container image version to the branch that's active
COMPOSE_TAG ?= $(GIT_BRANCH)
MAIN_NODE_TYPE ?= hybrid
# If set to true docker-compose will also start a keycloak instance
KEYCLOAK ?= false
# If set to true docker-compose will also start an ldap instance
LDAP ?= false
# If set to true docker-compose will also start a splunk instance
SPLUNK ?= false
# If set to true docker-compose will also start a prometheus instance
PROMETHEUS ?= false
# If set to true docker-compose will also start a grafana instance
GRAFANA ?= false
VENV_BASE ?= /var/lib/awx/venv
DEV_DOCKER_TAG_BASE ?= quay.io/awx
DEV_DOCKER_TAG_BASE ?= ghcr.io/ansible
DEVEL_IMAGE_NAME ?= $(DEV_DOCKER_TAG_BASE)/awx_devel:$(COMPOSE_TAG)
RECEPTOR_IMAGE ?= quay.io/ansible/receptor:devel
@@ -26,7 +34,7 @@ RECEPTOR_IMAGE ?= quay.io/ansible/receptor:devel
SRC_ONLY_PKGS ?= cffi,pycparser,psycopg2,twilio
# These should be upgraded in the AWX and Ansible venv before attempting
# to install the actual requirements
VENV_BOOTSTRAP ?= pip==21.2.4 setuptools==58.2.0 wheel==0.36.2
VENV_BOOTSTRAP ?= pip==21.2.4 setuptools==58.2.0 setuptools_scm[toml]==6.4.2 wheel==0.36.2
NAME ?= awx
@@ -41,7 +49,7 @@ I18N_FLAG_FILE = .i18n_built
.PHONY: awx-link clean clean-tmp clean-venv requirements requirements_dev \
develop refresh adduser migrate dbchange \
receiver test test_unit test_coverage coverage_html \
dev_build release_build sdist \
sdist \
ui-release ui-devel \
VERSION PYTHON_VERSION docker-compose-sources \
.git/hooks/pre-commit
@@ -175,7 +183,7 @@ collectstatic:
fi; \
mkdir -p awx/public/static && $(PYTHON) manage.py collectstatic --clear --noinput > /dev/null 2>&1
UWSGI_DEV_RELOAD_COMMAND ?= supervisorctl restart tower-processes:awx-dispatcher tower-processes:awx-receiver
DEV_RELOAD_COMMAND ?= supervisorctl restart tower-processes:*
uwsgi: collectstatic
@if [ "$(VENV_BASE)" ]; then \
@@ -190,12 +198,13 @@ uwsgi: collectstatic
--processes=5 \
--harakiri=120 --master \
--no-orphans \
--py-autoreload 1 \
--max-requests=1000 \
--stats /tmp/stats.socket \
--lazy-apps \
--logformat "%(addr) %(method) %(uri) - %(proto) %(status)" \
--hook-accepting1="exec: $(UWSGI_DEV_RELOAD_COMMAND)"
--logformat "%(addr) %(method) %(uri) - %(proto) %(status)"
awx-autoreload:
@/awx_devel/tools/docker-compose/awx-autoreload /awx_devel/awx "$(DEV_RELOAD_COMMAND)"
daphne:
@if [ "$(VENV_BASE)" ]; then \
@@ -264,7 +273,7 @@ api-lint:
yamllint -s .
awx-link:
[ -d "/awx_devel/awx.egg-info" ] || $(PYTHON) /awx_devel/setup.py egg_info_dev
[ -d "/awx_devel/awx.egg-info" ] || $(PYTHON) /awx_devel/tools/scripts/egg_info_dev
cp -f /tmp/awx.egg-link /var/lib/awx/venv/awx/lib/$(PYTHON)/site-packages/awx.egg-link
TEST_DIRS ?= awx/main/tests/unit awx/main/tests/functional awx/conf/tests awx/sso/tests
@@ -283,6 +292,7 @@ COLLECTION_TEST_TARGET ?=
COLLECTION_PACKAGE ?= awx
COLLECTION_NAMESPACE ?= awx
COLLECTION_INSTALL = ~/.ansible/collections/ansible_collections/$(COLLECTION_NAMESPACE)/$(COLLECTION_PACKAGE)
COLLECTION_TEMPLATE_VERSION ?= false
test_collection:
rm -f $(shell ls -d $(VENV_BASE)/awx/lib/python* | head -n 1)/no-global-site-packages.txt
@@ -310,7 +320,7 @@ awx_collection_build: $(shell find awx_collection -type f)
-e collection_package=$(COLLECTION_PACKAGE) \
-e collection_namespace=$(COLLECTION_NAMESPACE) \
-e collection_version=$(COLLECTION_VERSION) \
-e '{"awx_template_version":false}'
-e '{"awx_template_version": $(COLLECTION_TEMPLATE_VERSION)}'
ansible-galaxy collection build awx_collection_build --force --output-path=awx_collection_build
build_collection: awx_collection_build
@@ -413,14 +423,6 @@ ui-test-general:
$(NPM_BIN) --prefix awx/ui install
$(NPM_BIN) run --prefix awx/ui pretest
$(NPM_BIN) run --prefix awx/ui/ test-general --runInBand
# Build a pip-installable package into dist/ with a timestamped version number.
dev_build:
$(PYTHON) setup.py dev_build
# Build a pip-installable package into dist/ with the release version number.
release_build:
$(PYTHON) setup.py release_build
HEADLESS ?= no
ifeq ($(HEADLESS), yes)
@@ -428,7 +430,7 @@ dist/$(SDIST_TAR_FILE):
else
dist/$(SDIST_TAR_FILE): $(UI_BUILD_FLAG_FILE)
endif
$(PYTHON) setup.py $(SDIST_COMMAND)
$(PYTHON) -m build -s
ln -sf $(SDIST_TAR_FILE) dist/awx.tar.gz
sdist: dist/$(SDIST_TAR_FILE)
@@ -462,7 +464,11 @@ docker-compose-sources: .git/hooks/pre-commit
-e control_plane_node_count=$(CONTROL_PLANE_NODE_COUNT) \
-e execution_node_count=$(EXECUTION_NODE_COUNT) \
-e minikube_container_group=$(MINIKUBE_CONTAINER_GROUP) \
-e enable_keycloak=$(KEYCLOAK)
-e enable_keycloak=$(KEYCLOAK) \
-e enable_ldap=$(LDAP) \
-e enable_splunk=$(SPLUNK) \
-e enable_prometheus=$(PROMETHEUS) \
-e enable_grafana=$(GRAFANA)
docker-compose: awx/projects docker-compose-sources
@@ -510,7 +516,7 @@ docker-clean:
fi
docker-clean-volumes: docker-compose-clean docker-compose-container-group-clean
docker volume rm tools_awx_db
docker volume rm -f tools_awx_db tools_grafana_storage tools_prometheus_storage $(docker volume ls --filter name=tools_redis_socket_ -q)
docker-refresh: docker-clean docker-compose
@@ -521,9 +527,6 @@ docker-compose-elk: awx/projects docker-compose-sources
docker-compose-cluster-elk: awx/projects docker-compose-sources
docker-compose -f tools/docker-compose/_sources/docker-compose.yml -f tools/elastic/docker-compose.logstash-link-cluster.yml -f tools/elastic/docker-compose.elastic-override.yml up --no-recreate
prometheus:
docker run -u0 --net=tools_default --link=`docker ps | egrep -o "tools_awx(_run)?_([^ ]+)?"`:awxweb --volume `pwd`/tools/prometheus:/prometheus --name prometheus -d -p 0.0.0.0:9090:9090 prom/prometheus --web.enable-lifecycle --config.file=/prometheus/prometheus.yml
docker-compose-container-group:
MINIKUBE_CONTAINER_GROUP=true make docker-compose
@@ -555,8 +558,9 @@ Dockerfile.kube-dev: tools/ansible/roles/dockerfile/templates/Dockerfile.j2
-e receptor_image=$(RECEPTOR_IMAGE)
awx-kube-dev-build: Dockerfile.kube-dev
docker build -f Dockerfile.kube-dev \
DOCKER_BUILDKIT=1 docker build -f Dockerfile.kube-dev \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--cache-from=$(DEV_DOCKER_TAG_BASE)/awx_kube_devel:$(COMPOSE_TAG) \
-t $(DEV_DOCKER_TAG_BASE)/awx_kube_devel:$(COMPOSE_TAG) .

View File

@@ -1,9 +1,3 @@
---
name: "\U0001F525 Security bug report"
about: How to report security vulnerabilities
---
For all security related bugs, email security@ansible.com instead of using this issue tracker and you will receive a prompt response.
For more information on the Ansible community's practices regarding responsible disclosure, see https://www.ansible.com/security

View File

@@ -6,9 +6,40 @@ import os
import sys
import warnings
from pkg_resources import get_distribution
__version__ = get_distribution('awx').version
def get_version():
version_from_file = get_version_from_file()
if version_from_file:
return version_from_file
else:
from setuptools_scm import get_version
version = get_version(root='..', relative_to=__file__)
return version
def get_version_from_file():
vf = version_file()
if vf:
with open(vf, 'r') as file:
return file.read().strip()
def version_file():
current_dir = os.path.dirname(os.path.abspath(__file__))
version_file = os.path.join(current_dir, '..', 'VERSION')
if os.path.exists(version_file):
return version_file
try:
import pkg_resources
__version__ = pkg_resources.get_distribution('awx').version
except pkg_resources.DistributionNotFound:
__version__ = get_version()
__all__ = ['__version__']
@@ -21,7 +52,6 @@ try:
except ImportError: # pragma: no cover
MODE = 'production'
import hashlib
try:
@@ -36,7 +66,6 @@ else:
from django.db.backends.utils import names_digest
from django.db import connection
if HAS_DJANGO is True:
# See upgrade blocker note in requirements/README.md
@@ -79,9 +108,10 @@ def oauth2_getattribute(self, attr):
# Custom method to override
# oauth2_provider.settings.OAuth2ProviderSettings.__getattribute__
from django.conf import settings
from oauth2_provider.settings import DEFAULTS
val = None
if 'migrate' not in sys.argv:
if (isinstance(attr, str)) and (attr in DEFAULTS) and (not attr.startswith('_')):
# certain Django OAuth Toolkit migrations actually reference
# setting lookups for references to model classes (e.g.,
# oauth2_settings.REFRESH_TOKEN_MODEL)

View File

@@ -6,7 +6,7 @@ import logging
# Django
from django.conf import settings
from django.utils.encoding import smart_text
from django.utils.encoding import smart_str
# Django REST Framework
from rest_framework import authentication
@@ -24,7 +24,7 @@ class LoggedBasicAuthentication(authentication.BasicAuthentication):
ret = super(LoggedBasicAuthentication, self).authenticate(request)
if ret:
username = ret[0].username if ret[0] else '<none>'
logger.info(smart_text(u"User {} performed a {} to {} through the API".format(username, request.method, request.path)))
logger.info(smart_str(u"User {} performed a {} to {} through the API".format(username, request.method, request.path)))
return ret
def authenticate_header(self, request):
@@ -45,7 +45,7 @@ class LoggedOAuth2Authentication(OAuth2Authentication):
user, token = ret
username = user.username if user else '<none>'
logger.info(
smart_text(u"User {} performed a {} to {} through the API using OAuth 2 token {}.".format(username, request.method, request.path, token.pk))
smart_str(u"User {} performed a {} to {} through the API using OAuth 2 token {}.".format(username, request.method, request.path, token.pk))
)
setattr(user, 'oauth_scopes', [x for x in token.scope.split() if x])
return ret

View File

@@ -1,6 +1,6 @@
# Django
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework import serializers

View File

@@ -2,7 +2,7 @@
# All Rights Reserved.
# Django
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework.exceptions import ValidationError
@@ -13,7 +13,7 @@ class ActiveJobConflict(ValidationError):
def __init__(self, active_jobs):
# During APIException.__init__(), Django Rest Framework
# turn everything in self.detail into string by using force_text.
# turn everything in self.detail into string by using force_str.
# Declare detail afterwards circumvent this behavior.
super(ActiveJobConflict, self).__init__()
self.detail = {"error": _("Resource is being used by running jobs."), "active_jobs": active_jobs}

View File

@@ -2,7 +2,7 @@
# All Rights Reserved.
# Django
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ObjectDoesNotExist
# Django REST Framework
@@ -28,13 +28,17 @@ class NullFieldMixin(object):
return (is_empty_value, data)
class BooleanNullField(NullFieldMixin, serializers.NullBooleanField):
class BooleanNullField(NullFieldMixin, serializers.BooleanField):
"""
Custom boolean field that allows null and empty string as False values.
"""
def __init__(self, **kwargs):
kwargs['allow_null'] = True
super().__init__(**kwargs)
def to_internal_value(self, data):
return bool(super(BooleanNullField, self).to_internal_value(data))
return bool(super().to_internal_value(data))
class CharNullField(NullFieldMixin, serializers.CharField):
@@ -47,7 +51,7 @@ class CharNullField(NullFieldMixin, serializers.CharField):
super(CharNullField, self).__init__(**kwargs)
def to_internal_value(self, data):
return super(CharNullField, self).to_internal_value(data or u'')
return super(CharNullField, self).to_internal_value(data or '')
class ChoiceNullField(NullFieldMixin, serializers.ChoiceField):
@@ -60,7 +64,7 @@ class ChoiceNullField(NullFieldMixin, serializers.ChoiceField):
super(ChoiceNullField, self).__init__(**kwargs)
def to_internal_value(self, data):
return super(ChoiceNullField, self).to_internal_value(data or u'')
return super(ChoiceNullField, self).to_internal_value(data or '')
class VerbatimField(serializers.Field):

View File

@@ -7,15 +7,15 @@ import json
from functools import reduce
# Django
from django.core.exceptions import FieldError, ValidationError
from django.core.exceptions import FieldError, ValidationError, FieldDoesNotExist
from django.db import models
from django.db.models import Q, CharField, IntegerField, BooleanField
from django.db.models.fields import FieldDoesNotExist
from django.db.models import Q, CharField, IntegerField, BooleanField, TextField, JSONField
from django.db.models.fields.related import ForeignObjectRel, ManyToManyField, ForeignKey
from django.db.models.functions import Cast
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework.exceptions import ParseError, PermissionDenied
@@ -185,16 +185,14 @@ class FieldLookupBackend(BaseFilterBackend):
return (field_list[-1], new_lookup)
def to_python_related(self, value):
value = force_text(value)
value = force_str(value)
if value.lower() in ('none', 'null'):
return None
else:
return int(value)
def value_to_python_for_field(self, field, value):
if isinstance(field, models.NullBooleanField):
return to_python_boolean(value, allow_none=True)
elif isinstance(field, models.BooleanField):
if isinstance(field, models.BooleanField):
return to_python_boolean(value)
elif isinstance(field, (ForeignObjectRel, ManyToManyField, GenericForeignKey, ForeignKey)):
try:
@@ -244,6 +242,8 @@ class FieldLookupBackend(BaseFilterBackend):
new_lookups.append('{}__{}__icontains'.format(new_lookup[:-8], rm_field.name))
return value, new_lookups, needs_distinct
else:
if isinstance(field, JSONField):
new_lookup = new_lookup.replace(field.name, f'{field.name}_as_txt')
value = self.value_to_python_for_field(field, value)
return value, new_lookup, needs_distinct
@@ -293,7 +293,7 @@ class FieldLookupBackend(BaseFilterBackend):
search_filter_relation = 'AND'
values = reduce(lambda list1, list2: list1 + list2, [i.split(',') for i in values])
for value in values:
search_value, new_keys, _ = self.value_to_python(queryset.model, key, force_text(value))
search_value, new_keys, _ = self.value_to_python(queryset.model, key, force_str(value))
assert isinstance(new_keys, list)
search_filters[search_value] = new_keys
# by definition, search *only* joins across relations,
@@ -325,6 +325,9 @@ class FieldLookupBackend(BaseFilterBackend):
value, new_key, distinct = self.value_to_python(queryset.model, key, value)
if distinct:
needs_distinct = True
if '_as_txt' in new_key:
fname = next(item for item in new_key.split('__') if item.endswith('_as_txt'))
queryset = queryset.annotate(**{fname: Cast(fname[:-7], output_field=TextField())})
if q_chain:
chain_filters.append((q_not, new_key, value))
elif q_or:
@@ -395,11 +398,11 @@ class OrderByBackend(BaseFilterBackend):
order_by = value.split(',')
else:
order_by = (value,)
if order_by is None:
order_by = self.get_default_ordering(view)
default_order_by = self.get_default_ordering(view)
# glue the order by and default order by together so that the default is the backup option
order_by = list(order_by or []) + list(default_order_by or [])
if order_by:
order_by = self._validate_ordering_fields(queryset.model, order_by)
# Special handling of the type field for ordering. In this
# case, we're not sorting exactly on the type field, but
# given the limited number of views with multiple types,

View File

@@ -10,18 +10,18 @@ import urllib.parse
# Django
from django.conf import settings
from django.contrib.auth import views as auth_views
from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from django.core.exceptions import FieldDoesNotExist
from django.db import connection
from django.db.models.fields import FieldDoesNotExist
from django.db.models.fields.related import OneToOneRel
from django.http import QueryDict
from django.shortcuts import get_object_or_404
from django.template.loader import render_to_string
from django.utils.encoding import smart_text
from django.utils.encoding import smart_str
from django.utils.safestring import mark_safe
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import views as auth_views
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework.exceptions import PermissionDenied, AuthenticationFailed, ParseError, NotAcceptable, UnsupportedMediaType
@@ -93,10 +93,10 @@ class LoggedLoginView(auth_views.LoginView):
ret = super(LoggedLoginView, self).post(request, *args, **kwargs)
current_user = getattr(request, 'user', None)
if request.user.is_authenticated:
logger.info(smart_text(u"User {} logged in from {}".format(self.request.user.username, request.META.get('REMOTE_ADDR', None))))
logger.info(smart_str(u"User {} logged in from {}".format(self.request.user.username, request.META.get('REMOTE_ADDR', None))))
ret.set_cookie('userLoggedIn', 'true')
current_user = UserSerializer(self.request.user)
current_user = smart_text(JSONRenderer().render(current_user.data))
current_user = smart_str(JSONRenderer().render(current_user.data))
current_user = urllib.parse.quote('%s' % current_user, '')
ret.set_cookie('current_user', current_user, secure=settings.SESSION_COOKIE_SECURE or None)
ret.setdefault('X-API-Session-Cookie-Name', getattr(settings, 'SESSION_COOKIE_NAME', 'awx_sessionid'))
@@ -104,7 +104,7 @@ class LoggedLoginView(auth_views.LoginView):
return ret
else:
if 'username' in self.request.POST:
logger.warn(smart_text(u"Login failed for user {} from {}".format(self.request.POST.get('username'), request.META.get('REMOTE_ADDR', None))))
logger.warning(smart_str(u"Login failed for user {} from {}".format(self.request.POST.get('username'), request.META.get('REMOTE_ADDR', None))))
ret.status_code = 401
return ret
@@ -392,8 +392,8 @@ class GenericAPIView(generics.GenericAPIView, APIView):
if hasattr(self.model._meta, "verbose_name"):
d.update(
{
'model_verbose_name': smart_text(self.model._meta.verbose_name),
'model_verbose_name_plural': smart_text(self.model._meta.verbose_name_plural),
'model_verbose_name': smart_str(self.model._meta.verbose_name),
'model_verbose_name_plural': smart_str(self.model._meta.verbose_name_plural),
}
)
serializer = self.get_serializer()
@@ -524,8 +524,8 @@ class SubListAPIView(ParentMixin, ListAPIView):
d = super(SubListAPIView, self).get_description_context()
d.update(
{
'parent_model_verbose_name': smart_text(self.parent_model._meta.verbose_name),
'parent_model_verbose_name_plural': smart_text(self.parent_model._meta.verbose_name_plural),
'parent_model_verbose_name': smart_str(self.parent_model._meta.verbose_name),
'parent_model_verbose_name_plural': smart_str(self.parent_model._meta.verbose_name_plural),
}
)
return d
@@ -638,6 +638,11 @@ class SubListCreateAttachDetachAPIView(SubListCreateAPIView):
# attaching/detaching them from the parent.
def is_valid_relation(self, parent, sub, created=False):
"Override in subclasses to do efficient validation of attaching"
return None
def is_valid_removal(self, parent, sub):
"Same as is_valid_relation but called on disassociation"
return None
def get_description_context(self):
@@ -722,6 +727,11 @@ class SubListCreateAttachDetachAPIView(SubListCreateAPIView):
if not request.user.can_access(self.parent_model, 'unattach', parent, sub, self.relationship, request.data):
raise PermissionDenied()
# Verify that removing the relationship is valid.
unattach_errors = self.is_valid_removal(parent, sub)
if unattach_errors is not None:
return Response(unattach_errors, status=status.HTTP_400_BAD_REQUEST)
if parent_key:
sub.delete()
else:

View File

@@ -6,11 +6,12 @@ from uuid import UUID
# Django
from django.core.exceptions import PermissionDenied
from django.db.models import JSONField
from django.db.models.fields import PositiveIntegerField, BooleanField
from django.db.models.fields.related import ForeignKey
from django.http import Http404
from django.utils.encoding import force_text, smart_text
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_str, smart_str
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework import exceptions
@@ -22,7 +23,7 @@ from rest_framework.request import clone_request
# AWX
from awx.api.fields import ChoiceNullField
from awx.main.fields import JSONField, ImplicitRoleField
from awx.main.fields import ImplicitRoleField
from awx.main.models import NotificationTemplate
from awx.main.utils.execution_environments import get_default_pod_spec
@@ -53,7 +54,7 @@ class Metadata(metadata.SimpleMetadata):
for attr in text_attrs:
value = getattr(field, attr, None)
if value is not None and value != '':
field_info[attr] = force_text(value, strings_only=True)
field_info[attr] = force_str(value, strings_only=True)
placeholder = getattr(field, 'placeholder', serializers.empty)
if placeholder is not serializers.empty:
@@ -77,7 +78,7 @@ class Metadata(metadata.SimpleMetadata):
}
if field.field_name in field_help_text:
opts = serializer.Meta.model._meta.concrete_model._meta
verbose_name = smart_text(opts.verbose_name)
verbose_name = smart_str(opts.verbose_name)
field_info['help_text'] = field_help_text[field.field_name].format(verbose_name)
if field.field_name == 'type':

View File

@@ -1,11 +1,11 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import MetricsView
urls = [url(r'^$', MetricsView.as_view(), name='metrics_view')]
urls = [re_path(r'^$', MetricsView.as_view(), name='metrics_view')]
__all__ = ['urls']

View File

@@ -5,7 +5,7 @@ import json
# Django
from django.conf import settings
from django.utils.encoding import smart_str
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework import parsers

View File

@@ -4,8 +4,6 @@
# Python
import logging
from django.conf import settings
# Django REST Framework
from rest_framework.exceptions import MethodNotAllowed, PermissionDenied
from rest_framework import permissions
@@ -250,13 +248,6 @@ class IsSystemAdminOrAuditor(permissions.BasePermission):
return request.user.is_superuser
class InstanceGroupTowerPermission(ModelAccessPermission):
def has_object_permission(self, request, view, obj):
if request.method == 'DELETE' and obj.name in [settings.DEFAULT_EXECUTION_QUEUE_NAME, settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME]:
return False
return super(InstanceGroupTowerPermission, self).has_object_permission(request, view, obj)
class WebhookKeyPermission(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return request.user.can_access(view.model, 'admin', obj, request.data)

View File

@@ -25,8 +25,8 @@ from django.contrib.auth.password_validation import validate_password as django_
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, ValidationError as DjangoValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_text
from django.utils.translation import gettext_lazy as _
from django.utils.encoding import force_str
from django.utils.text import capfirst
from django.utils.timezone import now
from django.utils.functional import cached_property
@@ -97,7 +97,7 @@ from awx.main.models import (
)
from awx.main.models.base import VERBOSITY_CHOICES, NEW_JOB_TYPE_CHOICES
from awx.main.models.rbac import get_roles_on_resource, role_summary_fields_generator
from awx.main.fields import ImplicitRoleField, JSONBField
from awx.main.fields import ImplicitRoleField
from awx.main.utils import (
get_type_for_model,
get_model_for_type,
@@ -113,6 +113,7 @@ from awx.main.utils import (
)
from awx.main.utils.filters import SmartFilter
from awx.main.utils.named_url_graph import reset_counters
from awx.main.scheduler.task_manager_models import TaskManagerInstanceGroups, TaskManagerInstances
from awx.main.redact import UriCleaner, REPLACE_STR
from awx.main.validators import vars_validate_or_raise
@@ -357,7 +358,7 @@ class BaseSerializer(serializers.ModelSerializer, metaclass=BaseSerializerMetacl
}
choices = []
for t in self.get_types():
name = _(type_name_map.get(t, force_text(get_model_for_type(t)._meta.verbose_name).title()))
name = _(type_name_map.get(t, force_str(get_model_for_type(t)._meta.verbose_name).title()))
choices.append((t, name))
return choices
@@ -645,7 +646,7 @@ class BaseSerializer(serializers.ModelSerializer, metaclass=BaseSerializerMetacl
v2.extend(e)
else:
v2.append(e)
d[k] = list(map(force_text, v2))
d[k] = list(map(force_str, v2))
raise ValidationError(d)
return attrs
@@ -1263,6 +1264,12 @@ class OAuth2ApplicationSerializer(BaseSerializer):
activity_stream=self.reverse('api:o_auth2_application_activity_stream_list', kwargs={'pk': obj.pk}),
)
)
if obj.organization_id:
res.update(
dict(
organization=self.reverse('api:organization_detail', kwargs={'pk': obj.organization_id}),
)
)
return res
def get_modified(self, obj):
@@ -1600,7 +1607,6 @@ class ProjectUpdateSerializer(UnifiedJobSerializer, ProjectOptionsSerializer):
class ProjectUpdateDetailSerializer(ProjectUpdateSerializer):
host_status_counts = serializers.SerializerMethodField(help_text=_('A count of hosts uniquely assigned to each status.'))
playbook_counts = serializers.SerializerMethodField(help_text=_('A count of all plays and tasks for the job run.'))
class Meta:
@@ -1615,14 +1621,6 @@ class ProjectUpdateDetailSerializer(ProjectUpdateSerializer):
return data
def get_host_status_counts(self, obj):
try:
counts = obj.project_update_events.only('event_data').get(event='playbook_on_stats').get_host_status_counts()
except ProjectUpdateEvent.DoesNotExist:
counts = {}
return counts
class ProjectUpdateListSerializer(ProjectUpdateSerializer, UnifiedJobListSerializer):
class Meta:
@@ -1718,7 +1716,7 @@ class InventorySerializer(LabelsListMixin, BaseSerializerWithVariables):
def validate_host_filter(self, host_filter):
if host_filter:
try:
for match in JSONBField.get_lookups().keys():
for match in models.JSONField.get_lookups().keys():
if match == 'exact':
# __exact is allowed
continue
@@ -1847,11 +1845,11 @@ class HostSerializer(BaseSerializerWithVariables):
if port < 1 or port > 65535:
raise ValueError
except ValueError:
raise serializers.ValidationError(_(u'Invalid port specification: %s') % force_text(port))
raise serializers.ValidationError(_(u'Invalid port specification: %s') % force_str(port))
return name, port
def validate_name(self, value):
name = force_text(value or '')
name = force_str(value or '')
# Validate here only, update in main validate method.
host, port = self._get_host_port_from_name(name)
return value
@@ -1865,13 +1863,13 @@ class HostSerializer(BaseSerializerWithVariables):
return vars_validate_or_raise(value)
def validate(self, attrs):
name = force_text(attrs.get('name', self.instance and self.instance.name or ''))
name = force_str(attrs.get('name', self.instance and self.instance.name or ''))
inventory = attrs.get('inventory', self.instance and self.instance.inventory or '')
host, port = self._get_host_port_from_name(name)
if port:
attrs['name'] = host
variables = force_text(attrs.get('variables', self.instance and self.instance.variables or ''))
variables = force_str(attrs.get('variables', self.instance and self.instance.variables or ''))
vars_dict = parse_yaml_or_json(variables)
vars_dict['ansible_ssh_port'] = port
attrs['variables'] = json.dumps(vars_dict)
@@ -1944,7 +1942,7 @@ class GroupSerializer(BaseSerializerWithVariables):
return res
def validate(self, attrs):
name = force_text(attrs.get('name', self.instance and self.instance.name or ''))
name = force_str(attrs.get('name', self.instance and self.instance.name or ''))
inventory = attrs.get('inventory', self.instance and self.instance.inventory or '')
if Host.objects.filter(name=name, inventory=inventory).exists():
raise serializers.ValidationError(_('A Host with that name already exists.'))
@@ -2075,7 +2073,7 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
class Meta:
model = InventorySource
fields = ('*', 'name', 'inventory', 'update_on_launch', 'update_cache_timeout', 'source_project', 'update_on_project_update') + (
fields = ('*', 'name', 'inventory', 'update_on_launch', 'update_cache_timeout', 'source_project') + (
'last_update_failed',
'last_updated',
) # Backwards compatibility.
@@ -2138,11 +2136,6 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
raise serializers.ValidationError(_("Cannot use manual project for SCM-based inventory."))
return value
def validate_update_on_project_update(self, value):
if value and self.instance and self.instance.schedules.exists():
raise serializers.ValidationError(_("Setting not compatible with existing schedules."))
return value
def validate_inventory(self, value):
if value and value.kind == 'smart':
raise serializers.ValidationError({"detail": _("Cannot create Inventory Source for Smart Inventory")})
@@ -2193,7 +2186,7 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
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.")})
else:
redundant_scm_fields = list(filter(lambda x: attrs.get(x, None), ['source_project', 'source_path', 'update_on_project_update']))
redundant_scm_fields = list(filter(lambda x: attrs.get(x, None), ['source_project', 'source_path']))
if redundant_scm_fields:
raise serializers.ValidationError({"detail": _("Cannot set %s if not SCM type." % ' '.join(redundant_scm_fields))})
@@ -2238,7 +2231,6 @@ class InventoryUpdateSerializer(UnifiedJobSerializer, InventorySourceOptionsSeri
'source_project_update',
'custom_virtualenv',
'instance_group',
'-controller_node',
)
def get_related(self, obj):
@@ -2313,7 +2305,6 @@ class InventoryUpdateDetailSerializer(InventoryUpdateSerializer):
class InventoryUpdateListSerializer(InventoryUpdateSerializer, UnifiedJobListSerializer):
class Meta:
model = InventoryUpdate
fields = ('*', '-controller_node') # field removal undone by UJ serializer
class InventoryUpdateCancelSerializer(InventoryUpdateSerializer):
@@ -2666,6 +2657,13 @@ class CredentialSerializer(BaseSerializer):
return credential_type
def validate_inputs(self, inputs):
if self.instance and self.instance.credential_type.kind == "vault":
if 'vault_id' in inputs and inputs['vault_id'] != self.instance.inputs['vault_id']:
raise ValidationError(_('Vault IDs cannot be changed once they have been created.'))
return inputs
class CredentialSerializerCreate(CredentialSerializer):
@@ -2838,8 +2836,8 @@ class JobOptionsSerializer(LabelsListMixin, BaseSerializer):
if not project:
raise serializers.ValidationError({'project': _('This field is required.')})
playbook_not_found = bool(
(project and project.scm_type and (not project.allow_override) and playbook and force_text(playbook) not in project.playbook_files)
or (project and not project.scm_type and playbook and force_text(playbook) not in project.playbooks) # manual
(project and project.scm_type and (not project.allow_override) and playbook and force_str(playbook) not in project.playbook_files)
or (project and not project.scm_type and playbook and force_str(playbook) not in project.playbooks) # manual
)
if playbook_not_found:
raise serializers.ValidationError({'playbook': _('Playbook not found for project.')})
@@ -3100,7 +3098,6 @@ class JobSerializer(UnifiedJobSerializer, JobOptionsSerializer):
class JobDetailSerializer(JobSerializer):
host_status_counts = serializers.SerializerMethodField(help_text=_('A count of hosts uniquely assigned to each status.'))
playbook_counts = serializers.SerializerMethodField(help_text=_('A count of all plays and tasks for the job run.'))
custom_virtualenv = serializers.ReadOnlyField()
@@ -3116,14 +3113,6 @@ class JobDetailSerializer(JobSerializer):
return data
def get_host_status_counts(self, obj):
try:
counts = obj.get_event_queryset().only('event_data').get(event='playbook_on_stats').get_host_status_counts()
except JobEvent.DoesNotExist:
counts = {}
return counts
class JobCancelSerializer(BaseSerializer):
@@ -3312,21 +3301,10 @@ class AdHocCommandSerializer(UnifiedJobSerializer):
class AdHocCommandDetailSerializer(AdHocCommandSerializer):
host_status_counts = serializers.SerializerMethodField(help_text=_('A count of hosts uniquely assigned to each status.'))
class Meta:
model = AdHocCommand
fields = ('*', 'host_status_counts')
def get_host_status_counts(self, obj):
try:
counts = obj.ad_hoc_command_events.only('event_data').get(event='playbook_on_stats').get_host_status_counts()
except AdHocCommandEvent.DoesNotExist:
counts = {}
return counts
class AdHocCommandCancelSerializer(AdHocCommandSerializer):
@@ -3628,7 +3606,7 @@ class LaunchConfigurationBaseSerializer(BaseSerializer):
job_tags = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
limit = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
skip_tags = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
diff_mode = serializers.NullBooleanField(required=False, default=None)
diff_mode = serializers.BooleanField(required=False, allow_null=True, default=None)
verbosity = serializers.ChoiceField(allow_null=True, required=False, default=None, choices=VERBOSITY_CHOICES)
exclude_errors = ()
@@ -4495,7 +4473,10 @@ class NotificationTemplateSerializer(BaseSerializer):
body = messages[event].get('body', {})
if body:
try:
potential_body = json.loads(body)
rendered_body = (
sandbox.ImmutableSandboxedEnvironment(undefined=DescriptiveUndefined).from_string(body).render(JobNotificationMixin.context_stub())
)
potential_body = json.loads(rendered_body)
if not isinstance(potential_body, dict):
error_list.append(
_("Webhook body for '{}' should be a json dictionary. Found type '{}'.".format(event, type(potential_body).__name__))
@@ -4638,69 +4619,74 @@ class SchedulePreviewSerializer(BaseSerializer):
# We reject rrules if:
# - DTSTART is not include
# - INTERVAL is not included
# - SECONDLY is used
# - TZID is used
# - BYDAY prefixed with a number (MO is good but not 20MO)
# - BYYEARDAY
# - BYWEEKNO
# - Multiple DTSTART or RRULE elements
# - Can't contain both COUNT and UNTIL
# - COUNT > 999
# - Multiple DTSTART
# - At least one of RRULE is not included
# - EXDATE or RDATE is included
# For any rule in the ruleset:
# - INTERVAL is not included
# - SECONDLY is used
# - BYDAY prefixed with a number (MO is good but not 20MO)
# - Can't contain both COUNT and UNTIL
# - COUNT > 999
def validate_rrule(self, value):
rrule_value = value
multi_by_month_day = r".*?BYMONTHDAY[\:\=][0-9]+,-*[0-9]+"
multi_by_month = r".*?BYMONTH[\:\=][0-9]+,[0-9]+"
by_day_with_numeric_prefix = r".*?BYDAY[\:\=][0-9]+[a-zA-Z]{2}"
match_count = re.match(r".*?(COUNT\=[0-9]+)", rrule_value)
match_multiple_dtstart = re.findall(r".*?(DTSTART(;[^:]+)?\:[0-9]+T[0-9]+Z?)", rrule_value)
match_native_dtstart = re.findall(r".*?(DTSTART:[0-9]+T[0-9]+) ", rrule_value)
match_multiple_rrule = re.findall(r".*?(RRULE\:)", rrule_value)
match_multiple_rrule = re.findall(r".*?(RULE\:[^\s]*)", rrule_value)
errors = []
if not len(match_multiple_dtstart):
raise serializers.ValidationError(_('Valid DTSTART required in rrule. Value should start with: DTSTART:YYYYMMDDTHHMMSSZ'))
errors.append(_('Valid DTSTART required in rrule. Value should start with: DTSTART:YYYYMMDDTHHMMSSZ'))
if len(match_native_dtstart):
raise serializers.ValidationError(_('DTSTART cannot be a naive datetime. Specify ;TZINFO= or YYYYMMDDTHHMMSSZZ.'))
errors.append(_('DTSTART cannot be a naive datetime. Specify ;TZINFO= or YYYYMMDDTHHMMSSZZ.'))
if len(match_multiple_dtstart) > 1:
raise serializers.ValidationError(_('Multiple DTSTART is not supported.'))
if not len(match_multiple_rrule):
raise serializers.ValidationError(_('RRULE required in rrule.'))
if len(match_multiple_rrule) > 1:
raise serializers.ValidationError(_('Multiple RRULE is not supported.'))
if 'interval' not in rrule_value.lower():
raise serializers.ValidationError(_('INTERVAL required in rrule.'))
if 'secondly' in rrule_value.lower():
raise serializers.ValidationError(_('SECONDLY is not supported.'))
if re.match(multi_by_month_day, rrule_value):
raise serializers.ValidationError(_('Multiple BYMONTHDAYs not supported.'))
if re.match(multi_by_month, rrule_value):
raise serializers.ValidationError(_('Multiple BYMONTHs not supported.'))
if re.match(by_day_with_numeric_prefix, rrule_value):
raise serializers.ValidationError(_("BYDAY with numeric prefix not supported."))
if 'byyearday' in rrule_value.lower():
raise serializers.ValidationError(_("BYYEARDAY not supported."))
if 'byweekno' in rrule_value.lower():
raise serializers.ValidationError(_("BYWEEKNO not supported."))
if 'COUNT' in rrule_value and 'UNTIL' in rrule_value:
raise serializers.ValidationError(_("RRULE may not contain both COUNT and UNTIL"))
if match_count:
count_val = match_count.groups()[0].strip().split("=")
if int(count_val[1]) > 999:
raise serializers.ValidationError(_("COUNT > 999 is unsupported."))
errors.append(_('Multiple DTSTART is not supported.'))
if "rrule:" not in rrule_value.lower():
errors.append(_('One or more rule required in rrule.'))
if "exdate:" in rrule_value.lower():
raise serializers.ValidationError(_('EXDATE not allowed in rrule.'))
if "rdate:" in rrule_value.lower():
raise serializers.ValidationError(_('RDATE not allowed in rrule.'))
for a_rule in match_multiple_rrule:
if 'interval' not in a_rule.lower():
errors.append("{0}: {1}".format(_('INTERVAL required in rrule'), a_rule))
elif 'secondly' in a_rule.lower():
errors.append("{0}: {1}".format(_('SECONDLY is not supported'), a_rule))
if re.match(by_day_with_numeric_prefix, a_rule):
errors.append("{0}: {1}".format(_("BYDAY with numeric prefix not supported"), a_rule))
if 'COUNT' in a_rule and 'UNTIL' in a_rule:
errors.append("{0}: {1}".format(_("RRULE may not contain both COUNT and UNTIL"), a_rule))
match_count = re.match(r".*?(COUNT\=[0-9]+)", a_rule)
if match_count:
count_val = match_count.groups()[0].strip().split("=")
if int(count_val[1]) > 999:
errors.append("{0}: {1}".format(_("COUNT > 999 is unsupported"), a_rule))
try:
Schedule.rrulestr(rrule_value)
except Exception as e:
import traceback
logger.error(traceback.format_exc())
raise serializers.ValidationError(_("rrule parsing failed validation: {}").format(e))
errors.append(_("rrule parsing failed validation: {}").format(e))
if errors:
raise serializers.ValidationError(errors)
return value
class ScheduleSerializer(LaunchConfigurationBaseSerializer, SchedulePreviewSerializer):
show_capabilities = ['edit', 'delete']
timezone = serializers.SerializerMethodField()
until = serializers.SerializerMethodField()
timezone = serializers.SerializerMethodField(
help_text=_(
'The timezone this schedule runs in. This field is extracted from the RRULE. If the timezone in the RRULE is a link to another timezone, the link will be reflected in this field.'
),
)
until = serializers.SerializerMethodField(
help_text=_('The date this schedule will end. This field is computed from the RRULE. If the schedule does not end an emptry string will be returned'),
)
class Meta:
model = Schedule
@@ -4754,13 +4740,6 @@ class ScheduleSerializer(LaunchConfigurationBaseSerializer, SchedulePreviewSeria
raise serializers.ValidationError(_('Inventory Source must be a cloud resource.'))
elif type(value) == Project and value.scm_type == '':
raise serializers.ValidationError(_('Manual Project cannot have a schedule set.'))
elif type(value) == InventorySource and value.source == 'scm' and value.update_on_project_update:
raise serializers.ValidationError(
_(
'Inventory sources with `update_on_project_update` cannot be scheduled. '
'Schedule its source project `{}` instead.'.format(value.source_project.name)
)
)
return value
def validate(self, attrs):
@@ -4850,6 +4829,11 @@ class InstanceSerializer(BaseSerializer):
else:
return float("{0:.2f}".format(((float(obj.capacity) - float(obj.consumed_capacity)) / (float(obj.capacity))) * 100))
def validate(self, attrs):
if self.instance.node_type == 'hop':
raise serializers.ValidationError(_('Hop node instances may not be changed.'))
return attrs
class InstanceHealthCheckSerializer(BaseSerializer):
class Meta:
@@ -4862,7 +4846,6 @@ class InstanceGroupSerializer(BaseSerializer):
show_capabilities = ['edit', 'delete']
committed_capacity = serializers.SerializerMethodField()
consumed_capacity = serializers.SerializerMethodField()
percent_capacity_remaining = serializers.SerializerMethodField()
jobs_running = serializers.IntegerField(
@@ -4911,7 +4894,6 @@ class InstanceGroupSerializer(BaseSerializer):
"created",
"modified",
"capacity",
"committed_capacity",
"consumed_capacity",
"percent_capacity_remaining",
"jobs_running",
@@ -4936,6 +4918,9 @@ class InstanceGroupSerializer(BaseSerializer):
return res
def validate_policy_instance_list(self, value):
if self.instance and self.instance.name in [settings.DEFAULT_EXECUTION_QUEUE_NAME, settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME]:
if self.instance.policy_instance_list != value:
raise serializers.ValidationError(_('%s instance group policy_instance_list may not be changed.' % self.instance.name))
for instance_name in value:
if value.count(instance_name) > 1:
raise serializers.ValidationError(_('Duplicate entry {}.').format(instance_name))
@@ -4946,6 +4931,11 @@ class InstanceGroupSerializer(BaseSerializer):
return value
def validate_policy_instance_percentage(self, value):
if self.instance and self.instance.name in [settings.DEFAULT_EXECUTION_QUEUE_NAME, settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME]:
if value != self.instance.policy_instance_percentage:
raise serializers.ValidationError(
_('%s instance group policy_instance_percentage may not be changed from the initial value set by the installer.' % self.instance.name)
)
if value and self.instance and self.instance.is_container_group:
raise serializers.ValidationError(_('Containerized instances may not be managed via the API'))
return value
@@ -4964,6 +4954,13 @@ class InstanceGroupSerializer(BaseSerializer):
return value
def validate_is_container_group(self, value):
if self.instance and self.instance.name in [settings.DEFAULT_EXECUTION_QUEUE_NAME, settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME]:
if value != self.instance.is_container_group:
raise serializers.ValidationError(_('%s instance group is_container_group may not be changed.' % self.instance.name))
return value
def validate_credential(self, value):
if value and not value.kubernetes:
raise serializers.ValidationError(_('Only Kubernetes credentials can be associated with an Instance Group'))
@@ -4977,30 +4974,29 @@ class InstanceGroupSerializer(BaseSerializer):
return attrs
def get_capacity_dict(self):
def get_ig_mgr(self):
# Store capacity values (globally computed) in the context
if 'capacity_map' not in self.context:
ig_qs = None
if 'task_manager_igs' not in self.context:
instance_groups_queryset = None
jobs_qs = UnifiedJob.objects.filter(status__in=('running', 'waiting'))
if self.parent: # Is ListView:
ig_qs = self.parent.instance
self.context['capacity_map'] = InstanceGroup.objects.capacity_values(qs=ig_qs, tasks=jobs_qs, breakdown=True)
return self.context['capacity_map']
instance_groups_queryset = self.parent.instance
instances = TaskManagerInstances(jobs_qs)
instance_groups = TaskManagerInstanceGroups(instances_by_hostname=instances, instance_groups_queryset=instance_groups_queryset)
self.context['task_manager_igs'] = instance_groups
return self.context['task_manager_igs']
def get_consumed_capacity(self, obj):
return self.get_capacity_dict()[obj.name]['running_capacity']
def get_committed_capacity(self, obj):
return self.get_capacity_dict()[obj.name]['committed_capacity']
ig_mgr = self.get_ig_mgr()
return ig_mgr.get_consumed_capacity(obj.name)
def get_percent_capacity_remaining(self, obj):
if not obj.capacity:
return 0.0
consumed = self.get_consumed_capacity(obj)
if consumed >= obj.capacity:
return 0.0
else:
return float("{0:.2f}".format(((float(obj.capacity) - float(consumed)) / (float(obj.capacity))) * 100))
ig_mgr = self.get_ig_mgr()
return float("{0:.2f}".format((float(ig_mgr.get_remaining_capacity(obj.name)) / (float(obj.capacity))) * 100))
def get_instances(self, obj):
return obj.instances.count()
@@ -5078,7 +5074,7 @@ class ActivityStreamSerializer(BaseSerializer):
try:
return json.loads(obj.changes)
except Exception:
logger.warn("Error deserializing activity stream json changes")
logger.warning("Error deserializing activity stream json changes")
return {}
def get_object_association(self, obj):

View File

@@ -0,0 +1,102 @@
# View a summary of children events
Special view to facilitate processing job output in the UI.
In order to collapse events and their children, the UI needs to know how
many children exist for a given event.
The UI also needs to know the order of the event (0 based index), which
usually matches the counter, but not always.
This view returns a JSON object where the key is the event counter, and the value
includes the number of children (and grandchildren) events.
Only events with children are included in the output.
## Example
e.g. Demo Job Template job
tuple(event counter, uuid, parent_uuid)
```
(1, '4598d19e-93b4-4e33-a0ae-b387a7348964', '')
(2, 'aae0d189-e3cb-102a-9f00-000000000006', '4598d19e-93b4-4e33-a0ae-b387a7348964')
(3, 'aae0d189-e3cb-102a-9f00-00000000000c', 'aae0d189-e3cb-102a-9f00-000000000006')
(4, 'f4194f14-e406-4124-8519-0fdb08b18f4b', 'aae0d189-e3cb-102a-9f00-00000000000c')
(5, '39f7ad99-dbf3-41e0-93f8-9999db4004f2', 'aae0d189-e3cb-102a-9f00-00000000000c')
(6, 'aae0d189-e3cb-102a-9f00-000000000008', 'aae0d189-e3cb-102a-9f00-000000000006')
(7, '39a49992-5ca4-4b6c-b178-e56d0b0333da', 'aae0d189-e3cb-102a-9f00-000000000008')
(8, '504f3b28-3ea8-4f6f-bd82-60cf8e807cc0', 'aae0d189-e3cb-102a-9f00-000000000008')
(9, 'a242be54-ebe6-4021-afab-f2878bff2e9f', '4598d19e-93b4-4e33-a0ae-b387a7348964')
```
output
```
{
"1": {
"rowNumber": 0,
"numChildren": 8
},
"2": {
"rowNumber": 1,
"numChildren": 6
},
"3": {
"rowNumber": 2,
"numChildren": 2
},
"6": {
"rowNumber": 5,
"numChildren": 2
}
}
"meta_event_nested_parent_uuid": {}
}
```
counter 1 is event 0, and has 8 children
counter 2 is event 1, and has 6 children
etc.
The UI also needs to be able to collapse over "meta" events -- events that
show up due to verbosity or warnings from the system while the play is running.
These events have a 0 level event, with no parent uuid.
```
playbook_on_start
verbose
playbook_on_play_start
playbook_on_task_start
runner_on_start <- level 3
verbose <- jump to level 0
verbose
runner_on_ok <- jump back to level 3
playbook_on_task_start
runner_on_start
runner_on_ok
verbose
verbose
playbook_on_stats
```
These verbose statements that fall in the middle of a series of children events
are problematic for the UI.
To help, this view will attempt to place the events into the hierarchy, without
the event level jumps.
```
playbook_on_start
verbose
playbook_on_play_start
playbook_on_task_start
runner_on_start <- A
verbose <- this maps to the uuid of A
verbose
runner_on_ok
playbook_on_task_start <- B
runner_on_start
runner_on_ok
verbose <- this maps to the uuid of B
verbose
playbook_on_stats
```
The output will include a JSON object where the key is the event counter,
and the value is the assigned nested uuid.

View File

@@ -1,14 +1,14 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import ActivityStreamList, ActivityStreamDetail
urls = [
url(r'^$', ActivityStreamList.as_view(), name='activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/$', ActivityStreamDetail.as_view(), name='activity_stream_detail'),
re_path(r'^$', ActivityStreamList.as_view(), name='activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/$', ActivityStreamDetail.as_view(), name='activity_stream_detail'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
AdHocCommandList,
@@ -16,14 +16,14 @@ from awx.api.views import (
urls = [
url(r'^$', AdHocCommandList.as_view(), name='ad_hoc_command_list'),
url(r'^(?P<pk>[0-9]+)/$', AdHocCommandDetail.as_view(), name='ad_hoc_command_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', AdHocCommandCancel.as_view(), name='ad_hoc_command_cancel'),
url(r'^(?P<pk>[0-9]+)/relaunch/$', AdHocCommandRelaunch.as_view(), name='ad_hoc_command_relaunch'),
url(r'^(?P<pk>[0-9]+)/events/$', AdHocCommandAdHocCommandEventsList.as_view(), name='ad_hoc_command_ad_hoc_command_events_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', AdHocCommandActivityStreamList.as_view(), name='ad_hoc_command_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notifications/$', AdHocCommandNotificationsList.as_view(), name='ad_hoc_command_notifications_list'),
url(r'^(?P<pk>[0-9]+)/stdout/$', AdHocCommandStdout.as_view(), name='ad_hoc_command_stdout'),
re_path(r'^$', AdHocCommandList.as_view(), name='ad_hoc_command_list'),
re_path(r'^(?P<pk>[0-9]+)/$', AdHocCommandDetail.as_view(), name='ad_hoc_command_detail'),
re_path(r'^(?P<pk>[0-9]+)/cancel/$', AdHocCommandCancel.as_view(), name='ad_hoc_command_cancel'),
re_path(r'^(?P<pk>[0-9]+)/relaunch/$', AdHocCommandRelaunch.as_view(), name='ad_hoc_command_relaunch'),
re_path(r'^(?P<pk>[0-9]+)/events/$', AdHocCommandAdHocCommandEventsList.as_view(), name='ad_hoc_command_ad_hoc_command_events_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', AdHocCommandActivityStreamList.as_view(), name='ad_hoc_command_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/notifications/$', AdHocCommandNotificationsList.as_view(), name='ad_hoc_command_notifications_list'),
re_path(r'^(?P<pk>[0-9]+)/stdout/$', AdHocCommandStdout.as_view(), name='ad_hoc_command_stdout'),
]
__all__ = ['urls']

View File

@@ -1,13 +1,13 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import AdHocCommandEventDetail
urls = [
url(r'^(?P<pk>[0-9]+)/$', AdHocCommandEventDetail.as_view(), name='ad_hoc_command_event_detail'),
re_path(r'^(?P<pk>[0-9]+)/$', AdHocCommandEventDetail.as_view(), name='ad_hoc_command_event_detail'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
CredentialList,
@@ -18,16 +18,16 @@ from awx.api.views import (
urls = [
url(r'^$', CredentialList.as_view(), name='credential_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', CredentialActivityStreamList.as_view(), name='credential_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/$', CredentialDetail.as_view(), name='credential_detail'),
url(r'^(?P<pk>[0-9]+)/access_list/$', CredentialAccessList.as_view(), name='credential_access_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', CredentialObjectRolesList.as_view(), name='credential_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/owner_users/$', CredentialOwnerUsersList.as_view(), name='credential_owner_users_list'),
url(r'^(?P<pk>[0-9]+)/owner_teams/$', CredentialOwnerTeamsList.as_view(), name='credential_owner_teams_list'),
url(r'^(?P<pk>[0-9]+)/copy/$', CredentialCopy.as_view(), name='credential_copy'),
url(r'^(?P<pk>[0-9]+)/input_sources/$', CredentialInputSourceSubList.as_view(), name='credential_input_source_sublist'),
url(r'^(?P<pk>[0-9]+)/test/$', CredentialExternalTest.as_view(), name='credential_external_test'),
re_path(r'^$', CredentialList.as_view(), name='credential_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', CredentialActivityStreamList.as_view(), name='credential_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/$', CredentialDetail.as_view(), name='credential_detail'),
re_path(r'^(?P<pk>[0-9]+)/access_list/$', CredentialAccessList.as_view(), name='credential_access_list'),
re_path(r'^(?P<pk>[0-9]+)/object_roles/$', CredentialObjectRolesList.as_view(), name='credential_object_roles_list'),
re_path(r'^(?P<pk>[0-9]+)/owner_users/$', CredentialOwnerUsersList.as_view(), name='credential_owner_users_list'),
re_path(r'^(?P<pk>[0-9]+)/owner_teams/$', CredentialOwnerTeamsList.as_view(), name='credential_owner_teams_list'),
re_path(r'^(?P<pk>[0-9]+)/copy/$', CredentialCopy.as_view(), name='credential_copy'),
re_path(r'^(?P<pk>[0-9]+)/input_sources/$', CredentialInputSourceSubList.as_view(), name='credential_input_source_sublist'),
re_path(r'^(?P<pk>[0-9]+)/test/$', CredentialExternalTest.as_view(), name='credential_external_test'),
]
__all__ = ['urls']

View File

@@ -1,14 +1,14 @@
# Copyright (c) 2019 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import CredentialInputSourceDetail, CredentialInputSourceList
urls = [
url(r'^$', CredentialInputSourceList.as_view(), name='credential_input_source_list'),
url(r'^(?P<pk>[0-9]+)/$', CredentialInputSourceDetail.as_view(), name='credential_input_source_detail'),
re_path(r'^$', CredentialInputSourceList.as_view(), name='credential_input_source_list'),
re_path(r'^(?P<pk>[0-9]+)/$', CredentialInputSourceDetail.as_view(), name='credential_input_source_detail'),
]
__all__ = ['urls']

View File

@@ -1,17 +1,17 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import CredentialTypeList, CredentialTypeDetail, CredentialTypeCredentialList, CredentialTypeActivityStreamList, CredentialTypeExternalTest
urls = [
url(r'^$', CredentialTypeList.as_view(), name='credential_type_list'),
url(r'^(?P<pk>[0-9]+)/$', CredentialTypeDetail.as_view(), name='credential_type_detail'),
url(r'^(?P<pk>[0-9]+)/credentials/$', CredentialTypeCredentialList.as_view(), name='credential_type_credential_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', CredentialTypeActivityStreamList.as_view(), name='credential_type_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/test/$', CredentialTypeExternalTest.as_view(), name='credential_type_external_test'),
re_path(r'^$', CredentialTypeList.as_view(), name='credential_type_list'),
re_path(r'^(?P<pk>[0-9]+)/$', CredentialTypeDetail.as_view(), name='credential_type_detail'),
re_path(r'^(?P<pk>[0-9]+)/credentials/$', CredentialTypeCredentialList.as_view(), name='credential_type_credential_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', CredentialTypeActivityStreamList.as_view(), name='credential_type_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/test/$', CredentialTypeExternalTest.as_view(), name='credential_type_external_test'),
]
__all__ = ['urls']

View File

@@ -1,4 +1,4 @@
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
ExecutionEnvironmentList,
@@ -10,11 +10,11 @@ from awx.api.views import (
urls = [
url(r'^$', ExecutionEnvironmentList.as_view(), name='execution_environment_list'),
url(r'^(?P<pk>[0-9]+)/$', ExecutionEnvironmentDetail.as_view(), name='execution_environment_detail'),
url(r'^(?P<pk>[0-9]+)/unified_job_templates/$', ExecutionEnvironmentJobTemplateList.as_view(), name='execution_environment_job_template_list'),
url(r'^(?P<pk>[0-9]+)/copy/$', ExecutionEnvironmentCopy.as_view(), name='execution_environment_copy'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', ExecutionEnvironmentActivityStreamList.as_view(), name='execution_environment_activity_stream_list'),
re_path(r'^$', ExecutionEnvironmentList.as_view(), name='execution_environment_list'),
re_path(r'^(?P<pk>[0-9]+)/$', ExecutionEnvironmentDetail.as_view(), name='execution_environment_detail'),
re_path(r'^(?P<pk>[0-9]+)/unified_job_templates/$', ExecutionEnvironmentJobTemplateList.as_view(), name='execution_environment_job_template_list'),
re_path(r'^(?P<pk>[0-9]+)/copy/$', ExecutionEnvironmentCopy.as_view(), name='execution_environment_copy'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', ExecutionEnvironmentActivityStreamList.as_view(), name='execution_environment_activity_stream_list'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
GroupList,
@@ -20,18 +20,18 @@ from awx.api.views import (
urls = [
url(r'^$', GroupList.as_view(), name='group_list'),
url(r'^(?P<pk>[0-9]+)/$', GroupDetail.as_view(), name='group_detail'),
url(r'^(?P<pk>[0-9]+)/children/$', GroupChildrenList.as_view(), name='group_children_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', GroupHostsList.as_view(), name='group_hosts_list'),
url(r'^(?P<pk>[0-9]+)/all_hosts/$', GroupAllHostsList.as_view(), name='group_all_hosts_list'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', GroupVariableData.as_view(), name='group_variable_data'),
url(r'^(?P<pk>[0-9]+)/job_events/$', GroupJobEventsList.as_view(), name='group_job_events_list'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', GroupJobHostSummariesList.as_view(), name='group_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/potential_children/$', GroupPotentialChildrenList.as_view(), name='group_potential_children_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', GroupActivityStreamList.as_view(), name='group_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', GroupInventorySourcesList.as_view(), name='group_inventory_sources_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', GroupAdHocCommandsList.as_view(), name='group_ad_hoc_commands_list'),
re_path(r'^$', GroupList.as_view(), name='group_list'),
re_path(r'^(?P<pk>[0-9]+)/$', GroupDetail.as_view(), name='group_detail'),
re_path(r'^(?P<pk>[0-9]+)/children/$', GroupChildrenList.as_view(), name='group_children_list'),
re_path(r'^(?P<pk>[0-9]+)/hosts/$', GroupHostsList.as_view(), name='group_hosts_list'),
re_path(r'^(?P<pk>[0-9]+)/all_hosts/$', GroupAllHostsList.as_view(), name='group_all_hosts_list'),
re_path(r'^(?P<pk>[0-9]+)/variable_data/$', GroupVariableData.as_view(), name='group_variable_data'),
re_path(r'^(?P<pk>[0-9]+)/job_events/$', GroupJobEventsList.as_view(), name='group_job_events_list'),
re_path(r'^(?P<pk>[0-9]+)/job_host_summaries/$', GroupJobHostSummariesList.as_view(), name='group_job_host_summaries_list'),
re_path(r'^(?P<pk>[0-9]+)/potential_children/$', GroupPotentialChildrenList.as_view(), name='group_potential_children_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', GroupActivityStreamList.as_view(), name='group_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/inventory_sources/$', GroupInventorySourcesList.as_view(), name='group_inventory_sources_list'),
re_path(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', GroupAdHocCommandsList.as_view(), name='group_ad_hoc_commands_list'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
HostList,
@@ -20,18 +20,18 @@ from awx.api.views import (
urls = [
url(r'^$', HostList.as_view(), name='host_list'),
url(r'^(?P<pk>[0-9]+)/$', HostDetail.as_view(), name='host_detail'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', HostVariableData.as_view(), name='host_variable_data'),
url(r'^(?P<pk>[0-9]+)/groups/$', HostGroupsList.as_view(), name='host_groups_list'),
url(r'^(?P<pk>[0-9]+)/all_groups/$', HostAllGroupsList.as_view(), name='host_all_groups_list'),
url(r'^(?P<pk>[0-9]+)/job_events/', HostJobEventsList.as_view(), name='host_job_events_list'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', HostJobHostSummariesList.as_view(), name='host_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', HostActivityStreamList.as_view(), name='host_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', HostInventorySourcesList.as_view(), name='host_inventory_sources_list'),
url(r'^(?P<pk>[0-9]+)/smart_inventories/$', HostSmartInventoriesList.as_view(), name='host_smart_inventories_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', HostAdHocCommandsList.as_view(), name='host_ad_hoc_commands_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_command_events/$', HostAdHocCommandEventsList.as_view(), name='host_ad_hoc_command_events_list'),
re_path(r'^$', HostList.as_view(), name='host_list'),
re_path(r'^(?P<pk>[0-9]+)/$', HostDetail.as_view(), name='host_detail'),
re_path(r'^(?P<pk>[0-9]+)/variable_data/$', HostVariableData.as_view(), name='host_variable_data'),
re_path(r'^(?P<pk>[0-9]+)/groups/$', HostGroupsList.as_view(), name='host_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/all_groups/$', HostAllGroupsList.as_view(), name='host_all_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/job_events/', HostJobEventsList.as_view(), name='host_job_events_list'),
re_path(r'^(?P<pk>[0-9]+)/job_host_summaries/$', HostJobHostSummariesList.as_view(), name='host_job_host_summaries_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', HostActivityStreamList.as_view(), name='host_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/inventory_sources/$', HostInventorySourcesList.as_view(), name='host_inventory_sources_list'),
re_path(r'^(?P<pk>[0-9]+)/smart_inventories/$', HostSmartInventoriesList.as_view(), name='host_smart_inventories_list'),
re_path(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', HostAdHocCommandsList.as_view(), name='host_ad_hoc_commands_list'),
re_path(r'^(?P<pk>[0-9]+)/ad_hoc_command_events/$', HostAdHocCommandEventsList.as_view(), name='host_ad_hoc_command_events_list'),
]
__all__ = ['urls']

View File

@@ -1,17 +1,17 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import InstanceList, InstanceDetail, InstanceUnifiedJobsList, InstanceInstanceGroupsList, InstanceHealthCheck
urls = [
url(r'^$', InstanceList.as_view(), name='instance_list'),
url(r'^(?P<pk>[0-9]+)/$', InstanceDetail.as_view(), name='instance_detail'),
url(r'^(?P<pk>[0-9]+)/jobs/$', InstanceUnifiedJobsList.as_view(), name='instance_unified_jobs_list'),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', InstanceInstanceGroupsList.as_view(), name='instance_instance_groups_list'),
url(r'^(?P<pk>[0-9]+)/health_check/$', InstanceHealthCheck.as_view(), name='instance_health_check'),
re_path(r'^$', InstanceList.as_view(), name='instance_list'),
re_path(r'^(?P<pk>[0-9]+)/$', InstanceDetail.as_view(), name='instance_detail'),
re_path(r'^(?P<pk>[0-9]+)/jobs/$', InstanceUnifiedJobsList.as_view(), name='instance_unified_jobs_list'),
re_path(r'^(?P<pk>[0-9]+)/instance_groups/$', InstanceInstanceGroupsList.as_view(), name='instance_instance_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/health_check/$', InstanceHealthCheck.as_view(), name='instance_health_check'),
]
__all__ = ['urls']

View File

@@ -1,16 +1,16 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import InstanceGroupList, InstanceGroupDetail, InstanceGroupUnifiedJobsList, InstanceGroupInstanceList
urls = [
url(r'^$', InstanceGroupList.as_view(), name='instance_group_list'),
url(r'^(?P<pk>[0-9]+)/$', InstanceGroupDetail.as_view(), name='instance_group_detail'),
url(r'^(?P<pk>[0-9]+)/jobs/$', InstanceGroupUnifiedJobsList.as_view(), name='instance_group_unified_jobs_list'),
url(r'^(?P<pk>[0-9]+)/instances/$', InstanceGroupInstanceList.as_view(), name='instance_group_instance_list'),
re_path(r'^$', InstanceGroupList.as_view(), name='instance_group_list'),
re_path(r'^(?P<pk>[0-9]+)/$', InstanceGroupDetail.as_view(), name='instance_group_detail'),
re_path(r'^(?P<pk>[0-9]+)/jobs/$', InstanceGroupUnifiedJobsList.as_view(), name='instance_group_unified_jobs_list'),
re_path(r'^(?P<pk>[0-9]+)/instances/$', InstanceGroupInstanceList.as_view(), name='instance_group_instance_list'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
InventoryList,
@@ -26,24 +26,24 @@ from awx.api.views import (
urls = [
url(r'^$', InventoryList.as_view(), name='inventory_list'),
url(r'^(?P<pk>[0-9]+)/$', InventoryDetail.as_view(), name='inventory_detail'),
url(r'^(?P<pk>[0-9]+)/hosts/$', InventoryHostsList.as_view(), name='inventory_hosts_list'),
url(r'^(?P<pk>[0-9]+)/groups/$', InventoryGroupsList.as_view(), name='inventory_groups_list'),
url(r'^(?P<pk>[0-9]+)/root_groups/$', InventoryRootGroupsList.as_view(), name='inventory_root_groups_list'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', InventoryVariableData.as_view(), name='inventory_variable_data'),
url(r'^(?P<pk>[0-9]+)/script/$', InventoryScriptView.as_view(), name='inventory_script_view'),
url(r'^(?P<pk>[0-9]+)/tree/$', InventoryTreeView.as_view(), name='inventory_tree_view'),
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', InventoryInventorySourcesList.as_view(), name='inventory_inventory_sources_list'),
url(r'^(?P<pk>[0-9]+)/update_inventory_sources/$', InventoryInventorySourcesUpdate.as_view(), name='inventory_inventory_sources_update'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', InventoryActivityStreamList.as_view(), name='inventory_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/job_templates/$', InventoryJobTemplateList.as_view(), name='inventory_job_template_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', InventoryAdHocCommandsList.as_view(), name='inventory_ad_hoc_commands_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', InventoryAccessList.as_view(), name='inventory_access_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', InventoryObjectRolesList.as_view(), name='inventory_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', InventoryInstanceGroupsList.as_view(), name='inventory_instance_groups_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', InventoryLabelList.as_view(), name='inventory_label_list'),
url(r'^(?P<pk>[0-9]+)/copy/$', InventoryCopy.as_view(), name='inventory_copy'),
re_path(r'^$', InventoryList.as_view(), name='inventory_list'),
re_path(r'^(?P<pk>[0-9]+)/$', InventoryDetail.as_view(), name='inventory_detail'),
re_path(r'^(?P<pk>[0-9]+)/hosts/$', InventoryHostsList.as_view(), name='inventory_hosts_list'),
re_path(r'^(?P<pk>[0-9]+)/groups/$', InventoryGroupsList.as_view(), name='inventory_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/root_groups/$', InventoryRootGroupsList.as_view(), name='inventory_root_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/variable_data/$', InventoryVariableData.as_view(), name='inventory_variable_data'),
re_path(r'^(?P<pk>[0-9]+)/script/$', InventoryScriptView.as_view(), name='inventory_script_view'),
re_path(r'^(?P<pk>[0-9]+)/tree/$', InventoryTreeView.as_view(), name='inventory_tree_view'),
re_path(r'^(?P<pk>[0-9]+)/inventory_sources/$', InventoryInventorySourcesList.as_view(), name='inventory_inventory_sources_list'),
re_path(r'^(?P<pk>[0-9]+)/update_inventory_sources/$', InventoryInventorySourcesUpdate.as_view(), name='inventory_inventory_sources_update'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', InventoryActivityStreamList.as_view(), name='inventory_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/job_templates/$', InventoryJobTemplateList.as_view(), name='inventory_job_template_list'),
re_path(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', InventoryAdHocCommandsList.as_view(), name='inventory_ad_hoc_commands_list'),
re_path(r'^(?P<pk>[0-9]+)/access_list/$', InventoryAccessList.as_view(), name='inventory_access_list'),
re_path(r'^(?P<pk>[0-9]+)/object_roles/$', InventoryObjectRolesList.as_view(), name='inventory_object_roles_list'),
re_path(r'^(?P<pk>[0-9]+)/instance_groups/$', InventoryInstanceGroupsList.as_view(), name='inventory_instance_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/labels/$', InventoryLabelList.as_view(), name='inventory_label_list'),
re_path(r'^(?P<pk>[0-9]+)/copy/$', InventoryCopy.as_view(), name='inventory_copy'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
InventorySourceList,
@@ -20,26 +20,26 @@ from awx.api.views import (
urls = [
url(r'^$', InventorySourceList.as_view(), name='inventory_source_list'),
url(r'^(?P<pk>[0-9]+)/$', InventorySourceDetail.as_view(), name='inventory_source_detail'),
url(r'^(?P<pk>[0-9]+)/update/$', InventorySourceUpdateView.as_view(), name='inventory_source_update_view'),
url(r'^(?P<pk>[0-9]+)/inventory_updates/$', InventorySourceUpdatesList.as_view(), name='inventory_source_updates_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', InventorySourceActivityStreamList.as_view(), name='inventory_source_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/schedules/$', InventorySourceSchedulesList.as_view(), name='inventory_source_schedules_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', InventorySourceCredentialsList.as_view(), name='inventory_source_credentials_list'),
url(r'^(?P<pk>[0-9]+)/groups/$', InventorySourceGroupsList.as_view(), name='inventory_source_groups_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', InventorySourceHostsList.as_view(), name='inventory_source_hosts_list'),
url(
re_path(r'^$', InventorySourceList.as_view(), name='inventory_source_list'),
re_path(r'^(?P<pk>[0-9]+)/$', InventorySourceDetail.as_view(), name='inventory_source_detail'),
re_path(r'^(?P<pk>[0-9]+)/update/$', InventorySourceUpdateView.as_view(), name='inventory_source_update_view'),
re_path(r'^(?P<pk>[0-9]+)/inventory_updates/$', InventorySourceUpdatesList.as_view(), name='inventory_source_updates_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', InventorySourceActivityStreamList.as_view(), name='inventory_source_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/schedules/$', InventorySourceSchedulesList.as_view(), name='inventory_source_schedules_list'),
re_path(r'^(?P<pk>[0-9]+)/credentials/$', InventorySourceCredentialsList.as_view(), name='inventory_source_credentials_list'),
re_path(r'^(?P<pk>[0-9]+)/groups/$', InventorySourceGroupsList.as_view(), name='inventory_source_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/hosts/$', InventorySourceHostsList.as_view(), name='inventory_source_hosts_list'),
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_started/$',
InventorySourceNotificationTemplatesStartedList.as_view(),
name='inventory_source_notification_templates_started_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_error/$',
InventorySourceNotificationTemplatesErrorList.as_view(),
name='inventory_source_notification_templates_error_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_success/$',
InventorySourceNotificationTemplatesSuccessList.as_view(),
name='inventory_source_notification_templates_success_list',

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
InventoryUpdateList,
@@ -15,13 +15,13 @@ from awx.api.views import (
urls = [
url(r'^$', InventoryUpdateList.as_view(), name='inventory_update_list'),
url(r'^(?P<pk>[0-9]+)/$', InventoryUpdateDetail.as_view(), name='inventory_update_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', InventoryUpdateCancel.as_view(), name='inventory_update_cancel'),
url(r'^(?P<pk>[0-9]+)/stdout/$', InventoryUpdateStdout.as_view(), name='inventory_update_stdout'),
url(r'^(?P<pk>[0-9]+)/notifications/$', InventoryUpdateNotificationsList.as_view(), name='inventory_update_notifications_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', InventoryUpdateCredentialsList.as_view(), name='inventory_update_credentials_list'),
url(r'^(?P<pk>[0-9]+)/events/$', InventoryUpdateEventsList.as_view(), name='inventory_update_events_list'),
re_path(r'^$', InventoryUpdateList.as_view(), name='inventory_update_list'),
re_path(r'^(?P<pk>[0-9]+)/$', InventoryUpdateDetail.as_view(), name='inventory_update_detail'),
re_path(r'^(?P<pk>[0-9]+)/cancel/$', InventoryUpdateCancel.as_view(), name='inventory_update_cancel'),
re_path(r'^(?P<pk>[0-9]+)/stdout/$', InventoryUpdateStdout.as_view(), name='inventory_update_stdout'),
re_path(r'^(?P<pk>[0-9]+)/notifications/$', InventoryUpdateNotificationsList.as_view(), name='inventory_update_notifications_list'),
re_path(r'^(?P<pk>[0-9]+)/credentials/$', InventoryUpdateCredentialsList.as_view(), name='inventory_update_credentials_list'),
re_path(r'^(?P<pk>[0-9]+)/events/$', InventoryUpdateEventsList.as_view(), name='inventory_update_events_list'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
JobList,
@@ -10,6 +10,7 @@ from awx.api.views import (
JobRelaunch,
JobCreateSchedule,
JobJobHostSummariesList,
JobJobEventsChildrenSummary,
JobJobEventsList,
JobActivityStreamList,
JobStdout,
@@ -20,18 +21,19 @@ from awx.api.views import (
urls = [
url(r'^$', JobList.as_view(), name='job_list'),
url(r'^(?P<pk>[0-9]+)/$', JobDetail.as_view(), name='job_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', JobCancel.as_view(), name='job_cancel'),
url(r'^(?P<pk>[0-9]+)/relaunch/$', JobRelaunch.as_view(), name='job_relaunch'),
url(r'^(?P<pk>[0-9]+)/create_schedule/$', JobCreateSchedule.as_view(), name='job_create_schedule'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', JobJobHostSummariesList.as_view(), name='job_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/job_events/$', JobJobEventsList.as_view(), name='job_job_events_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', JobActivityStreamList.as_view(), name='job_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/stdout/$', JobStdout.as_view(), name='job_stdout'),
url(r'^(?P<pk>[0-9]+)/notifications/$', JobNotificationsList.as_view(), name='job_notifications_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', JobLabelList.as_view(), name='job_label_list'),
url(r'^(?P<pk>[0-9]+)/$', JobHostSummaryDetail.as_view(), name='job_host_summary_detail'),
re_path(r'^$', JobList.as_view(), name='job_list'),
re_path(r'^(?P<pk>[0-9]+)/$', JobDetail.as_view(), name='job_detail'),
re_path(r'^(?P<pk>[0-9]+)/cancel/$', JobCancel.as_view(), name='job_cancel'),
re_path(r'^(?P<pk>[0-9]+)/relaunch/$', JobRelaunch.as_view(), name='job_relaunch'),
re_path(r'^(?P<pk>[0-9]+)/create_schedule/$', JobCreateSchedule.as_view(), name='job_create_schedule'),
re_path(r'^(?P<pk>[0-9]+)/job_host_summaries/$', JobJobHostSummariesList.as_view(), name='job_job_host_summaries_list'),
re_path(r'^(?P<pk>[0-9]+)/job_events/$', JobJobEventsList.as_view(), name='job_job_events_list'),
re_path(r'^(?P<pk>[0-9]+)/job_events/children_summary/$', JobJobEventsChildrenSummary.as_view(), name='job_job_events_children_summary'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', JobActivityStreamList.as_view(), name='job_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/stdout/$', JobStdout.as_view(), name='job_stdout'),
re_path(r'^(?P<pk>[0-9]+)/notifications/$', JobNotificationsList.as_view(), name='job_notifications_list'),
re_path(r'^(?P<pk>[0-9]+)/labels/$', JobLabelList.as_view(), name='job_label_list'),
re_path(r'^(?P<pk>[0-9]+)/$', JobHostSummaryDetail.as_view(), name='job_host_summary_detail'),
]
__all__ = ['urls']

View File

@@ -1,13 +1,13 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import JobEventDetail, JobEventChildrenList
urls = [
url(r'^(?P<pk>[0-9]+)/$', JobEventDetail.as_view(), name='job_event_detail'),
url(r'^(?P<pk>[0-9]+)/children/$', JobEventChildrenList.as_view(), name='job_event_children_list'),
re_path(r'^(?P<pk>[0-9]+)/$', JobEventDetail.as_view(), name='job_event_detail'),
re_path(r'^(?P<pk>[0-9]+)/children/$', JobEventChildrenList.as_view(), name='job_event_children_list'),
]
__all__ = ['urls']

View File

@@ -1,11 +1,11 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import JobHostSummaryDetail
urls = [url(r'^(?P<pk>[0-9]+)/$', JobHostSummaryDetail.as_view(), name='job_host_summary_detail')]
urls = [re_path(r'^(?P<pk>[0-9]+)/$', JobHostSummaryDetail.as_view(), name='job_host_summary_detail')]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import include, url
from django.urls import include, re_path
from awx.api.views import (
JobTemplateList,
@@ -25,36 +25,36 @@ from awx.api.views import (
urls = [
url(r'^$', JobTemplateList.as_view(), name='job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', JobTemplateDetail.as_view(), name='job_template_detail'),
url(r'^(?P<pk>[0-9]+)/launch/$', JobTemplateLaunch.as_view(), name='job_template_launch'),
url(r'^(?P<pk>[0-9]+)/jobs/$', JobTemplateJobsList.as_view(), name='job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/slice_workflow_jobs/$', JobTemplateSliceWorkflowJobsList.as_view(), name='job_template_slice_workflow_jobs_list'),
url(r'^(?P<pk>[0-9]+)/callback/$', JobTemplateCallback.as_view(), name='job_template_callback'),
url(r'^(?P<pk>[0-9]+)/schedules/$', JobTemplateSchedulesList.as_view(), name='job_template_schedules_list'),
url(r'^(?P<pk>[0-9]+)/survey_spec/$', JobTemplateSurveySpec.as_view(), name='job_template_survey_spec'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', JobTemplateActivityStreamList.as_view(), name='job_template_activity_stream_list'),
url(
re_path(r'^$', JobTemplateList.as_view(), name='job_template_list'),
re_path(r'^(?P<pk>[0-9]+)/$', JobTemplateDetail.as_view(), name='job_template_detail'),
re_path(r'^(?P<pk>[0-9]+)/launch/$', JobTemplateLaunch.as_view(), name='job_template_launch'),
re_path(r'^(?P<pk>[0-9]+)/jobs/$', JobTemplateJobsList.as_view(), name='job_template_jobs_list'),
re_path(r'^(?P<pk>[0-9]+)/slice_workflow_jobs/$', JobTemplateSliceWorkflowJobsList.as_view(), name='job_template_slice_workflow_jobs_list'),
re_path(r'^(?P<pk>[0-9]+)/callback/$', JobTemplateCallback.as_view(), name='job_template_callback'),
re_path(r'^(?P<pk>[0-9]+)/schedules/$', JobTemplateSchedulesList.as_view(), name='job_template_schedules_list'),
re_path(r'^(?P<pk>[0-9]+)/survey_spec/$', JobTemplateSurveySpec.as_view(), name='job_template_survey_spec'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', JobTemplateActivityStreamList.as_view(), name='job_template_activity_stream_list'),
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_started/$',
JobTemplateNotificationTemplatesStartedList.as_view(),
name='job_template_notification_templates_started_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_error/$',
JobTemplateNotificationTemplatesErrorList.as_view(),
name='job_template_notification_templates_error_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_success/$',
JobTemplateNotificationTemplatesSuccessList.as_view(),
name='job_template_notification_templates_success_list',
),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', JobTemplateInstanceGroupsList.as_view(), name='job_template_instance_groups_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', JobTemplateAccessList.as_view(), name='job_template_access_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', JobTemplateObjectRolesList.as_view(), name='job_template_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', JobTemplateLabelList.as_view(), name='job_template_label_list'),
url(r'^(?P<pk>[0-9]+)/copy/$', JobTemplateCopy.as_view(), name='job_template_copy'),
url(r'^(?P<pk>[0-9]+)/', include('awx.api.urls.webhooks'), {'model_kwarg': 'job_templates'}),
re_path(r'^(?P<pk>[0-9]+)/instance_groups/$', JobTemplateInstanceGroupsList.as_view(), name='job_template_instance_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/access_list/$', JobTemplateAccessList.as_view(), name='job_template_access_list'),
re_path(r'^(?P<pk>[0-9]+)/object_roles/$', JobTemplateObjectRolesList.as_view(), name='job_template_object_roles_list'),
re_path(r'^(?P<pk>[0-9]+)/labels/$', JobTemplateLabelList.as_view(), name='job_template_label_list'),
re_path(r'^(?P<pk>[0-9]+)/copy/$', JobTemplateCopy.as_view(), name='job_template_copy'),
re_path(r'^(?P<pk>[0-9]+)/', include('awx.api.urls.webhooks'), {'model_kwarg': 'job_templates'}),
]
__all__ = ['urls']

View File

@@ -1,11 +1,11 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import LabelList, LabelDetail
urls = [url(r'^$', LabelList.as_view(), name='label_list'), url(r'^(?P<pk>[0-9]+)/$', LabelDetail.as_view(), name='label_detail')]
urls = [re_path(r'^$', LabelList.as_view(), name='label_list'), re_path(r'^(?P<pk>[0-9]+)/$', LabelDetail.as_view(), name='label_detail')]
__all__ = ['urls']

View File

@@ -1,11 +1,14 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import NotificationList, NotificationDetail
urls = [url(r'^$', NotificationList.as_view(), name='notification_list'), url(r'^(?P<pk>[0-9]+)/$', NotificationDetail.as_view(), name='notification_detail')]
urls = [
re_path(r'^$', NotificationList.as_view(), name='notification_list'),
re_path(r'^(?P<pk>[0-9]+)/$', NotificationDetail.as_view(), name='notification_detail'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
NotificationTemplateList,
@@ -13,11 +13,11 @@ from awx.api.views import (
urls = [
url(r'^$', NotificationTemplateList.as_view(), name='notification_template_list'),
url(r'^(?P<pk>[0-9]+)/$', NotificationTemplateDetail.as_view(), name='notification_template_detail'),
url(r'^(?P<pk>[0-9]+)/test/$', NotificationTemplateTest.as_view(), name='notification_template_test'),
url(r'^(?P<pk>[0-9]+)/notifications/$', NotificationTemplateNotificationList.as_view(), name='notification_template_notification_list'),
url(r'^(?P<pk>[0-9]+)/copy/$', NotificationTemplateCopy.as_view(), name='notification_template_copy'),
re_path(r'^$', NotificationTemplateList.as_view(), name='notification_template_list'),
re_path(r'^(?P<pk>[0-9]+)/$', NotificationTemplateDetail.as_view(), name='notification_template_detail'),
re_path(r'^(?P<pk>[0-9]+)/test/$', NotificationTemplateTest.as_view(), name='notification_template_test'),
re_path(r'^(?P<pk>[0-9]+)/notifications/$', NotificationTemplateNotificationList.as_view(), name='notification_template_notification_list'),
re_path(r'^(?P<pk>[0-9]+)/copy/$', NotificationTemplateCopy.as_view(), name='notification_template_copy'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
OAuth2ApplicationList,
@@ -15,13 +15,13 @@ from awx.api.views import (
urls = [
url(r'^applications/$', OAuth2ApplicationList.as_view(), name='o_auth2_application_list'),
url(r'^applications/(?P<pk>[0-9]+)/$', OAuth2ApplicationDetail.as_view(), name='o_auth2_application_detail'),
url(r'^applications/(?P<pk>[0-9]+)/tokens/$', ApplicationOAuth2TokenList.as_view(), name='o_auth2_application_token_list'),
url(r'^applications/(?P<pk>[0-9]+)/activity_stream/$', OAuth2ApplicationActivityStreamList.as_view(), name='o_auth2_application_activity_stream_list'),
url(r'^tokens/$', OAuth2TokenList.as_view(), name='o_auth2_token_list'),
url(r'^tokens/(?P<pk>[0-9]+)/$', OAuth2TokenDetail.as_view(), name='o_auth2_token_detail'),
url(r'^tokens/(?P<pk>[0-9]+)/activity_stream/$', OAuth2TokenActivityStreamList.as_view(), name='o_auth2_token_activity_stream_list'),
re_path(r'^applications/$', OAuth2ApplicationList.as_view(), name='o_auth2_application_list'),
re_path(r'^applications/(?P<pk>[0-9]+)/$', OAuth2ApplicationDetail.as_view(), name='o_auth2_application_detail'),
re_path(r'^applications/(?P<pk>[0-9]+)/tokens/$', ApplicationOAuth2TokenList.as_view(), name='o_auth2_application_token_list'),
re_path(r'^applications/(?P<pk>[0-9]+)/activity_stream/$', OAuth2ApplicationActivityStreamList.as_view(), name='o_auth2_application_activity_stream_list'),
re_path(r'^tokens/$', OAuth2TokenList.as_view(), name='o_auth2_token_list'),
re_path(r'^tokens/(?P<pk>[0-9]+)/$', OAuth2TokenDetail.as_view(), name='o_auth2_token_detail'),
re_path(r'^tokens/(?P<pk>[0-9]+)/activity_stream/$', OAuth2TokenActivityStreamList.as_view(), name='o_auth2_token_activity_stream_list'),
]
__all__ = ['urls']

View File

@@ -4,7 +4,7 @@ from datetime import timedelta
from django.utils.timezone import now
from django.conf import settings
from django.conf.urls import url
from django.urls import re_path
from oauthlib import oauth2
from oauth2_provider import views
@@ -35,10 +35,10 @@ class TokenView(views.TokenView):
urls = [
url(r'^$', ApiOAuthAuthorizationRootView.as_view(), name='oauth_authorization_root_view'),
url(r"^authorize/$", views.AuthorizationView.as_view(), name="authorize"),
url(r"^token/$", TokenView.as_view(), name="token"),
url(r"^revoke_token/$", views.RevokeTokenView.as_view(), name="revoke-token"),
re_path(r'^$', ApiOAuthAuthorizationRootView.as_view(), name='oauth_authorization_root_view'),
re_path(r"^authorize/$", views.AuthorizationView.as_view(), name="authorize"),
re_path(r"^token/$", TokenView.as_view(), name="token"),
re_path(r"^revoke_token/$", views.RevokeTokenView.as_view(), name="revoke-token"),
]

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
OrganizationList,
@@ -30,44 +30,44 @@ from awx.api.views import (
urls = [
url(r'^$', OrganizationList.as_view(), name='organization_list'),
url(r'^(?P<pk>[0-9]+)/$', OrganizationDetail.as_view(), name='organization_detail'),
url(r'^(?P<pk>[0-9]+)/users/$', OrganizationUsersList.as_view(), name='organization_users_list'),
url(r'^(?P<pk>[0-9]+)/admins/$', OrganizationAdminsList.as_view(), name='organization_admins_list'),
url(r'^(?P<pk>[0-9]+)/inventories/$', OrganizationInventoriesList.as_view(), name='organization_inventories_list'),
url(r'^(?P<pk>[0-9]+)/execution_environments/$', OrganizationExecutionEnvironmentsList.as_view(), name='organization_execution_environments_list'),
url(r'^(?P<pk>[0-9]+)/projects/$', OrganizationProjectsList.as_view(), name='organization_projects_list'),
url(r'^(?P<pk>[0-9]+)/job_templates/$', OrganizationJobTemplatesList.as_view(), name='organization_job_templates_list'),
url(r'^(?P<pk>[0-9]+)/workflow_job_templates/$', OrganizationWorkflowJobTemplatesList.as_view(), name='organization_workflow_job_templates_list'),
url(r'^(?P<pk>[0-9]+)/teams/$', OrganizationTeamsList.as_view(), name='organization_teams_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', OrganizationCredentialList.as_view(), name='organization_credential_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', OrganizationActivityStreamList.as_view(), name='organization_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates/$', OrganizationNotificationTemplatesList.as_view(), name='organization_notification_templates_list'),
url(
re_path(r'^$', OrganizationList.as_view(), name='organization_list'),
re_path(r'^(?P<pk>[0-9]+)/$', OrganizationDetail.as_view(), name='organization_detail'),
re_path(r'^(?P<pk>[0-9]+)/users/$', OrganizationUsersList.as_view(), name='organization_users_list'),
re_path(r'^(?P<pk>[0-9]+)/admins/$', OrganizationAdminsList.as_view(), name='organization_admins_list'),
re_path(r'^(?P<pk>[0-9]+)/inventories/$', OrganizationInventoriesList.as_view(), name='organization_inventories_list'),
re_path(r'^(?P<pk>[0-9]+)/execution_environments/$', OrganizationExecutionEnvironmentsList.as_view(), name='organization_execution_environments_list'),
re_path(r'^(?P<pk>[0-9]+)/projects/$', OrganizationProjectsList.as_view(), name='organization_projects_list'),
re_path(r'^(?P<pk>[0-9]+)/job_templates/$', OrganizationJobTemplatesList.as_view(), name='organization_job_templates_list'),
re_path(r'^(?P<pk>[0-9]+)/workflow_job_templates/$', OrganizationWorkflowJobTemplatesList.as_view(), name='organization_workflow_job_templates_list'),
re_path(r'^(?P<pk>[0-9]+)/teams/$', OrganizationTeamsList.as_view(), name='organization_teams_list'),
re_path(r'^(?P<pk>[0-9]+)/credentials/$', OrganizationCredentialList.as_view(), name='organization_credential_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', OrganizationActivityStreamList.as_view(), name='organization_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/notification_templates/$', OrganizationNotificationTemplatesList.as_view(), name='organization_notification_templates_list'),
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_started/$',
OrganizationNotificationTemplatesStartedList.as_view(),
name='organization_notification_templates_started_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_error/$',
OrganizationNotificationTemplatesErrorList.as_view(),
name='organization_notification_templates_error_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_success/$',
OrganizationNotificationTemplatesSuccessList.as_view(),
name='organization_notification_templates_success_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_approvals/$',
OrganizationNotificationTemplatesApprovalList.as_view(),
name='organization_notification_templates_approvals_list',
),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', OrganizationInstanceGroupsList.as_view(), name='organization_instance_groups_list'),
url(r'^(?P<pk>[0-9]+)/galaxy_credentials/$', OrganizationGalaxyCredentialsList.as_view(), name='organization_galaxy_credentials_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', OrganizationObjectRolesList.as_view(), name='organization_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', OrganizationAccessList.as_view(), name='organization_access_list'),
url(r'^(?P<pk>[0-9]+)/applications/$', OrganizationApplicationList.as_view(), name='organization_applications_list'),
re_path(r'^(?P<pk>[0-9]+)/instance_groups/$', OrganizationInstanceGroupsList.as_view(), name='organization_instance_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/galaxy_credentials/$', OrganizationGalaxyCredentialsList.as_view(), name='organization_galaxy_credentials_list'),
re_path(r'^(?P<pk>[0-9]+)/object_roles/$', OrganizationObjectRolesList.as_view(), name='organization_object_roles_list'),
re_path(r'^(?P<pk>[0-9]+)/access_list/$', OrganizationAccessList.as_view(), name='organization_access_list'),
re_path(r'^(?P<pk>[0-9]+)/applications/$', OrganizationApplicationList.as_view(), name='organization_applications_list'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
ProjectList,
@@ -24,30 +24,32 @@ from awx.api.views import (
urls = [
url(r'^$', ProjectList.as_view(), name='project_list'),
url(r'^(?P<pk>[0-9]+)/$', ProjectDetail.as_view(), name='project_detail'),
url(r'^(?P<pk>[0-9]+)/playbooks/$', ProjectPlaybooks.as_view(), name='project_playbooks'),
url(r'^(?P<pk>[0-9]+)/inventories/$', ProjectInventories.as_view(), name='project_inventories'),
url(r'^(?P<pk>[0-9]+)/scm_inventory_sources/$', ProjectScmInventorySources.as_view(), name='project_scm_inventory_sources'),
url(r'^(?P<pk>[0-9]+)/teams/$', ProjectTeamsList.as_view(), name='project_teams_list'),
url(r'^(?P<pk>[0-9]+)/update/$', ProjectUpdateView.as_view(), name='project_update_view'),
url(r'^(?P<pk>[0-9]+)/project_updates/$', ProjectUpdatesList.as_view(), name='project_updates_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', ProjectActivityStreamList.as_view(), name='project_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/schedules/$', ProjectSchedulesList.as_view(), name='project_schedules_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', ProjectNotificationTemplatesErrorList.as_view(), name='project_notification_templates_error_list'),
url(
re_path(r'^$', ProjectList.as_view(), name='project_list'),
re_path(r'^(?P<pk>[0-9]+)/$', ProjectDetail.as_view(), name='project_detail'),
re_path(r'^(?P<pk>[0-9]+)/playbooks/$', ProjectPlaybooks.as_view(), name='project_playbooks'),
re_path(r'^(?P<pk>[0-9]+)/inventories/$', ProjectInventories.as_view(), name='project_inventories'),
re_path(r'^(?P<pk>[0-9]+)/scm_inventory_sources/$', ProjectScmInventorySources.as_view(), name='project_scm_inventory_sources'),
re_path(r'^(?P<pk>[0-9]+)/teams/$', ProjectTeamsList.as_view(), name='project_teams_list'),
re_path(r'^(?P<pk>[0-9]+)/update/$', ProjectUpdateView.as_view(), name='project_update_view'),
re_path(r'^(?P<pk>[0-9]+)/project_updates/$', ProjectUpdatesList.as_view(), name='project_updates_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', ProjectActivityStreamList.as_view(), name='project_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/schedules/$', ProjectSchedulesList.as_view(), name='project_schedules_list'),
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_error/$', ProjectNotificationTemplatesErrorList.as_view(), name='project_notification_templates_error_list'
),
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_success/$',
ProjectNotificationTemplatesSuccessList.as_view(),
name='project_notification_templates_success_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_started/$',
ProjectNotificationTemplatesStartedList.as_view(),
name='project_notification_templates_started_list',
),
url(r'^(?P<pk>[0-9]+)/object_roles/$', ProjectObjectRolesList.as_view(), name='project_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', ProjectAccessList.as_view(), name='project_access_list'),
url(r'^(?P<pk>[0-9]+)/copy/$', ProjectCopy.as_view(), name='project_copy'),
re_path(r'^(?P<pk>[0-9]+)/object_roles/$', ProjectObjectRolesList.as_view(), name='project_object_roles_list'),
re_path(r'^(?P<pk>[0-9]+)/access_list/$', ProjectAccessList.as_view(), name='project_access_list'),
re_path(r'^(?P<pk>[0-9]+)/copy/$', ProjectCopy.as_view(), name='project_copy'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
ProjectUpdateList,
@@ -15,13 +15,13 @@ from awx.api.views import (
urls = [
url(r'^$', ProjectUpdateList.as_view(), name='project_update_list'),
url(r'^(?P<pk>[0-9]+)/$', ProjectUpdateDetail.as_view(), name='project_update_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', ProjectUpdateCancel.as_view(), name='project_update_cancel'),
url(r'^(?P<pk>[0-9]+)/stdout/$', ProjectUpdateStdout.as_view(), name='project_update_stdout'),
url(r'^(?P<pk>[0-9]+)/scm_inventory_updates/$', ProjectUpdateScmInventoryUpdates.as_view(), name='project_update_scm_inventory_updates'),
url(r'^(?P<pk>[0-9]+)/notifications/$', ProjectUpdateNotificationsList.as_view(), name='project_update_notifications_list'),
url(r'^(?P<pk>[0-9]+)/events/$', ProjectUpdateEventsList.as_view(), name='project_update_events_list'),
re_path(r'^$', ProjectUpdateList.as_view(), name='project_update_list'),
re_path(r'^(?P<pk>[0-9]+)/$', ProjectUpdateDetail.as_view(), name='project_update_detail'),
re_path(r'^(?P<pk>[0-9]+)/cancel/$', ProjectUpdateCancel.as_view(), name='project_update_cancel'),
re_path(r'^(?P<pk>[0-9]+)/stdout/$', ProjectUpdateStdout.as_view(), name='project_update_stdout'),
re_path(r'^(?P<pk>[0-9]+)/scm_inventory_updates/$', ProjectUpdateScmInventoryUpdates.as_view(), name='project_update_scm_inventory_updates'),
re_path(r'^(?P<pk>[0-9]+)/notifications/$', ProjectUpdateNotificationsList.as_view(), name='project_update_notifications_list'),
re_path(r'^(?P<pk>[0-9]+)/events/$', ProjectUpdateEventsList.as_view(), name='project_update_events_list'),
]
__all__ = ['urls']

View File

@@ -1,18 +1,18 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import RoleList, RoleDetail, RoleUsersList, RoleTeamsList, RoleParentsList, RoleChildrenList
urls = [
url(r'^$', RoleList.as_view(), name='role_list'),
url(r'^(?P<pk>[0-9]+)/$', RoleDetail.as_view(), name='role_detail'),
url(r'^(?P<pk>[0-9]+)/users/$', RoleUsersList.as_view(), name='role_users_list'),
url(r'^(?P<pk>[0-9]+)/teams/$', RoleTeamsList.as_view(), name='role_teams_list'),
url(r'^(?P<pk>[0-9]+)/parents/$', RoleParentsList.as_view(), name='role_parents_list'),
url(r'^(?P<pk>[0-9]+)/children/$', RoleChildrenList.as_view(), name='role_children_list'),
re_path(r'^$', RoleList.as_view(), name='role_list'),
re_path(r'^(?P<pk>[0-9]+)/$', RoleDetail.as_view(), name='role_detail'),
re_path(r'^(?P<pk>[0-9]+)/users/$', RoleUsersList.as_view(), name='role_users_list'),
re_path(r'^(?P<pk>[0-9]+)/teams/$', RoleTeamsList.as_view(), name='role_teams_list'),
re_path(r'^(?P<pk>[0-9]+)/parents/$', RoleParentsList.as_view(), name='role_parents_list'),
re_path(r'^(?P<pk>[0-9]+)/children/$', RoleChildrenList.as_view(), name='role_children_list'),
]
__all__ = ['urls']

View File

@@ -1,16 +1,16 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import ScheduleList, ScheduleDetail, ScheduleUnifiedJobsList, ScheduleCredentialsList
urls = [
url(r'^$', ScheduleList.as_view(), name='schedule_list'),
url(r'^(?P<pk>[0-9]+)/$', ScheduleDetail.as_view(), name='schedule_detail'),
url(r'^(?P<pk>[0-9]+)/jobs/$', ScheduleUnifiedJobsList.as_view(), name='schedule_unified_jobs_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', ScheduleCredentialsList.as_view(), name='schedule_credentials_list'),
re_path(r'^$', ScheduleList.as_view(), name='schedule_list'),
re_path(r'^(?P<pk>[0-9]+)/$', ScheduleDetail.as_view(), name='schedule_detail'),
re_path(r'^(?P<pk>[0-9]+)/jobs/$', ScheduleUnifiedJobsList.as_view(), name='schedule_unified_jobs_list'),
re_path(r'^(?P<pk>[0-9]+)/credentials/$', ScheduleCredentialsList.as_view(), name='schedule_credentials_list'),
]
__all__ = ['urls']

View File

@@ -1,17 +1,17 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import SystemJobList, SystemJobDetail, SystemJobCancel, SystemJobNotificationsList, SystemJobEventsList
urls = [
url(r'^$', SystemJobList.as_view(), name='system_job_list'),
url(r'^(?P<pk>[0-9]+)/$', SystemJobDetail.as_view(), name='system_job_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', SystemJobCancel.as_view(), name='system_job_cancel'),
url(r'^(?P<pk>[0-9]+)/notifications/$', SystemJobNotificationsList.as_view(), name='system_job_notifications_list'),
url(r'^(?P<pk>[0-9]+)/events/$', SystemJobEventsList.as_view(), name='system_job_events_list'),
re_path(r'^$', SystemJobList.as_view(), name='system_job_list'),
re_path(r'^(?P<pk>[0-9]+)/$', SystemJobDetail.as_view(), name='system_job_detail'),
re_path(r'^(?P<pk>[0-9]+)/cancel/$', SystemJobCancel.as_view(), name='system_job_cancel'),
re_path(r'^(?P<pk>[0-9]+)/notifications/$', SystemJobNotificationsList.as_view(), name='system_job_notifications_list'),
re_path(r'^(?P<pk>[0-9]+)/events/$', SystemJobEventsList.as_view(), name='system_job_events_list'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
SystemJobTemplateList,
@@ -16,22 +16,22 @@ from awx.api.views import (
urls = [
url(r'^$', SystemJobTemplateList.as_view(), name='system_job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', SystemJobTemplateDetail.as_view(), name='system_job_template_detail'),
url(r'^(?P<pk>[0-9]+)/launch/$', SystemJobTemplateLaunch.as_view(), name='system_job_template_launch'),
url(r'^(?P<pk>[0-9]+)/jobs/$', SystemJobTemplateJobsList.as_view(), name='system_job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/schedules/$', SystemJobTemplateSchedulesList.as_view(), name='system_job_template_schedules_list'),
url(
re_path(r'^$', SystemJobTemplateList.as_view(), name='system_job_template_list'),
re_path(r'^(?P<pk>[0-9]+)/$', SystemJobTemplateDetail.as_view(), name='system_job_template_detail'),
re_path(r'^(?P<pk>[0-9]+)/launch/$', SystemJobTemplateLaunch.as_view(), name='system_job_template_launch'),
re_path(r'^(?P<pk>[0-9]+)/jobs/$', SystemJobTemplateJobsList.as_view(), name='system_job_template_jobs_list'),
re_path(r'^(?P<pk>[0-9]+)/schedules/$', SystemJobTemplateSchedulesList.as_view(), name='system_job_template_schedules_list'),
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_started/$',
SystemJobTemplateNotificationTemplatesStartedList.as_view(),
name='system_job_template_notification_templates_started_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_error/$',
SystemJobTemplateNotificationTemplatesErrorList.as_view(),
name='system_job_template_notification_templates_error_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_success/$',
SystemJobTemplateNotificationTemplatesSuccessList.as_view(),
name='system_job_template_notification_templates_success_list',

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
TeamList,
@@ -17,15 +17,15 @@ from awx.api.views import (
urls = [
url(r'^$', TeamList.as_view(), name='team_list'),
url(r'^(?P<pk>[0-9]+)/$', TeamDetail.as_view(), name='team_detail'),
url(r'^(?P<pk>[0-9]+)/projects/$', TeamProjectsList.as_view(), name='team_projects_list'),
url(r'^(?P<pk>[0-9]+)/users/$', TeamUsersList.as_view(), name='team_users_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', TeamCredentialsList.as_view(), name='team_credentials_list'),
url(r'^(?P<pk>[0-9]+)/roles/$', TeamRolesList.as_view(), name='team_roles_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', TeamObjectRolesList.as_view(), name='team_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', TeamActivityStreamList.as_view(), name='team_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', TeamAccessList.as_view(), name='team_access_list'),
re_path(r'^$', TeamList.as_view(), name='team_list'),
re_path(r'^(?P<pk>[0-9]+)/$', TeamDetail.as_view(), name='team_detail'),
re_path(r'^(?P<pk>[0-9]+)/projects/$', TeamProjectsList.as_view(), name='team_projects_list'),
re_path(r'^(?P<pk>[0-9]+)/users/$', TeamUsersList.as_view(), name='team_users_list'),
re_path(r'^(?P<pk>[0-9]+)/credentials/$', TeamCredentialsList.as_view(), name='team_credentials_list'),
re_path(r'^(?P<pk>[0-9]+)/roles/$', TeamRolesList.as_view(), name='team_roles_list'),
re_path(r'^(?P<pk>[0-9]+)/object_roles/$', TeamObjectRolesList.as_view(), name='team_object_roles_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', TeamActivityStreamList.as_view(), name='team_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/access_list/$', TeamAccessList.as_view(), name='team_access_list'),
]
__all__ = ['urls']

View File

@@ -3,7 +3,7 @@
from __future__ import absolute_import, unicode_literals
from django.conf import settings
from django.conf.urls import include, url
from django.urls import include, re_path
from awx.api.generics import LoggedLoginView, LoggedLogoutView
from awx.api.views import (
@@ -74,78 +74,78 @@ from .workflow_approval import urls as workflow_approval_urls
v2_urls = [
url(r'^$', ApiV2RootView.as_view(), name='api_v2_root_view'),
url(r'^credential_types/', include(credential_type_urls)),
url(r'^credential_input_sources/', include(credential_input_source_urls)),
url(r'^hosts/(?P<pk>[0-9]+)/ansible_facts/$', HostAnsibleFactsDetail.as_view(), name='host_ansible_facts_detail'),
url(r'^jobs/(?P<pk>[0-9]+)/credentials/$', JobCredentialsList.as_view(), name='job_credentials_list'),
url(r'^job_templates/(?P<pk>[0-9]+)/credentials/$', JobTemplateCredentialsList.as_view(), name='job_template_credentials_list'),
url(r'^schedules/preview/$', SchedulePreview.as_view(), name='schedule_rrule'),
url(r'^schedules/zoneinfo/$', ScheduleZoneInfo.as_view(), name='schedule_zoneinfo'),
url(r'^applications/$', OAuth2ApplicationList.as_view(), name='o_auth2_application_list'),
url(r'^applications/(?P<pk>[0-9]+)/$', OAuth2ApplicationDetail.as_view(), name='o_auth2_application_detail'),
url(r'^applications/(?P<pk>[0-9]+)/tokens/$', ApplicationOAuth2TokenList.as_view(), name='application_o_auth2_token_list'),
url(r'^tokens/$', OAuth2TokenList.as_view(), name='o_auth2_token_list'),
url(r'^', include(oauth2_urls)),
url(r'^metrics/$', MetricsView.as_view(), name='metrics_view'),
url(r'^ping/$', ApiV2PingView.as_view(), name='api_v2_ping_view'),
url(r'^config/$', ApiV2ConfigView.as_view(), name='api_v2_config_view'),
url(r'^config/subscriptions/$', ApiV2SubscriptionView.as_view(), name='api_v2_subscription_view'),
url(r'^config/attach/$', ApiV2AttachView.as_view(), name='api_v2_attach_view'),
url(r'^auth/$', AuthView.as_view()),
url(r'^me/$', UserMeList.as_view(), name='user_me_list'),
url(r'^dashboard/$', DashboardView.as_view(), name='dashboard_view'),
url(r'^dashboard/graphs/jobs/$', DashboardJobsGraphView.as_view(), name='dashboard_jobs_graph_view'),
url(r'^mesh_visualizer/', MeshVisualizer.as_view(), name='mesh_visualizer_view'),
url(r'^settings/', include('awx.conf.urls')),
url(r'^instances/', include(instance_urls)),
url(r'^instance_groups/', include(instance_group_urls)),
url(r'^schedules/', include(schedule_urls)),
url(r'^organizations/', include(organization_urls)),
url(r'^users/', include(user_urls)),
url(r'^execution_environments/', include(execution_environment_urls)),
url(r'^projects/', include(project_urls)),
url(r'^project_updates/', include(project_update_urls)),
url(r'^teams/', include(team_urls)),
url(r'^inventories/', include(inventory_urls)),
url(r'^hosts/', include(host_urls)),
url(r'^groups/', include(group_urls)),
url(r'^inventory_sources/', include(inventory_source_urls)),
url(r'^inventory_updates/', include(inventory_update_urls)),
url(r'^credentials/', include(credential_urls)),
url(r'^roles/', include(role_urls)),
url(r'^job_templates/', include(job_template_urls)),
url(r'^jobs/', include(job_urls)),
url(r'^job_host_summaries/', include(job_host_summary_urls)),
url(r'^job_events/', include(job_event_urls)),
url(r'^ad_hoc_commands/', include(ad_hoc_command_urls)),
url(r'^ad_hoc_command_events/', include(ad_hoc_command_event_urls)),
url(r'^system_job_templates/', include(system_job_template_urls)),
url(r'^system_jobs/', include(system_job_urls)),
url(r'^notification_templates/', include(notification_template_urls)),
url(r'^notifications/', include(notification_urls)),
url(r'^workflow_job_templates/', include(workflow_job_template_urls)),
url(r'^workflow_jobs/', include(workflow_job_urls)),
url(r'^labels/', include(label_urls)),
url(r'^workflow_job_template_nodes/', include(workflow_job_template_node_urls)),
url(r'^workflow_job_nodes/', include(workflow_job_node_urls)),
url(r'^unified_job_templates/$', UnifiedJobTemplateList.as_view(), name='unified_job_template_list'),
url(r'^unified_jobs/$', UnifiedJobList.as_view(), name='unified_job_list'),
url(r'^activity_stream/', include(activity_stream_urls)),
url(r'^workflow_approval_templates/', include(workflow_approval_template_urls)),
url(r'^workflow_approvals/', include(workflow_approval_urls)),
re_path(r'^$', ApiV2RootView.as_view(), name='api_v2_root_view'),
re_path(r'^credential_types/', include(credential_type_urls)),
re_path(r'^credential_input_sources/', include(credential_input_source_urls)),
re_path(r'^hosts/(?P<pk>[0-9]+)/ansible_facts/$', HostAnsibleFactsDetail.as_view(), name='host_ansible_facts_detail'),
re_path(r'^jobs/(?P<pk>[0-9]+)/credentials/$', JobCredentialsList.as_view(), name='job_credentials_list'),
re_path(r'^job_templates/(?P<pk>[0-9]+)/credentials/$', JobTemplateCredentialsList.as_view(), name='job_template_credentials_list'),
re_path(r'^schedules/preview/$', SchedulePreview.as_view(), name='schedule_rrule'),
re_path(r'^schedules/zoneinfo/$', ScheduleZoneInfo.as_view(), name='schedule_zoneinfo'),
re_path(r'^applications/$', OAuth2ApplicationList.as_view(), name='o_auth2_application_list'),
re_path(r'^applications/(?P<pk>[0-9]+)/$', OAuth2ApplicationDetail.as_view(), name='o_auth2_application_detail'),
re_path(r'^applications/(?P<pk>[0-9]+)/tokens/$', ApplicationOAuth2TokenList.as_view(), name='application_o_auth2_token_list'),
re_path(r'^tokens/$', OAuth2TokenList.as_view(), name='o_auth2_token_list'),
re_path(r'^', include(oauth2_urls)),
re_path(r'^metrics/$', MetricsView.as_view(), name='metrics_view'),
re_path(r'^ping/$', ApiV2PingView.as_view(), name='api_v2_ping_view'),
re_path(r'^config/$', ApiV2ConfigView.as_view(), name='api_v2_config_view'),
re_path(r'^config/subscriptions/$', ApiV2SubscriptionView.as_view(), name='api_v2_subscription_view'),
re_path(r'^config/attach/$', ApiV2AttachView.as_view(), name='api_v2_attach_view'),
re_path(r'^auth/$', AuthView.as_view()),
re_path(r'^me/$', UserMeList.as_view(), name='user_me_list'),
re_path(r'^dashboard/$', DashboardView.as_view(), name='dashboard_view'),
re_path(r'^dashboard/graphs/jobs/$', DashboardJobsGraphView.as_view(), name='dashboard_jobs_graph_view'),
re_path(r'^mesh_visualizer/', MeshVisualizer.as_view(), name='mesh_visualizer_view'),
re_path(r'^settings/', include('awx.conf.urls')),
re_path(r'^instances/', include(instance_urls)),
re_path(r'^instance_groups/', include(instance_group_urls)),
re_path(r'^schedules/', include(schedule_urls)),
re_path(r'^organizations/', include(organization_urls)),
re_path(r'^users/', include(user_urls)),
re_path(r'^execution_environments/', include(execution_environment_urls)),
re_path(r'^projects/', include(project_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'^hosts/', include(host_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)),
re_path(r'^credentials/', include(credential_urls)),
re_path(r'^roles/', include(role_urls)),
re_path(r'^job_templates/', include(job_template_urls)),
re_path(r'^jobs/', include(job_urls)),
re_path(r'^job_host_summaries/', include(job_host_summary_urls)),
re_path(r'^job_events/', include(job_event_urls)),
re_path(r'^ad_hoc_commands/', include(ad_hoc_command_urls)),
re_path(r'^ad_hoc_command_events/', include(ad_hoc_command_event_urls)),
re_path(r'^system_job_templates/', include(system_job_template_urls)),
re_path(r'^system_jobs/', include(system_job_urls)),
re_path(r'^notification_templates/', include(notification_template_urls)),
re_path(r'^notifications/', include(notification_urls)),
re_path(r'^workflow_job_templates/', include(workflow_job_template_urls)),
re_path(r'^workflow_jobs/', include(workflow_job_urls)),
re_path(r'^labels/', include(label_urls)),
re_path(r'^workflow_job_template_nodes/', include(workflow_job_template_node_urls)),
re_path(r'^workflow_job_nodes/', include(workflow_job_node_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'^workflow_approval_templates/', include(workflow_approval_template_urls)),
re_path(r'^workflow_approvals/', include(workflow_approval_urls)),
]
app_name = 'api'
urlpatterns = [
url(r'^$', ApiRootView.as_view(), name='api_root_view'),
url(r'^(?P<version>(v2))/', include(v2_urls)),
url(r'^login/$', LoggedLoginView.as_view(template_name='rest_framework/login.html', extra_context={'inside_login_context': True}), name='login'),
url(r'^logout/$', LoggedLogoutView.as_view(next_page='/api/', redirect_field_name='next'), name='logout'),
url(r'^o/', include(oauth2_root_urls)),
re_path(r'^$', ApiRootView.as_view(), name='api_root_view'),
re_path(r'^(?P<version>(v2))/', include(v2_urls)),
re_path(r'^login/$', LoggedLoginView.as_view(template_name='rest_framework/login.html', extra_context={'inside_login_context': True}), name='login'),
re_path(r'^logout/$', LoggedLogoutView.as_view(next_page='/api/', redirect_field_name='next'), name='logout'),
re_path(r'^o/', include(oauth2_root_urls)),
]
if settings.SETTINGS_MODULE == 'awx.settings.development':
from awx.api.swagger import SwaggerSchemaView
urlpatterns += [url(r'^swagger/$', SwaggerSchemaView.as_view(), name='swagger_view')]
urlpatterns += [re_path(r'^swagger/$', SwaggerSchemaView.as_view(), name='swagger_view')]

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
UserList,
@@ -21,20 +21,20 @@ from awx.api.views import (
)
urls = [
url(r'^$', UserList.as_view(), name='user_list'),
url(r'^(?P<pk>[0-9]+)/$', UserDetail.as_view(), name='user_detail'),
url(r'^(?P<pk>[0-9]+)/teams/$', UserTeamsList.as_view(), name='user_teams_list'),
url(r'^(?P<pk>[0-9]+)/organizations/$', UserOrganizationsList.as_view(), name='user_organizations_list'),
url(r'^(?P<pk>[0-9]+)/admin_of_organizations/$', UserAdminOfOrganizationsList.as_view(), name='user_admin_of_organizations_list'),
url(r'^(?P<pk>[0-9]+)/projects/$', UserProjectsList.as_view(), name='user_projects_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', UserCredentialsList.as_view(), name='user_credentials_list'),
url(r'^(?P<pk>[0-9]+)/roles/$', UserRolesList.as_view(), name='user_roles_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', UserActivityStreamList.as_view(), name='user_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', UserAccessList.as_view(), name='user_access_list'),
url(r'^(?P<pk>[0-9]+)/applications/$', OAuth2ApplicationList.as_view(), name='o_auth2_application_list'),
url(r'^(?P<pk>[0-9]+)/tokens/$', OAuth2UserTokenList.as_view(), name='o_auth2_token_list'),
url(r'^(?P<pk>[0-9]+)/authorized_tokens/$', UserAuthorizedTokenList.as_view(), name='user_authorized_token_list'),
url(r'^(?P<pk>[0-9]+)/personal_tokens/$', UserPersonalTokenList.as_view(), name='user_personal_token_list'),
re_path(r'^$', UserList.as_view(), name='user_list'),
re_path(r'^(?P<pk>[0-9]+)/$', UserDetail.as_view(), name='user_detail'),
re_path(r'^(?P<pk>[0-9]+)/teams/$', UserTeamsList.as_view(), name='user_teams_list'),
re_path(r'^(?P<pk>[0-9]+)/organizations/$', UserOrganizationsList.as_view(), name='user_organizations_list'),
re_path(r'^(?P<pk>[0-9]+)/admin_of_organizations/$', UserAdminOfOrganizationsList.as_view(), name='user_admin_of_organizations_list'),
re_path(r'^(?P<pk>[0-9]+)/projects/$', UserProjectsList.as_view(), name='user_projects_list'),
re_path(r'^(?P<pk>[0-9]+)/credentials/$', UserCredentialsList.as_view(), name='user_credentials_list'),
re_path(r'^(?P<pk>[0-9]+)/roles/$', UserRolesList.as_view(), name='user_roles_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', UserActivityStreamList.as_view(), name='user_activity_stream_list'),
re_path(r'^(?P<pk>[0-9]+)/access_list/$', UserAccessList.as_view(), name='user_access_list'),
re_path(r'^(?P<pk>[0-9]+)/applications/$', OAuth2ApplicationList.as_view(), name='o_auth2_application_list'),
re_path(r'^(?P<pk>[0-9]+)/tokens/$', OAuth2UserTokenList.as_view(), name='o_auth2_token_list'),
re_path(r'^(?P<pk>[0-9]+)/authorized_tokens/$', UserAuthorizedTokenList.as_view(), name='user_authorized_token_list'),
re_path(r'^(?P<pk>[0-9]+)/personal_tokens/$', UserPersonalTokenList.as_view(), name='user_personal_token_list'),
]
__all__ = ['urls']

View File

@@ -1,10 +1,10 @@
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import WebhookKeyView, GithubWebhookReceiver, GitlabWebhookReceiver
urlpatterns = [
url(r'^webhook_key/$', WebhookKeyView.as_view(), name='webhook_key'),
url(r'^github/$', GithubWebhookReceiver.as_view(), name='webhook_receiver_github'),
url(r'^gitlab/$', GitlabWebhookReceiver.as_view(), name='webhook_receiver_gitlab'),
re_path(r'^webhook_key/$', WebhookKeyView.as_view(), name='webhook_key'),
re_path(r'^github/$', GithubWebhookReceiver.as_view(), name='webhook_receiver_github'),
re_path(r'^gitlab/$', GitlabWebhookReceiver.as_view(), name='webhook_receiver_gitlab'),
]

View File

@@ -1,16 +1,16 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import WorkflowApprovalList, WorkflowApprovalDetail, WorkflowApprovalApprove, WorkflowApprovalDeny
urls = [
url(r'^$', WorkflowApprovalList.as_view(), name='workflow_approval_list'),
url(r'^(?P<pk>[0-9]+)/$', WorkflowApprovalDetail.as_view(), name='workflow_approval_detail'),
url(r'^(?P<pk>[0-9]+)/approve/$', WorkflowApprovalApprove.as_view(), name='workflow_approval_approve'),
url(r'^(?P<pk>[0-9]+)/deny/$', WorkflowApprovalDeny.as_view(), name='workflow_approval_deny'),
re_path(r'^$', WorkflowApprovalList.as_view(), name='workflow_approval_list'),
re_path(r'^(?P<pk>[0-9]+)/$', WorkflowApprovalDetail.as_view(), name='workflow_approval_detail'),
re_path(r'^(?P<pk>[0-9]+)/approve/$', WorkflowApprovalApprove.as_view(), name='workflow_approval_approve'),
re_path(r'^(?P<pk>[0-9]+)/deny/$', WorkflowApprovalDeny.as_view(), name='workflow_approval_deny'),
]
__all__ = ['urls']

View File

@@ -1,14 +1,14 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import WorkflowApprovalTemplateDetail, WorkflowApprovalTemplateJobsList
urls = [
url(r'^(?P<pk>[0-9]+)/$', WorkflowApprovalTemplateDetail.as_view(), name='workflow_approval_template_detail'),
url(r'^(?P<pk>[0-9]+)/approvals/$', WorkflowApprovalTemplateJobsList.as_view(), name='workflow_approval_template_jobs_list'),
re_path(r'^(?P<pk>[0-9]+)/$', WorkflowApprovalTemplateDetail.as_view(), name='workflow_approval_template_detail'),
re_path(r'^(?P<pk>[0-9]+)/approvals/$', WorkflowApprovalTemplateJobsList.as_view(), name='workflow_approval_template_jobs_list'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
WorkflowJobList,
@@ -16,14 +16,14 @@ from awx.api.views import (
urls = [
url(r'^$', WorkflowJobList.as_view(), name='workflow_job_list'),
url(r'^(?P<pk>[0-9]+)/$', WorkflowJobDetail.as_view(), name='workflow_job_detail'),
url(r'^(?P<pk>[0-9]+)/workflow_nodes/$', WorkflowJobWorkflowNodesList.as_view(), name='workflow_job_workflow_nodes_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', WorkflowJobLabelList.as_view(), name='workflow_job_label_list'),
url(r'^(?P<pk>[0-9]+)/cancel/$', WorkflowJobCancel.as_view(), name='workflow_job_cancel'),
url(r'^(?P<pk>[0-9]+)/relaunch/$', WorkflowJobRelaunch.as_view(), name='workflow_job_relaunch'),
url(r'^(?P<pk>[0-9]+)/notifications/$', WorkflowJobNotificationsList.as_view(), name='workflow_job_notifications_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', WorkflowJobActivityStreamList.as_view(), name='workflow_job_activity_stream_list'),
re_path(r'^$', WorkflowJobList.as_view(), name='workflow_job_list'),
re_path(r'^(?P<pk>[0-9]+)/$', WorkflowJobDetail.as_view(), name='workflow_job_detail'),
re_path(r'^(?P<pk>[0-9]+)/workflow_nodes/$', WorkflowJobWorkflowNodesList.as_view(), name='workflow_job_workflow_nodes_list'),
re_path(r'^(?P<pk>[0-9]+)/labels/$', WorkflowJobLabelList.as_view(), name='workflow_job_label_list'),
re_path(r'^(?P<pk>[0-9]+)/cancel/$', WorkflowJobCancel.as_view(), name='workflow_job_cancel'),
re_path(r'^(?P<pk>[0-9]+)/relaunch/$', WorkflowJobRelaunch.as_view(), name='workflow_job_relaunch'),
re_path(r'^(?P<pk>[0-9]+)/notifications/$', WorkflowJobNotificationsList.as_view(), name='workflow_job_notifications_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', WorkflowJobActivityStreamList.as_view(), name='workflow_job_activity_stream_list'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
WorkflowJobNodeList,
@@ -14,12 +14,12 @@ from awx.api.views import (
urls = [
url(r'^$', WorkflowJobNodeList.as_view(), name='workflow_job_node_list'),
url(r'^(?P<pk>[0-9]+)/$', WorkflowJobNodeDetail.as_view(), name='workflow_job_node_detail'),
url(r'^(?P<pk>[0-9]+)/success_nodes/$', WorkflowJobNodeSuccessNodesList.as_view(), name='workflow_job_node_success_nodes_list'),
url(r'^(?P<pk>[0-9]+)/failure_nodes/$', WorkflowJobNodeFailureNodesList.as_view(), name='workflow_job_node_failure_nodes_list'),
url(r'^(?P<pk>[0-9]+)/always_nodes/$', WorkflowJobNodeAlwaysNodesList.as_view(), name='workflow_job_node_always_nodes_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', WorkflowJobNodeCredentialsList.as_view(), name='workflow_job_node_credentials_list'),
re_path(r'^$', WorkflowJobNodeList.as_view(), name='workflow_job_node_list'),
re_path(r'^(?P<pk>[0-9]+)/$', WorkflowJobNodeDetail.as_view(), name='workflow_job_node_detail'),
re_path(r'^(?P<pk>[0-9]+)/success_nodes/$', WorkflowJobNodeSuccessNodesList.as_view(), name='workflow_job_node_success_nodes_list'),
re_path(r'^(?P<pk>[0-9]+)/failure_nodes/$', WorkflowJobNodeFailureNodesList.as_view(), name='workflow_job_node_failure_nodes_list'),
re_path(r'^(?P<pk>[0-9]+)/always_nodes/$', WorkflowJobNodeAlwaysNodesList.as_view(), name='workflow_job_node_always_nodes_list'),
re_path(r'^(?P<pk>[0-9]+)/credentials/$', WorkflowJobNodeCredentialsList.as_view(), name='workflow_job_node_credentials_list'),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import include, url
from django.urls import include, re_path
from awx.api.views import (
WorkflowJobTemplateList,
@@ -24,39 +24,39 @@ from awx.api.views import (
urls = [
url(r'^$', WorkflowJobTemplateList.as_view(), name='workflow_job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', WorkflowJobTemplateDetail.as_view(), name='workflow_job_template_detail'),
url(r'^(?P<pk>[0-9]+)/workflow_jobs/$', WorkflowJobTemplateJobsList.as_view(), name='workflow_job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/launch/$', WorkflowJobTemplateLaunch.as_view(), name='workflow_job_template_launch'),
url(r'^(?P<pk>[0-9]+)/copy/$', WorkflowJobTemplateCopy.as_view(), name='workflow_job_template_copy'),
url(r'^(?P<pk>[0-9]+)/schedules/$', WorkflowJobTemplateSchedulesList.as_view(), name='workflow_job_template_schedules_list'),
url(r'^(?P<pk>[0-9]+)/survey_spec/$', WorkflowJobTemplateSurveySpec.as_view(), name='workflow_job_template_survey_spec'),
url(r'^(?P<pk>[0-9]+)/workflow_nodes/$', WorkflowJobTemplateWorkflowNodesList.as_view(), name='workflow_job_template_workflow_nodes_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', WorkflowJobTemplateActivityStreamList.as_view(), name='workflow_job_template_activity_stream_list'),
url(
re_path(r'^$', WorkflowJobTemplateList.as_view(), name='workflow_job_template_list'),
re_path(r'^(?P<pk>[0-9]+)/$', WorkflowJobTemplateDetail.as_view(), name='workflow_job_template_detail'),
re_path(r'^(?P<pk>[0-9]+)/workflow_jobs/$', WorkflowJobTemplateJobsList.as_view(), name='workflow_job_template_jobs_list'),
re_path(r'^(?P<pk>[0-9]+)/launch/$', WorkflowJobTemplateLaunch.as_view(), name='workflow_job_template_launch'),
re_path(r'^(?P<pk>[0-9]+)/copy/$', WorkflowJobTemplateCopy.as_view(), name='workflow_job_template_copy'),
re_path(r'^(?P<pk>[0-9]+)/schedules/$', WorkflowJobTemplateSchedulesList.as_view(), name='workflow_job_template_schedules_list'),
re_path(r'^(?P<pk>[0-9]+)/survey_spec/$', WorkflowJobTemplateSurveySpec.as_view(), name='workflow_job_template_survey_spec'),
re_path(r'^(?P<pk>[0-9]+)/workflow_nodes/$', WorkflowJobTemplateWorkflowNodesList.as_view(), name='workflow_job_template_workflow_nodes_list'),
re_path(r'^(?P<pk>[0-9]+)/activity_stream/$', WorkflowJobTemplateActivityStreamList.as_view(), name='workflow_job_template_activity_stream_list'),
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_started/$',
WorkflowJobTemplateNotificationTemplatesStartedList.as_view(),
name='workflow_job_template_notification_templates_started_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_error/$',
WorkflowJobTemplateNotificationTemplatesErrorList.as_view(),
name='workflow_job_template_notification_templates_error_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_success/$',
WorkflowJobTemplateNotificationTemplatesSuccessList.as_view(),
name='workflow_job_template_notification_templates_success_list',
),
url(
re_path(
r'^(?P<pk>[0-9]+)/notification_templates_approvals/$',
WorkflowJobTemplateNotificationTemplatesApprovalList.as_view(),
name='workflow_job_template_notification_templates_approvals_list',
),
url(r'^(?P<pk>[0-9]+)/access_list/$', WorkflowJobTemplateAccessList.as_view(), name='workflow_job_template_access_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', WorkflowJobTemplateObjectRolesList.as_view(), name='workflow_job_template_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', WorkflowJobTemplateLabelList.as_view(), name='workflow_job_template_label_list'),
url(r'^(?P<pk>[0-9]+)/', include('awx.api.urls.webhooks'), {'model_kwarg': 'workflow_job_templates'}),
re_path(r'^(?P<pk>[0-9]+)/access_list/$', WorkflowJobTemplateAccessList.as_view(), name='workflow_job_template_access_list'),
re_path(r'^(?P<pk>[0-9]+)/object_roles/$', WorkflowJobTemplateObjectRolesList.as_view(), name='workflow_job_template_object_roles_list'),
re_path(r'^(?P<pk>[0-9]+)/labels/$', WorkflowJobTemplateLabelList.as_view(), name='workflow_job_template_label_list'),
re_path(r'^(?P<pk>[0-9]+)/', include('awx.api.urls.webhooks'), {'model_kwarg': 'workflow_job_templates'}),
]
__all__ = ['urls']

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from django.urls import re_path
from awx.api.views import (
WorkflowJobTemplateNodeList,
@@ -15,13 +15,13 @@ from awx.api.views import (
urls = [
url(r'^$', WorkflowJobTemplateNodeList.as_view(), name='workflow_job_template_node_list'),
url(r'^(?P<pk>[0-9]+)/$', WorkflowJobTemplateNodeDetail.as_view(), name='workflow_job_template_node_detail'),
url(r'^(?P<pk>[0-9]+)/success_nodes/$', WorkflowJobTemplateNodeSuccessNodesList.as_view(), name='workflow_job_template_node_success_nodes_list'),
url(r'^(?P<pk>[0-9]+)/failure_nodes/$', WorkflowJobTemplateNodeFailureNodesList.as_view(), name='workflow_job_template_node_failure_nodes_list'),
url(r'^(?P<pk>[0-9]+)/always_nodes/$', WorkflowJobTemplateNodeAlwaysNodesList.as_view(), name='workflow_job_template_node_always_nodes_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', WorkflowJobTemplateNodeCredentialsList.as_view(), name='workflow_job_template_node_credentials_list'),
url(r'^(?P<pk>[0-9]+)/create_approval_template/$', WorkflowJobTemplateNodeCreateApproval.as_view(), name='workflow_job_template_node_create_approval'),
re_path(r'^$', WorkflowJobTemplateNodeList.as_view(), name='workflow_job_template_node_list'),
re_path(r'^(?P<pk>[0-9]+)/$', WorkflowJobTemplateNodeDetail.as_view(), name='workflow_job_template_node_detail'),
re_path(r'^(?P<pk>[0-9]+)/success_nodes/$', WorkflowJobTemplateNodeSuccessNodesList.as_view(), name='workflow_job_template_node_success_nodes_list'),
re_path(r'^(?P<pk>[0-9]+)/failure_nodes/$', WorkflowJobTemplateNodeFailureNodesList.as_view(), name='workflow_job_template_node_failure_nodes_list'),
re_path(r'^(?P<pk>[0-9]+)/always_nodes/$', WorkflowJobTemplateNodeAlwaysNodesList.as_view(), name='workflow_job_template_node_always_nodes_list'),
re_path(r'^(?P<pk>[0-9]+)/credentials/$', WorkflowJobTemplateNodeCredentialsList.as_view(), name='workflow_job_template_node_credentials_list'),
re_path(r'^(?P<pk>[0-9]+)/create_approval_template/$', WorkflowJobTemplateNodeCreateApproval.as_view(), name='workflow_job_template_node_create_approval'),
]
__all__ = ['urls']

View File

@@ -29,7 +29,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.template.loader import render_to_string
from django.http import HttpResponse
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# Django REST Framework
@@ -105,7 +105,6 @@ from awx.api.permissions import (
ProjectUpdatePermission,
InventoryInventorySourcesUpdatePermission,
UserPermission,
InstanceGroupTowerPermission,
VariableDataPermission,
WorkflowApprovalPermission,
IsSystemAdminOrAuditor,
@@ -116,7 +115,6 @@ from awx.api.metadata import RoleMetadata
from awx.main.constants import ACTIVE_STATES, SURVEY_TYPE_MAPPING
from awx.main.scheduler.dag_workflow import WorkflowDAG
from awx.api.views.mixin import (
ControlledByScmMixin,
InstanceGroupMembershipMixin,
OrganizationCountsMixin,
RelatedJobsPreventDeleteMixin,
@@ -173,6 +171,7 @@ from awx.api.views.root import ( # noqa
)
from awx.api.views.webhooks import WebhookKeyView, GithubWebhookReceiver, GitlabWebhookReceiver # noqa
from awx.api.pagination import UnifiedJobEventPagination
from awx.main.utils import set_environ
logger = logging.getLogger('awx.api.views')
@@ -365,6 +364,7 @@ class InstanceList(ListAPIView):
model = models.Instance
serializer_class = serializers.InstanceSerializer
search_fields = ('hostname',)
ordering = ('id',)
class InstanceDetail(RetrieveUpdateAPIView):
@@ -409,7 +409,15 @@ class InstanceInstanceGroupsList(InstanceGroupMembershipMixin, SubListCreateAtta
if parent.node_type == 'control':
return {'msg': _(f"Cannot change instance group membership of control-only node: {parent.hostname}.")}
if parent.node_type == 'hop':
return {'msg': _(f"Cannot change instance group membership of hop node: {parent.hostname}.")}
return {'msg': _(f"Cannot change instance group membership of hop node : {parent.hostname}.")}
return None
def is_valid_removal(self, parent, sub):
res = self.is_valid_relation(parent, sub)
if res:
return res
if sub.name == settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME and parent.node_type == 'hybrid':
return {'msg': _(f"Cannot disassociate hybrid instance {parent.hostname} from {sub.name}.")}
return None
@@ -480,7 +488,6 @@ class InstanceGroupDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAP
name = _("Instance Group Detail")
model = models.InstanceGroup
serializer_class = serializers.InstanceGroupSerializer
permission_classes = (InstanceGroupTowerPermission,)
def update_raw_data(self, data):
if self.get_object().is_container_group:
@@ -512,7 +519,15 @@ class InstanceGroupInstanceList(InstanceGroupMembershipMixin, SubListAttachDetac
if sub.node_type == 'control':
return {'msg': _(f"Cannot change instance group membership of control-only node: {sub.hostname}.")}
if sub.node_type == 'hop':
return {'msg': _(f"Cannot change instance group membership of hop node: {sub.hostname}.")}
return {'msg': _(f"Cannot change instance group membership of hop node : {sub.hostname}.")}
return None
def is_valid_removal(self, parent, sub):
res = self.is_valid_relation(parent, sub)
if res:
return res
if sub.node_type == 'hybrid' and parent.name == settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME:
return {'msg': _(f"Cannot disassociate hybrid node {sub.hostname} from {parent.name}.")}
return None
@@ -521,6 +536,7 @@ class ScheduleList(ListCreateAPIView):
name = _("Schedules")
model = models.Schedule
serializer_class = serializers.ScheduleSerializer
ordering = ('id',)
class ScheduleDetail(RetrieveUpdateDestroyAPIView):
@@ -561,8 +577,7 @@ class ScheduleZoneInfo(APIView):
swagger_topic = 'System Configuration'
def get(self, request):
zones = [{'name': zone} for zone in models.Schedule.get_zoneinfo()]
return Response(zones)
return Response({'zones': models.Schedule.get_zoneinfo(), 'links': models.Schedule.get_zoneinfo_links()})
class LaunchConfigCredentialsBase(SubListAttachDetachAPIView):
@@ -1557,8 +1572,9 @@ class CredentialExternalTest(SubDetailAPIView):
backend_kwargs[field_name] = value
backend_kwargs.update(request.data.get('metadata', {}))
try:
obj.credential_type.plugin.backend(**backend_kwargs)
return Response({}, status=status.HTTP_202_ACCEPTED)
with set_environ(**settings.AWX_TASK_ENV):
obj.credential_type.plugin.backend(**backend_kwargs)
return Response({}, status=status.HTTP_202_ACCEPTED)
except requests.exceptions.HTTPError as exc:
message = 'HTTP {}'.format(exc.response.status_code)
return Response({'inputs': message}, status=status.HTTP_400_BAD_REQUEST)
@@ -1658,7 +1674,7 @@ class HostList(HostRelatedSearchMixin, ListCreateAPIView):
return Response(dict(error=_(str(e))), status=status.HTTP_400_BAD_REQUEST)
class HostDetail(RelatedJobsPreventDeleteMixin, ControlledByScmMixin, RetrieveUpdateDestroyAPIView):
class HostDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAPIView):
always_allow_superuser = False
model = models.Host
@@ -1692,7 +1708,7 @@ class InventoryHostsList(HostRelatedSearchMixin, SubListCreateAttachDetachAPIVie
return qs
class HostGroupsList(ControlledByScmMixin, SubListCreateAttachDetachAPIView):
class HostGroupsList(SubListCreateAttachDetachAPIView):
'''the list of groups a host is directly a member of'''
model = models.Group
@@ -1808,7 +1824,7 @@ class EnforceParentRelationshipMixin(object):
return super(EnforceParentRelationshipMixin, self).create(request, *args, **kwargs)
class GroupChildrenList(ControlledByScmMixin, EnforceParentRelationshipMixin, SubListCreateAttachDetachAPIView):
class GroupChildrenList(EnforceParentRelationshipMixin, SubListCreateAttachDetachAPIView):
model = models.Group
serializer_class = serializers.GroupSerializer
@@ -1854,7 +1870,7 @@ class GroupPotentialChildrenList(SubListAPIView):
return qs.exclude(pk__in=except_pks)
class GroupHostsList(HostRelatedSearchMixin, ControlledByScmMixin, SubListCreateAttachDetachAPIView):
class GroupHostsList(HostRelatedSearchMixin, SubListCreateAttachDetachAPIView):
'''the list of hosts directly below a group'''
model = models.Host
@@ -1918,7 +1934,7 @@ class GroupActivityStreamList(SubListAPIView):
return qs.filter(Q(group=parent) | Q(host__in=parent.hosts.all()))
class GroupDetail(RelatedJobsPreventDeleteMixin, ControlledByScmMixin, RetrieveUpdateDestroyAPIView):
class GroupDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAPIView):
model = models.Group
serializer_class = serializers.GroupSerializer
@@ -3826,6 +3842,112 @@ class JobJobEventsList(BaseJobEventsList):
return job.get_event_queryset().select_related('host').order_by('start_line')
class JobJobEventsChildrenSummary(APIView):
renderer_classes = [JSONRenderer]
meta_events = ('debug', 'verbose', 'warning', 'error', 'system_warning', 'deprecated')
def get(self, request, **kwargs):
resp = dict(children_summary={}, meta_event_nested_uuid={}, event_processing_finished=False, is_tree=True)
job = get_object_or_404(models.Job, pk=kwargs['pk'])
if not job.event_processing_finished:
return Response(resp)
else:
resp["event_processing_finished"] = True
events = list(job.get_event_queryset().values('counter', 'uuid', 'parent_uuid', 'event').order_by('counter'))
if len(events) == 0:
return Response(resp)
# key is counter, value is number of total children (including children of children, etc.)
map_counter_children_tally = {i['counter']: {"rowNumber": 0, "numChildren": 0} for i in events}
# key is uuid, value is counter
map_uuid_counter = {i['uuid']: i['counter'] for i in events}
# key is uuid, value is parent uuid. Used as a quick lookup
map_uuid_puuid = {i['uuid']: i['parent_uuid'] for i in events}
# key is counter of meta events (i.e. verbose), value is uuid of the assigned parent
map_meta_counter_nested_uuid = {}
# collapsable tree view in the UI only makes sense for tree-like
# hierarchy. If ansible is ran with a strategy like free or host_pinned, then
# events can be out of sequential order, and no longer follow a tree structure
# E1
# E2
# E3
# E4 <- parent is E3
# E5 <- parent is E1
# in the above, there is no clear way to collapse E1, because E5 comes after
# E3, which occurs after E1. Thus the tree view should be disabled.
# mark the last seen uuid at a given level (0-3)
# if a parent uuid is not in this list, then we know the events are not tree-like
# and return a response with is_tree: False
level_current_uuid = [None, None, None, None]
prev_non_meta_event = events[0]
for i, e in enumerate(events):
if not e['event'] in JobJobEventsChildrenSummary.meta_events:
prev_non_meta_event = e
if not e['uuid']:
continue
if not e['event'] in JobJobEventsChildrenSummary.meta_events:
level = models.JobEvent.LEVEL_FOR_EVENT[e['event']]
level_current_uuid[level] = e['uuid']
# if setting level 1, for example, set levels 2 and 3 back to None
for u in range(level + 1, len(level_current_uuid)):
level_current_uuid[u] = None
puuid = e['parent_uuid']
if puuid and puuid not in level_current_uuid:
# improper tree detected, so bail out early
resp['is_tree'] = False
return Response(resp)
# if event is verbose (or debug, etc), we need to "assign" it a
# parent. This code looks at the event level of the previous
# non-verbose event, and the level of the next (by looking ahead)
# non-verbose event. The verbose event is assigned the same parent
# uuid of the higher level event.
# e.g.
# E1
# E2
# verbose
# verbose <- we are on this event currently
# E4
# We'll compare E2 and E4, and the verbose event
# will be assigned the parent uuid of E4 (higher event level)
if e['event'] in JobJobEventsChildrenSummary.meta_events:
event_level_before = models.JobEvent.LEVEL_FOR_EVENT[prev_non_meta_event['event']]
# find next non meta event
z = i
next_non_meta_event = events[-1]
while z < len(events):
if events[z]['event'] not in JobJobEventsChildrenSummary.meta_events:
next_non_meta_event = events[z]
break
z += 1
event_level_after = models.JobEvent.LEVEL_FOR_EVENT[next_non_meta_event['event']]
if event_level_after and event_level_after > event_level_before:
puuid = next_non_meta_event['parent_uuid']
else:
puuid = prev_non_meta_event['parent_uuid']
if puuid:
map_meta_counter_nested_uuid[e['counter']] = puuid
map_counter_children_tally[e['counter']]['rowNumber'] = i
if not puuid:
continue
# now traverse up the parent, grandparent, etc. events and tally those
while puuid:
map_counter_children_tally[map_uuid_counter[puuid]]['numChildren'] += 1
puuid = map_uuid_puuid.get(puuid, None)
# create new dictionary, dropping events with 0 children
resp["children_summary"] = {k: v for k, v in map_counter_children_tally.items() if v['numChildren'] != 0}
resp["meta_event_nested_uuid"] = map_meta_counter_nested_uuid
return Response(resp)
class AdHocCommandList(ListCreateAPIView):
model = models.AdHocCommand

View File

@@ -8,7 +8,7 @@ import logging
from django.conf import settings
from django.db.models import Q
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework.exceptions import PermissionDenied
@@ -41,7 +41,7 @@ from awx.api.serializers import (
JobTemplateSerializer,
LabelSerializer,
)
from awx.api.views.mixin import RelatedJobsPreventDeleteMixin, ControlledByScmMixin
from awx.api.views.mixin import RelatedJobsPreventDeleteMixin
from awx.api.pagination import UnifiedJobEventPagination
@@ -75,7 +75,7 @@ class InventoryList(ListCreateAPIView):
serializer_class = InventorySerializer
class InventoryDetail(RelatedJobsPreventDeleteMixin, ControlledByScmMixin, RetrieveUpdateDestroyAPIView):
class InventoryDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAPIView):
model = Inventory
serializer_class = InventorySerializer

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2018 Red Hat, Inc.
# All Rights Reserved.
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from awx.api.generics import APIView, Response
from awx.api.permissions import IsSystemAdminOrAuditor

View File

@@ -5,7 +5,7 @@
import logging
# Django
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework.response import Response

View File

@@ -8,15 +8,14 @@ from django.db.models import Count
from django.db import transaction
from django.shortcuts import get_object_or_404
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from rest_framework.permissions import SAFE_METHODS
from rest_framework.exceptions import PermissionDenied
from rest_framework.response import Response
from rest_framework import status
from awx.main.constants import ACTIVE_STATES
from awx.main.utils import get_object_or_400, parse_yaml_or_json
from awx.main.utils import get_object_or_400
from awx.main.models.ha import Instance, InstanceGroup
from awx.main.models.organization import Team
from awx.main.models.projects import Project
@@ -68,49 +67,27 @@ class InstanceGroupMembershipMixin(object):
membership.
"""
def attach_validate(self, request):
parent = self.get_parent_object()
sub_id, res = super().attach_validate(request)
if res: # handle an error
return sub_id, res
sub = get_object_or_400(self.model, pk=sub_id)
attach_errors = self.is_valid_relation(parent, sub)
if attach_errors:
return sub_id, Response(attach_errors, status=status.HTTP_400_BAD_REQUEST)
return sub_id, res
def attach(self, request, *args, **kwargs):
response = super(InstanceGroupMembershipMixin, self).attach(request, *args, **kwargs)
sub_id, res = self.attach_validate(request)
if status.is_success(response.status_code):
sub_id = request.data.get('id', None)
if self.parent_model is Instance:
inst_name = self.get_parent_object().hostname
else:
inst_name = get_object_or_400(self.model, pk=sub_id).hostname
with transaction.atomic():
ig_qs = InstanceGroup.objects.select_for_update()
instance_groups_queryset = InstanceGroup.objects.select_for_update()
if self.parent_model is Instance:
ig_obj = get_object_or_400(ig_qs, pk=sub_id)
ig_obj = get_object_or_400(instance_groups_queryset, pk=sub_id)
else:
# similar to get_parent_object, but selected for update
parent_filter = {self.lookup_field: self.kwargs.get(self.lookup_field, None)}
ig_obj = get_object_or_404(ig_qs, **parent_filter)
ig_obj = get_object_or_404(instance_groups_queryset, **parent_filter)
if inst_name not in ig_obj.policy_instance_list:
ig_obj.policy_instance_list.append(inst_name)
ig_obj.save(update_fields=['policy_instance_list'])
return response
def unattach_validate(self, request):
parent = self.get_parent_object()
(sub_id, res) = super(InstanceGroupMembershipMixin, self).unattach_validate(request)
if res:
return (sub_id, res)
sub = get_object_or_400(self.model, pk=sub_id)
attach_errors = self.is_valid_relation(parent, sub)
if attach_errors:
return (sub_id, Response(attach_errors, status=status.HTTP_400_BAD_REQUEST))
return (sub_id, res)
def unattach(self, request, *args, **kwargs):
response = super(InstanceGroupMembershipMixin, self).unattach(request, *args, **kwargs)
if status.is_success(response.status_code):
@@ -120,13 +97,13 @@ class InstanceGroupMembershipMixin(object):
else:
inst_name = get_object_or_400(self.model, pk=sub_id).hostname
with transaction.atomic():
ig_qs = InstanceGroup.objects.select_for_update()
instance_groups_queryset = InstanceGroup.objects.select_for_update()
if self.parent_model is Instance:
ig_obj = get_object_or_400(ig_qs, pk=sub_id)
ig_obj = get_object_or_400(instance_groups_queryset, pk=sub_id)
else:
# similar to get_parent_object, but selected for update
parent_filter = {self.lookup_field: self.kwargs.get(self.lookup_field, None)}
ig_obj = get_object_or_404(ig_qs, **parent_filter)
ig_obj = get_object_or_404(instance_groups_queryset, **parent_filter)
if inst_name in ig_obj.policy_instance_list:
ig_obj.policy_instance_list.pop(ig_obj.policy_instance_list.index(inst_name))
ig_obj.save(update_fields=['policy_instance_list'])
@@ -208,35 +185,6 @@ class OrganizationCountsMixin(object):
return full_context
class ControlledByScmMixin(object):
"""
Special method to reset SCM inventory commit hash
if anything that it manages changes.
"""
def _reset_inv_src_rev(self, obj):
if self.request.method in SAFE_METHODS or not obj:
return
project_following_sources = obj.inventory_sources.filter(update_on_project_update=True, source='scm')
if project_following_sources:
# Allow inventory changes unrelated to variables
if self.model == Inventory and (
not self.request or not self.request.data or parse_yaml_or_json(self.request.data.get('variables', '')) == parse_yaml_or_json(obj.variables)
):
return
project_following_sources.update(scm_last_revision='')
def get_object(self):
obj = super(ControlledByScmMixin, self).get_object()
self._reset_inv_src_rev(obj)
return obj
def get_parent_object(self):
obj = super(ControlledByScmMixin, self).get_parent_object()
self._reset_inv_src_rev(obj)
return obj
class NoTruncateMixin(object):
def get_serializer_context(self):
context = super().get_serializer_context()

View File

@@ -7,7 +7,7 @@ import logging
# Django
from django.db.models import Count
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# AWX
from awx.main.models import (

View File

@@ -8,11 +8,11 @@ import operator
from collections import OrderedDict
from django.conf import settings
from django.utils.encoding import smart_text
from django.utils.encoding import smart_str
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import ensure_csrf_cookie
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
@@ -205,7 +205,7 @@ class ApiV2SubscriptionView(APIView):
elif isinstance(exc, (ValueError, OSError)) and exc.args:
msg = exc.args[0]
else:
logger.exception(smart_text(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
logger.exception(smart_str(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
return Response({"error": msg}, status=status.HTTP_400_BAD_REQUEST)
return Response(validated)
@@ -246,7 +246,7 @@ class ApiV2AttachView(APIView):
elif isinstance(exc, (ValueError, OSError)) and exc.args:
msg = exc.args[0]
else:
logger.exception(smart_text(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
logger.exception(smart_str(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
return Response({"error": msg}, status=status.HTTP_400_BAD_REQUEST)
for sub in validated:
if sub['pool_id'] == pool_id:
@@ -322,7 +322,7 @@ class ApiV2ConfigView(APIView):
try:
data_actual = json.dumps(request.data)
except Exception:
logger.info(smart_text(u"Invalid JSON submitted for license."), extra=dict(actor=request.user.username))
logger.info(smart_str(u"Invalid JSON submitted for license."), extra=dict(actor=request.user.username))
return Response({"error": _("Invalid JSON")}, status=status.HTTP_400_BAD_REQUEST)
license_data = json.loads(data_actual)
@@ -346,7 +346,7 @@ class ApiV2ConfigView(APIView):
try:
license_data_validated = get_licenser().license_from_manifest(license_data)
except Exception:
logger.warning(smart_text(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
logger.warning(smart_str(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
return Response({"error": _("Invalid License")}, status=status.HTTP_400_BAD_REQUEST)
else:
license_data_validated = get_licenser().validate()
@@ -357,7 +357,7 @@ class ApiV2ConfigView(APIView):
settings.TOWER_URL_BASE = "{}://{}".format(request.scheme, request.get_host())
return Response(license_data_validated)
logger.warning(smart_text(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
logger.warning(smart_str(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
return Response({"error": _("Invalid subscription")}, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request):

View File

@@ -4,7 +4,7 @@ import logging
import urllib.parse
from django.utils.encoding import force_bytes
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from rest_framework import status
@@ -16,7 +16,7 @@ from awx.api import serializers
from awx.api.generics import APIView, GenericAPIView
from awx.api.permissions import WebhookKeyPermission
from awx.main.models import Job, JobTemplate, WorkflowJob, WorkflowJobTemplate
from awx.main.constants import JOB_VARIABLE_PREFIXES
logger = logging.getLogger('awx.api.views.webhooks')
@@ -136,15 +136,16 @@ class WebhookReceiverBase(APIView):
'webhook_credential': obj.webhook_credential,
'webhook_guid': event_guid,
},
'extra_vars': {
'tower_webhook_event_type': event_type,
'tower_webhook_event_guid': event_guid,
'tower_webhook_event_ref': event_ref,
'tower_webhook_status_api': status_api,
'tower_webhook_payload': request.data,
},
'extra_vars': {},
}
for name in JOB_VARIABLE_PREFIXES:
kwargs['extra_vars']['{}_webhook_event_type'.format(name)] = event_type
kwargs['extra_vars']['{}_webhook_event_guid'.format(name)] = event_guid
kwargs['extra_vars']['{}_webhook_event_ref'.format(name)] = event_ref
kwargs['extra_vars']['{}_webhook_status_api'.format(name)] = status_api
kwargs['extra_vars']['{}_webhook_payload'.format(name)] = request.data
new_job = obj.create_unified_job(**kwargs)
new_job.signal_start()
@@ -203,7 +204,7 @@ class GitlabWebhookReceiver(WebhookReceiverBase):
return h.hexdigest()
def get_event_status_api(self):
if self.get_event_type() != 'Merge Request Hook':
if self.get_event_type() not in self.ref_keys.keys():
return
project = self.request.data.get('project', {})
repo_url = project.get('web_url')

View File

@@ -7,8 +7,6 @@ from django.utils.module_loading import autodiscover_modules
# AWX
from .registry import settings_registry
default_app_config = 'awx.conf.apps.ConfConfig'
def register(setting, **kwargs):
settings_registry.register(setting, **kwargs)

View File

@@ -1,8 +1,10 @@
import sys
# Django
from django.apps import AppConfig
# from django.core import checks
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
class ConfConfig(AppConfig):
@@ -12,6 +14,9 @@ class ConfConfig(AppConfig):
def ready(self):
self.module.autodiscover()
from .settings import SettingsWrapper
SettingsWrapper.initialize()
if not set(sys.argv) & {'migrate', 'check_migrations'}:
from .settings import SettingsWrapper
SettingsWrapper.initialize()

View File

@@ -1,6 +1,6 @@
# Django
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# AWX
from awx.conf import fields, register

View File

@@ -7,10 +7,10 @@ from collections import OrderedDict
# Django
from django.core.validators import URLValidator, _lazy_re_compile
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework.fields import BooleanField, CharField, ChoiceField, DictField, DateTimeField, EmailField, IntegerField, ListField, NullBooleanField # noqa
from rest_framework.fields import BooleanField, CharField, ChoiceField, DictField, DateTimeField, EmailField, IntegerField, ListField # noqa
from rest_framework.serializers import PrimaryKeyRelatedField # noqa
# AWX
@@ -65,11 +65,11 @@ class StringListBooleanField(ListField):
try:
if isinstance(value, (list, tuple)):
return super(StringListBooleanField, self).to_representation(value)
elif value in NullBooleanField.TRUE_VALUES:
elif value in BooleanField.TRUE_VALUES:
return True
elif value in NullBooleanField.FALSE_VALUES:
elif value in BooleanField.FALSE_VALUES:
return False
elif value in NullBooleanField.NULL_VALUES:
elif value in BooleanField.NULL_VALUES:
return None
elif isinstance(value, str):
return self.child.to_representation(value)
@@ -82,11 +82,11 @@ class StringListBooleanField(ListField):
try:
if isinstance(data, (list, tuple)):
return super(StringListBooleanField, self).to_internal_value(data)
elif data in NullBooleanField.TRUE_VALUES:
elif data in BooleanField.TRUE_VALUES:
return True
elif data in NullBooleanField.FALSE_VALUES:
elif data in BooleanField.FALSE_VALUES:
return False
elif data in NullBooleanField.NULL_VALUES:
elif data in BooleanField.NULL_VALUES:
return None
elif isinstance(data, str):
return self.child.run_validation(data)

View File

@@ -2,9 +2,10 @@
from __future__ import unicode_literals
from django.db import migrations, models
import jsonfield.fields
from django.conf import settings
import awx.main.fields
class Migration(migrations.Migration):
@@ -18,7 +19,7 @@ class Migration(migrations.Migration):
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('key', models.CharField(max_length=255)),
('value', jsonfield.fields.JSONField(null=True)),
('value', awx.main.fields.JSONBlob(null=True)),
(
'user',
models.ForeignKey(related_name='settings', default=None, editable=False, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True),

View File

@@ -2,6 +2,7 @@
from __future__ import unicode_literals
from django.db import migrations
import awx.main.fields
@@ -9,4 +10,4 @@ class Migration(migrations.Migration):
dependencies = [('conf', '0002_v310_copy_tower_settings')]
operations = [migrations.AlterField(model_name='setting', name='value', field=awx.main.fields.JSONField(null=True))]
operations = [migrations.AlterField(model_name='setting', name='value', field=awx.main.fields.JSONBlob(null=True))]

View File

@@ -5,7 +5,7 @@ from django.utils.timezone import now
def fill_ldap_group_type_params(apps, schema_editor):
group_type = settings.AUTH_LDAP_GROUP_TYPE
group_type = getattr(settings, 'AUTH_LDAP_GROUP_TYPE', None)
Setting = apps.get_model('conf', 'Setting')
group_type_params = {'name_attr': 'cn', 'member_attr': 'member'}
@@ -17,7 +17,7 @@ def fill_ldap_group_type_params(apps, schema_editor):
else:
entry = Setting(key='AUTH_LDAP_GROUP_TYPE_PARAMS', value=group_type_params, created=now(), modified=now())
init_attrs = set(inspect.getargspec(group_type.__init__).args[1:])
init_attrs = set(inspect.getfullargspec(group_type.__init__).args[1:])
for k in list(group_type_params.keys()):
if k not in init_attrs:
del group_type_params[k]

View File

@@ -8,8 +8,8 @@ import json
from django.db import models
# AWX
from awx.main.fields import JSONBlob
from awx.main.models.base import CreatedModifiedModel, prevent_search
from awx.main.fields import JSONField
from awx.main.utils import encrypt_field
from awx.conf import settings_registry
@@ -19,7 +19,7 @@ __all__ = ['Setting']
class Setting(CreatedModifiedModel):
key = models.CharField(max_length=255)
value = JSONField(null=True)
value = JSONBlob(null=True)
user = prevent_search(models.ForeignKey('auth.User', related_name='settings', default=None, null=True, editable=False, on_delete=models.CASCADE))
def __str__(self):

View File

@@ -8,7 +8,7 @@ import logging
# Django
from django.core.exceptions import ImproperlyConfigured
from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from awx.conf.license import get_license

View File

@@ -1,7 +1,6 @@
# Python
import contextlib
import logging
import sys
import threading
import time
import os
@@ -31,7 +30,7 @@ from awx.conf.models import Setting
logger = logging.getLogger('awx.conf.settings')
SETTING_MEMORY_TTL = 5 if 'callback_receiver' in ' '.join(sys.argv) else 0
SETTING_MEMORY_TTL = 5
# Store a special value to indicate when a setting is not set in the database.
SETTING_CACHE_NOTSET = '___notset___'
@@ -81,17 +80,16 @@ def _ctit_db_wrapper(trans_safe=False):
yield
except DBError as exc:
if trans_safe:
if 'migrate' not in sys.argv and 'check_migrations' not in sys.argv:
level = logger.exception
if isinstance(exc, ProgrammingError):
if 'relation' in str(exc) and 'does not exist' in str(exc):
# this generally means we can't fetch Tower configuration
# because the database hasn't actually finished migrating yet;
# this is usually a sign that a service in a container (such as ws_broadcast)
# has come up *before* the database has finished migrating, and
# especially that the conf.settings table doesn't exist yet
level = logger.debug
level('Database settings are not available, using defaults.')
level = logger.exception
if isinstance(exc, ProgrammingError):
if 'relation' in str(exc) and 'does not exist' in str(exc):
# this generally means we can't fetch Tower configuration
# because the database hasn't actually finished migrating yet;
# this is usually a sign that a service in a container (such as ws_broadcast)
# has come up *before* the database has finished migrating, and
# especially that the conf.settings table doesn't exist yet
level = logger.debug
level('Database settings are not available, using defaults.')
else:
logger.exception('Error modifying something related to database settings.')
finally:
@@ -235,6 +233,8 @@ class SettingsWrapper(UserSettingsHolder):
self.__dict__['_awx_conf_init_readonly'] = False
self.__dict__['cache'] = EncryptedCacheProxy(cache, registry)
self.__dict__['registry'] = registry
self.__dict__['_awx_conf_memoizedcache'] = cachetools.TTLCache(maxsize=2048, ttl=SETTING_MEMORY_TTL)
self.__dict__['_awx_conf_memoizedcache_lock'] = threading.Lock()
# record the current pid so we compare it post-fork for
# processes like the dispatcher and callback receiver
@@ -397,12 +397,20 @@ class SettingsWrapper(UserSettingsHolder):
def SETTINGS_MODULE(self):
return self._get_default('SETTINGS_MODULE')
@cachetools.cached(cache=cachetools.TTLCache(maxsize=2048, ttl=SETTING_MEMORY_TTL))
@cachetools.cachedmethod(
cache=lambda self: self.__dict__['_awx_conf_memoizedcache'],
key=lambda *args, **kwargs: SettingsWrapper.hashkey(*args, **kwargs),
lock=lambda self: self.__dict__['_awx_conf_memoizedcache_lock'],
)
def _get_local_with_cache(self, name):
"""Get value while accepting the in-memory cache if key is available"""
with _ctit_db_wrapper(trans_safe=True):
return self._get_local(name)
def __getattr__(self, name):
value = empty
if name in self.all_supported_settings:
with _ctit_db_wrapper(trans_safe=True):
value = self._get_local(name)
value = self._get_local_with_cache(name)
if value is not empty:
return value
return self._get_default(name)
@@ -476,6 +484,23 @@ class SettingsWrapper(UserSettingsHolder):
set_on_default = getattr(self.default_settings, 'is_overridden', lambda s: False)(setting)
return set_locally or set_on_default
@classmethod
def hashkey(cls, *args, **kwargs):
"""
Usage of @cachetools.cached has changed to @cachetools.cachedmethod
The previous cachetools decorator called the hash function and passed in (self, key).
The new cachtools decorator calls the hash function with just (key).
Ideally, we would continue to pass self, however, the cachetools decorator interface
does not allow us to.
This hashkey function is to maintain that the key generated looks like
('<SettingsWrapper>', key). The thought is that maybe it is important to namespace
our cache to the SettingsWrapper scope in case some other usage of this cache exists.
I can not think of how any other system could and would use our private cache, but
for safety sake we are ensuring the key schema does not change.
"""
return cachetools.keys.hashkey(f"<{cls.__name__}>", *args, **kwargs)
def __getattr_without_cache__(self, name):
# Django 1.10 added an optimization to settings lookup:

View File

@@ -28,6 +28,9 @@ def handle_setting_change(key, for_delete=False):
cache_keys = {Setting.get_cache_key(k) for k in setting_keys}
cache.delete_many(cache_keys)
# if we have changed a setting, we want to avoid mucking with the in-memory cache entirely
settings._awx_conf_memoizedcache.clear()
# Send setting_changed signal with new value for each setting.
for setting_key in setting_keys:
setting_changed.send(sender=Setting, setting=setting_key, value=getattr(settings, setting_key, None), enter=not bool(for_delete))

View File

@@ -6,7 +6,7 @@ from uuid import uuid4
from django.conf import LazySettings
from django.core.cache.backends.locmem import LocMemCache
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from rest_framework.fields import empty
import pytest

View File

@@ -8,10 +8,12 @@ import codecs
from uuid import uuid4
import time
from unittest import mock
from django.conf import LazySettings
from django.core.cache.backends.locmem import LocMemCache
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
import pytest
from awx.conf import models, fields
@@ -299,3 +301,33 @@ def test_readonly_sensitive_cache_data_is_encrypted(settings):
cache.set('AWX_ENCRYPTED', 'SECRET!')
assert cache.get('AWX_ENCRYPTED') == 'SECRET!'
assert native_cache.get('AWX_ENCRYPTED') == 'FRPERG!'
@pytest.mark.defined_in_file(AWX_VAR='DEFAULT')
def test_in_memory_cache_only_for_registered_settings(settings):
"Test that we only make use of the in-memory TTL cache for registered settings"
settings._awx_conf_memoizedcache.clear()
settings.MIDDLEWARE
assert len(settings._awx_conf_memoizedcache) == 0 # does not cache MIDDLEWARE
settings.registry.register('AWX_VAR', field_class=fields.CharField, category=_('System'), category_slug='system')
settings._wrapped.__dict__['all_supported_settings'] = ['AWX_VAR'] # because it is cached_property
settings._awx_conf_memoizedcache.clear()
assert settings.AWX_VAR == 'DEFAULT'
assert len(settings._awx_conf_memoizedcache) == 1 # caches registered settings
@pytest.mark.defined_in_file(AWX_VAR='DEFAULT')
def test_in_memory_cache_works(settings):
settings._awx_conf_memoizedcache.clear()
settings.registry.register('AWX_VAR', field_class=fields.CharField, category=_('System'), category_slug='system')
settings._wrapped.__dict__['all_supported_settings'] = ['AWX_VAR']
settings._awx_conf_memoizedcache.clear()
with mock.patch('awx.conf.settings.SettingsWrapper._get_local', return_value='DEFAULT') as mock_get:
assert settings.AWX_VAR == 'DEFAULT'
mock_get.assert_called_once_with('AWX_VAR')
with mock.patch.object(settings, '_get_local') as mock_get:
assert settings.AWX_VAR == 'DEFAULT'
mock_get.assert_not_called()

View File

@@ -1,13 +1,13 @@
# Copyright (c) 2016 Ansible, Inc.
# All Rights Reserved.
from django.urls import re_path
from django.conf.urls import url
from awx.conf.views import SettingCategoryList, SettingSingletonDetail, SettingLoggingTest
urlpatterns = [
url(r'^$', SettingCategoryList.as_view(), name='setting_category_list'),
url(r'^(?P<category_slug>[a-z0-9-]+)/$', SettingSingletonDetail.as_view(), name='setting_singleton_detail'),
url(r'^logging/test/$', SettingLoggingTest.as_view(), name='setting_logging_test'),
re_path(r'^$', SettingCategoryList.as_view(), name='setting_category_list'),
re_path(r'^(?P<category_slug>[a-z0-9-]+)/$', SettingSingletonDetail.as_view(), name='setting_singleton_detail'),
re_path(r'^logging/test/$', SettingLoggingTest.as_view(), name='setting_logging_test'),
]

View File

@@ -13,7 +13,7 @@ from socket import SHUT_RDWR
from django.db import connection
from django.conf import settings
from django.http import Http404
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework.exceptions import PermissionDenied

View File

@@ -1,3 +1,6 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
@@ -8,8 +11,7 @@ msgstr ""
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: es \n"
"MIME-Version: 1.0\n"
"Language: \n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -21,9 +23,7 @@ msgstr "Tiempo de inactividad fuerza desconexión"
msgid ""
"Number of seconds that a user is inactive before they will need to login "
"again."
msgstr ""
"Número de segundos que un usuario es inactivo antes de que ellos vuelvan a "
"conectarse de nuevo."
msgstr "Número de segundos que un usuario es inactivo antes de que ellos vuelvan a conectarse de nuevo."
#: awx/api/conf.py:21 awx/api/conf.py:31 awx/api/conf.py:42 awx/api/conf.py:50
#: awx/api/conf.py:70 awx/api/conf.py:85 awx/api/conf.py:96 awx/sso/conf.py:105
@@ -45,9 +45,7 @@ msgstr "Número máximo de sesiones activas en simultáneo"
msgid ""
"Maximum number of simultaneous logged in sessions a user may have. To "
"disable enter -1."
msgstr ""
"Número máximo de sesiones activas en simultáneo que un usuario puede tener. "
"Para deshabilitar, introduzca -1."
msgstr "Número máximo de sesiones activas en simultáneo que un usuario puede tener. Para deshabilitar, introduzca -1."
#: awx/api/conf.py:37
msgid "Disable the built-in authentication system"
@@ -58,10 +56,7 @@ msgid ""
"Controls whether users are prevented from using the built-in authentication "
"system. You probably want to do this if you are using an LDAP or SAML "
"integration."
msgstr ""
"Controla si se impide que los usuarios utilicen el sistema de autenticación "
"integrado. Probablemente desee hacer esto si está usando una integración de "
"LDAP o SAML."
msgstr "Controla si se impide que los usuarios utilicen el sistema de autenticación integrado. Probablemente desee hacer esto si está usando una integración de LDAP o SAML."
#: awx/api/conf.py:48
msgid "Enable HTTP Basic Auth"
@@ -83,13 +78,7 @@ msgid ""
"authorization codes in the number of seconds, and "
"`REFRESH_TOKEN_EXPIRE_SECONDS`, the duration of refresh tokens, after "
"expired access tokens, in the number of seconds."
msgstr ""
"Diccionario para personalizar los tiempos de espera de OAuth2; los elementos "
"disponibles son `ACCESS_TOKEN_EXPIRE_SECONDS`, la duración de los tokens de "
"acceso en cantidad de segundos; `AUTHORIZATION_CODE_EXPIRE_SECONDS`, la "
"duración de los códigos de autorización en cantidad de segundos; y "
"`REFRESH_TOKEN_EXPIRE_SECONDS`, la duración de los tokens de actualización, "
"después de los tokens de acceso expirados, en cantidad de segundos."
msgstr "Diccionario para personalizar los tiempos de espera de OAuth2; los elementos disponibles son `ACCESS_TOKEN_EXPIRE_SECONDS`, la duración de los tokens de acceso en cantidad de segundos; `AUTHORIZATION_CODE_EXPIRE_SECONDS`, la duración de los códigos de autorización en cantidad de segundos; y `REFRESH_TOKEN_EXPIRE_SECONDS`, la duración de los tokens de actualización, después de los tokens de acceso expirados, en cantidad de segundos."
#: awx/api/conf.py:78
msgid "Allow External Users to Create OAuth2 Tokens"
@@ -101,11 +90,7 @@ msgid ""
"Radius, and others) are not allowed to create OAuth2 tokens. To change this "
"behavior, enable this setting. Existing tokens will not be deleted when this "
"setting is toggled off."
msgstr ""
"Por motivos de seguridad, los usuarios de proveedores de autenticación "
"externos (LDAP, SAML, SSO, Radius y otros) no tienen permitido crear tokens "
"de OAuth2. Habilite este ajuste para cambiar este comportamiento. Los tokens "
"existentes no se eliminarán cuando se desactive este ajuste."
msgstr "Por motivos de seguridad, los usuarios de proveedores de autenticación externos (LDAP, SAML, SSO, Radius y otros) no tienen permitido crear tokens de OAuth2. Habilite este ajuste para cambiar este comportamiento. Los tokens existentes no se eliminarán cuando se desactive este ajuste."
#: awx/api/conf.py:94
msgid "Login redirect override URL"
@@ -115,10 +100,7 @@ msgstr "URL de invalidación de redireccionamiento de inicio de sesión"
msgid ""
"URL to which unauthorized users will be redirected to log in. If blank, "
"users will be sent to the login page."
msgstr ""
"URL a la que los usuarios no autorizados serán redirigidos para iniciar "
"sesión. Si está en blanco, los usuarios serán enviados a la página de inicio "
"de sesión."
msgstr "URL a la que los usuarios no autorizados serán redirigidos para iniciar sesión. Si está en blanco, los usuarios serán enviados a la página de inicio de sesión."
#: awx/api/conf.py:114
msgid "There are no remote authentication systems configured."
@@ -167,17 +149,13 @@ msgstr "ID{field_name} no válido: {field_id}"
msgid ""
"Cannot apply role_level filter to this list because its model does not use "
"roles for access control."
msgstr ""
"No se puede aplicar el filtro role_level a esta lista debido a que su modelo "
"no usa roles para el control de acceso."
msgstr "No se puede aplicar el filtro role_level a esta lista debido a que su modelo no usa roles para el control de acceso."
#: awx/api/generics.py:179
msgid ""
"You did not use correct Content-Type in your HTTP request. If you are using "
"our REST API, the Content-Type must be application/json"
msgstr ""
"No utilizó el Tipo de contenido correcto en su solicitud HTTP. Si está "
"usando nuestra API REST, el Tipo de contenido debe ser aplicación/json."
msgstr "No utilizó el Tipo de contenido correcto en su solicitud HTTP. Si está usando nuestra API REST, el Tipo de contenido debe ser aplicación/json."
#: awx/api/generics.py:220
msgid " To establish a login session, visit"
@@ -223,9 +201,7 @@ msgstr "Estructura de datos con URLs de recursos relacionados."
msgid ""
"Data structure with name/description for related resources. The output for "
"some objects may be limited for performance reasons."
msgstr ""
"Estructura de datos con nombre/descripción de los recursos relacionados. La "
"salida de algunos objetos puede estar limitada por motivos de rendimiento."
msgstr "Estructura de datos con nombre/descripción de los recursos relacionados. La salida de algunos objetos puede estar limitada por motivos de rendimiento."
#: awx/api/metadata.py:75
msgid "Timestamp when this {} was created."
@@ -248,17 +224,14 @@ msgstr "Error de análisis JSON; no es un objeto JSON"
msgid ""
"JSON parse error - %s\n"
"Possible cause: trailing comma."
msgstr ""
"Error de análisis JSON - %s\n"
msgstr "Error de análisis JSON - %s\n"
"Posible causa: coma final."
#: awx/api/serializers.py:205
msgid ""
"The original object is already named {}, a copy from it cannot have the same "
"name."
msgstr ""
"El objeto original ya tiene el nombre {}, por lo que una copia de este no "
"puede tener el mismo nombre."
msgstr "El objeto original ya tiene el nombre {}, por lo que una copia de este no puede tener el mismo nombre."
#: awx/api/serializers.py:334
#, python-format
@@ -301,9 +274,7 @@ msgstr "Plantilla de trabajo"
msgid ""
"Indicates whether all of the events generated by this unified job have been "
"saved to the database."
msgstr ""
"Indica si todos los eventos generados por esta tarea unificada se guardaron "
"en la base de datos."
msgstr "Indica si todos los eventos generados por esta tarea unificada se guardaron en la base de datos."
#: awx/api/serializers.py:939
msgid "Write-only field used to change the password."
@@ -324,8 +295,7 @@ msgstr "No se puede cambiar %s en el usuario gestionado por LDAP."
#: awx/api/serializers.py:1153
msgid "Must be a simple space-separated string with allowed scopes {}."
msgstr ""
"Debe ser una cadena simple separada por espacios con alcances permitidos {}."
msgstr "Debe ser una cadena simple separada por espacios con alcances permitidos {}."
#: awx/api/serializers.py:1238
msgid "Authorization Grant Type"
@@ -378,9 +348,7 @@ msgstr "SCM track_submodules solo puede usarse con proyectos git."
msgid ""
"Only Container Registry credentials can be associated with an Execution "
"Environment"
msgstr ""
"Solo las credenciales del registro de contenedores pueden asociarse a un "
"entorno de ejecución"
msgstr "Solo las credenciales del registro de contenedores pueden asociarse a un entorno de ejecución"
#: awx/api/serializers.py:1440
msgid "Cannot change the organization of an execution environment"
@@ -390,9 +358,7 @@ msgstr "No se puede modificar la organización de un entorno de ejecución"
msgid ""
"One or more job templates depend on branch override behavior for this "
"project (ids: {})."
msgstr ""
"Una o más plantillas de trabajo dependen del comportamiento de invalidación "
"de ramas para este proyecto (ids: {})."
msgstr "Una o más plantillas de trabajo dependen del comportamiento de invalidación de ramas para este proyecto (ids: {})."
#: awx/api/serializers.py:1530
msgid "Update options must be set to false for manual projects."
@@ -406,9 +372,7 @@ msgstr "Colección de playbooks disponibles dentro de este proyecto."
msgid ""
"Array of inventory files and directories available within this project, not "
"comprehensive."
msgstr ""
"Colección de archivos de inventario y directorios disponibles dentro de este "
"proyecto, no global."
msgstr "Colección de archivos de inventario y directorios disponibles dentro de este proyecto, no global."
#: awx/api/serializers.py:1599 awx/api/serializers.py:3098
#: awx/api/serializers.py:3311
@@ -560,7 +524,7 @@ msgstr "Playbook no encontrado para el proyecto."
#: awx/api/serializers.py:2842
msgid "Must select playbook for project."
msgstr "Debe seleccionar un playbook para el proyecto"
msgstr "Debe seleccionar un playbook para el proyecto."
#: awx/api/serializers.py:2844 awx/api/serializers.py:2846
msgid "Project does not allow overriding branch."
@@ -893,8 +857,7 @@ msgid "Containerized instances may not be managed via the API"
msgstr "Las instancias contenedorizadas no pueden ser gestionadas a través de la API."
#: awx/api/serializers.py:4919 awx/api/serializers.py:4922
#, fuzzy, python-format
#| msgid "tower instance group name may not be changed."
#, python-format
msgid "%s instance group name may not be changed."
msgstr "El nombre del grupo de instancia %s no puede modificarse."
@@ -1049,8 +1012,6 @@ msgid ""
msgstr "No puede asignar credenciales de acceso a un equipo cuando el campo de organización no está establecido o pertenezca a una organización diferente."
#: awx/api/views/__init__.py:720
#, fuzzy
#| msgid "The instance that managed the execution environment."
msgid "Only the 'pull' field can be edited for managed execution environments."
msgstr "Sólo se puede editar el campo \"pull\" para los entornos de ejecución gestionados."
@@ -2087,8 +2048,6 @@ msgid "Unique identifier for an installation"
msgstr "Identificador único para una instalación"
#: awx/main/conf.py:183
#, fuzzy
#| msgid "The Instance group the job was run under"
msgid "The instance group where control plane tasks run"
msgstr "Grupo de instancias donde se ejecutan las tareas del plano de control"
@@ -2796,8 +2755,6 @@ msgid "The identifier for the secret e.g., /some/identifier"
msgstr "El identificador para el secreto; por ejemplo, /some/identifier"
#: awx/main/credential_plugins/dsv.py:12
#, fuzzy
#| msgid "Tenant ID"
msgid "Tenant"
msgstr "Inquilino"
@@ -2816,8 +2773,6 @@ msgid ""
msgstr "El TLD del inquilino, por ejemplo, \"com\" cuando la URL es https://ex.secretservercloud.com"
#: awx/main/credential_plugins/dsv.py:34
#, fuzzy
#| msgid "Secret Name"
msgid "Secret Path"
msgstr "Ruta secreta"
@@ -2826,8 +2781,6 @@ msgid "The secret path e.g. /test/secret1"
msgstr "La ruta secreta, por ejemplo, /test/secret1"
#: awx/main/credential_plugins/dsv.py:46
#, fuzzy
#| msgid "Job Template"
msgid "URL template"
msgstr "Plantilla URL"
@@ -2960,8 +2913,6 @@ msgid ""
msgstr "Principales válidos (ya sea nombres de usuario o nombres de host) para los que se debería firmar el certificado:"
#: awx/main/credential_plugins/tss.py:10
#, fuzzy
#| msgid "Auth Server URL"
msgid "Secret Server URL"
msgstr "URL del servidor secreto"
@@ -2972,8 +2923,6 @@ msgid ""
msgstr "La URL base del servidor secreto, por ejemplo, https://myserver/SecretServer o https://mytenant.secretservercloud.com"
#: awx/main/credential_plugins/tss.py:17
#, fuzzy
#| msgid "Red Hat customer username"
msgid "The (Application) user username"
msgstr "El nombre de usuario (de la aplicación)"
@@ -2995,20 +2944,14 @@ msgid "The corresponding password"
msgstr "La contraseña correspondiente"
#: awx/main/credential_plugins/tss.py:31
#, fuzzy
#| msgid "Secret Key"
msgid "Secret ID"
msgstr "Identificación secreta"
#: awx/main/credential_plugins/tss.py:32
#, fuzzy
#| msgid "The name of the secret to look up."
msgid "The integer ID of the secret"
msgstr "El ID entero del secreto"
#: awx/main/credential_plugins/tss.py:37
#, fuzzy
#| msgid "Secret Key"
msgid "Secret Field"
msgstr "Campo secreto"
@@ -3568,22 +3511,14 @@ msgstr "Ruta de archivo absoluta al archivo CA por usar (opcional)"
#: awx/main/models/credential/__init__.py:1023
#: awx/main/models/credential/__init__.py:1029 awx/main/models/inventory.py:813
#, fuzzy
#| msgid "Gather data for Insights for Ansible Automation Platform"
msgid "Red Hat Ansible Automation Platform"
msgstr "Plataforma Red Hat Ansible Automation"
#: awx/main/models/credential/__init__.py:1031
#, fuzzy
#| msgid "The Ansible Tower base URL to authenticate with."
msgid "Red Hat Ansible Automation Platform base URL to authenticate with."
msgstr "URL base de Red Hat Ansible Automation Platform para autenticar."
#: awx/main/models/credential/__init__.py:1038
#, fuzzy
#| msgid ""
#| "The Ansible Tower user to authenticate as.This should not be set if an "
#| "OAuth token is being used."
msgid ""
"Red Hat Ansible Automation Platform username id to authenticate as.This "
"should not be set if an OAuth token is being used."
@@ -4488,7 +4423,7 @@ msgstr "El número de segundos desde de que la última actualización del proyec
msgid ""
"Allow changing the SCM branch or revision in a job template that uses this "
"project."
msgstr "Permitir el cambio de la rama o revisión del SCM en una plantilla de trabajo que utilice este proyecto."
msgstr "Permitir el cambio de la rama o revisión de SCM en una plantilla de trabajo que utilice este proyecto."
#: awx/main/models/projects.py:294
msgid "The last revision fetched by a project update"
@@ -4925,7 +4860,7 @@ msgid "Exception connecting to PagerDuty: {}"
msgstr "Excepción conectando a PagerDuty: {}"
#: awx/main/notifications/pagerduty_backend.py:87
#: awx/main/notifications/slack_backend.py:48
#: awx/main/notifications/slack_backend.py:49
#: awx/main/notifications/twilio_backend.py:47
msgid "Exception sending messages: {}"
msgstr "Excepción enviando mensajes: {}"
@@ -5181,7 +5116,7 @@ msgstr "Al menos un certificado es necesario."
msgid ""
"At least %(min_certs)d certificates are required, only %(cert_count)d "
"provided."
msgstr "Se requieren al menos %(min_certs)d certificados, sólo %(cert_count)d proporcionados."
msgstr "Al menos %(min_certs)d certificados son necesarios, solo se proporcionó %(cert_count)d."
#: awx/main/validators.py:152
#, python-format
@@ -5195,8 +5130,7 @@ msgid ""
msgstr "No se permiten más de %(max_certs)d certificados, %(cert_count)d proporcionado."
#: awx/main/validators.py:289
#, fuzzy, python-brace-format
#| msgid "The container image to be used for execution."
#, python-brace-format
msgid "The container image name {value} is not valid"
msgstr "El nombre de la imagen del contenedor {value} no es válido"
@@ -5666,17 +5600,17 @@ msgstr "La clave secreta OAuth2 (Clave secreta del cliente) from your GitHub org
#: awx/sso/conf.py:751
msgid "GitHub Organization Name"
msgstr "Nombre de la organización de GitHub"
msgstr "Nombre para la organización GitHub"
#: awx/sso/conf.py:752
msgid ""
"The name of your GitHub organization, as used in your organization's URL: "
"https://github.com/<yourorg>/."
msgstr "El nombre de su organización de GitHub, como se utiliza en la URL de su organización: https://github.com/<votreorg>/."
msgstr "El nombre de su organización de GitHub, como se utiliza en la URL de su organización: https://github.com/<yourorg>/."
#: awx/sso/conf.py:762
msgid "GitHub Organization OAuth2 Organization Map"
msgstr "Mapa de organización de OAuth2 de la organización de GitHub"
msgstr "Mapa de organización OAuth2 para organizaciones GitHub"
#: awx/sso/conf.py:774
msgid "GitHub Organization OAuth2 Team Map"
@@ -5684,7 +5618,7 @@ msgstr "Mapa de equipos OAuth2 para equipos GitHub"
#: awx/sso/conf.py:790
msgid "GitHub Team OAuth2 Callback URL"
msgstr "URL de devolución de OAuth2 del equipo de GitHub"
msgstr "URL callback OAuth2 para los equipos GitHub"
#: awx/sso/conf.py:792 awx/sso/conf.py:1060
msgid ""
@@ -5692,12 +5626,12 @@ msgid ""
"<yourorg>/settings/applications and obtain an OAuth2 key (Client ID) and "
"secret (Client Secret). Provide this URL as the callback URL for your "
"application."
msgstr "Cree una aplicación propiedad de la organización en https://github.com/organizations/<votreorg>/settings/applications y obtenga una clave de OAuth2 (ID del cliente) y secreta (clave secreta de cliente). Proporcione esta URL como URL de devolución para su aplicación."
msgstr "Cree una aplicación propiedad de la organización en https://github.com/organizations/<yourorg>/settings/applications y obtenga una clave de OAuth2 (ID del cliente) y secreta (clave secreta de cliente). Proporcione esta URL como URL de devolución para su aplicación."
#: awx/sso/conf.py:797 awx/sso/conf.py:809 awx/sso/conf.py:820
#: awx/sso/conf.py:832 awx/sso/conf.py:843 awx/sso/conf.py:855
msgid "GitHub Team OAuth2"
msgstr "OAuth2 de equipo de GitHub"
msgstr "OAuth2 para equipos GitHub"
#: awx/sso/conf.py:807
msgid "GitHub Team OAuth2 Key"
@@ -5828,7 +5762,7 @@ msgstr "Nombre de la organización de GitHub Enterprise"
msgid ""
"The name of your GitHub Enterprise organization, as used in your "
"organization's URL: https://github.com/<yourorg>/."
msgstr "El nombre de su organización de GitHub Enterprise, como se utiliza en la URL de su organización: https://github.com/<votreorg>/."
msgstr "El nombre de su organización de GitHub Enterprise, como se utiliza en la URL de su organización: https://github.com/<yourorg>/."
#: awx/sso/conf.py:1030
msgid "GitHub Enterprise Organization OAuth2 Organization Map"
@@ -6303,68 +6237,4 @@ msgstr "%s se está actualizando."
#: awx/ui/urls.py:24
msgid "This page will refresh when complete."
msgstr "Esta página se actualizará cuando se complete."
#~ msgid "SSLError while trying to connect to {}"
#~ msgstr "SSLError al intentar conectarse a {}"
#~ msgid "Request to {} timed out."
#~ msgstr "El tiempo de solicitud {} caducó."
#~ msgid "Unknown exception {} while trying to GET {}"
#~ msgstr "Excepción desconocida {} al intentar usar GET {}"
#~ msgid ""
#~ "Unauthorized access. Please check your Insights Credential username and "
#~ "password."
#~ msgstr ""
#~ "Acceso no autorizado. Verifique su nombre de usuario y contraseña de "
#~ "Insights."
#~ msgid ""
#~ "Failed to access the Insights API at URL {}. Server responded with {} "
#~ "status code and message {}"
#~ msgstr ""
#~ "No se pudo acceder a la API de Insights en la URL {}. El servidor "
#~ "respondió con el código de estado {} y el mensaje {}"
#~ msgid "Expected JSON response from Insights at URL {} but instead got {}"
#~ msgstr ""
#~ "Respuesta JSON esperada de Insights en la URL {}; en cambio, se recibió {}"
#~ msgid ""
#~ "Could not translate Insights system ID {} into an Insights platform ID."
#~ msgstr ""
#~ "No se pudo traducir el ID del sistema Insights {} en un ID de plataforma "
#~ "de Insights."
#~ msgid "This host is not recognized as an Insights host."
#~ msgstr "Este host no se reconoce como un host de Insights."
#~ msgid "The Insights Credential for \"{}\" was not found."
#~ msgstr "No se encontró la credencial de Insights para \"{}\"."
#~ msgid ""
#~ "The path to the secret stored in the secret backend e.g, /some/secret/"
#~ msgstr ""
#~ "La ruta al secreto almacenado en el backend de secretos; por ejemplo, /"
#~ "some/secret/"
#~ msgid "Ansible Tower"
#~ msgstr "Ansible Tower"
#~ msgid "Ansible Tower Hostname"
#~ msgstr "Nombre de host de Ansible Tower"
#~ msgid ""
#~ "Credentials to be used by hosts belonging to this inventory when "
#~ "accessing Red Hat Insights API."
#~ msgstr ""
#~ "Credenciales que utilizarán los hosts que pertenecen a este inventario "
#~ "cuando accedan a la API de Red Hat Insights."
#~ msgid "Assignment not allowed for Smart Inventory"
#~ msgstr "Tarea no permitida para el inventario inteligente"
#~ msgid "Red Hat Insights host unique identifier."
#~ msgstr "Identificador único de host de Red Hat Insights."
msgstr "Esta página se actualizará cuando se complete."

Some files were not shown because too many files have changed in this diff Show More