Compare commits

...

1295 Commits

Author SHA1 Message Date
softwarefactory-project-zuul[bot]
0a1ecd4fe3 Merge pull request #8248 from ryanpetrello/15.0.0-bump
bump version to 15.0.0

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-30 13:07:08 +00:00
softwarefactory-project-zuul[bot]
e7a5d4c5d8 Merge pull request #8267 from mabashian/8252-jt-tabs-reload
Reset error/result only after the next request has resolved to prevent render flickering

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-30 12:24:08 +00:00
Ryan Petrello
2e371dd2ea more 15.0.0 changelog 2020-09-29 17:38:42 -04:00
Ryan Petrello
98b24cd2d8 Bump version to 15.0.0 2020-09-29 17:36:32 -04:00
softwarefactory-project-zuul[bot]
abc6a84210 Merge pull request #8260 from ryanpetrello/drf-upgrade
update to the latest Django Rest Framework

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-29 20:59:45 +00:00
softwarefactory-project-zuul[bot]
a9cfae70ff Merge pull request #8041 from mabashian/7680-inv-pending-delete
Adds support for pending deletion on inventory list

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-29 20:07:17 +00:00
softwarefactory-project-zuul[bot]
f47812845e Merge pull request #8229 from nixocio/ui_issue_7410
Make filter a bit more consistent accross UI

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-29 19:53:52 +00:00
mabashian
e13b16bf1c Add erroneously removed exhaustive dep comment 2020-09-29 15:42:11 -04:00
nixocio
aa69b925ad Make filter a bit more consistent accross UI
Add `description`, `created_by` and `modified_by` when those fields are
available.

See: https://github.com/ansible/awx/issues/7410
2020-09-29 15:23:28 -04:00
mabashian
ae1d27255b Add delete error handling on inventory detail view 2020-09-29 15:05:35 -04:00
mabashian
f672cee3a0 Reset error/result only after the next request has resolved to prevent render flicking 2020-09-29 13:11:06 -04:00
softwarefactory-project-zuul[bot]
820d4d292e Merge pull request #8253 from beeankha/edit_approval_node_bugfix
Fix Approval Node Edit Permissions

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-29 16:45:07 +00:00
softwarefactory-project-zuul[bot]
70dfe9a1f2 Merge pull request #8265 from Lodenk/typofix
fixed typo in the word example

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-29 16:36:58 +00:00
softwarefactory-project-zuul[bot]
6567fab1c8 Merge pull request #8251 from ryanpetrello/fix-vault-password-prompt-bug
fix a bug that can break password prompting in certain scenarios

Reviewed-by: Ryan Petrello
             https://github.com/ryanpetrello
2020-09-29 16:35:55 +00:00
beeankha
f584c1cc47 Fix Approval Node Edit Permissions 2020-09-29 12:14:12 -04:00
Patrick
359682022f fixed typo in the word example 2020-09-29 12:00:37 -04:00
softwarefactory-project-zuul[bot]
f39015156b Merge pull request #8228 from john-westcott-iv/tower_ad_hoc_module
Adding ad hoc command modules

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-29 14:59:52 +00:00
Ryan Petrello
089b0503bb update to the latest Django Rest Framework 2020-09-29 10:25:07 -04:00
softwarefactory-project-zuul[bot]
2019f808b9 Merge pull request #8254 from RULCSoft/fix-typos
Fix a few typos in awx/ui

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-29 14:04:51 +00:00
mabashian
3f1434f0f5 Only attempt to display sting error messages in ErrorDetail 2020-09-29 09:59:39 -04:00
softwarefactory-project-zuul[bot]
7f7864fe2b Merge pull request #8259 from rooftopcellist/gettext_translations
Include Gettext in dev container image for translation automation

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-29 13:48:28 +00:00
Ryan Petrello
c52054951d fix a bug that can break password prompting in certain scenarios
see: https://github.com/ansible/awx/issues/8202
2020-09-29 09:34:38 -04:00
mabashian
6942b4d5b6 Change deleteTeams to deleteInventories 2020-09-29 09:29:18 -04:00
mabashian
10110643ed Flatten out decision tree when an inventory websocket message is processed 2020-09-29 09:09:52 -04:00
mabashian
40e4ba43ef Copy the query params so that we don't add id__in to them. This fixes a bug where a newly copied row would not show up on the list if a websocket message for an inventory source sync had come through beforehand because id__in had been added to the query params. 2020-09-29 09:09:52 -04:00
mabashian
6681ffa8df Add default module_name to adhoc details step test to get rid of logged console error 2020-09-29 09:09:52 -04:00
mabashian
d84615f64b Rename onLoading/onDoneLoading props to onCopyStart and onCopyFinish. Wrap the functions being passed in as those props in useCallback to keep them hooks safe. 2020-09-29 09:09:52 -04:00
mabashian
4b566e9388 Adds support for pending deletion on inventory list 2020-09-29 09:09:52 -04:00
Christian M. Adams
e7b5f311b5 Include Gettext in dev container image for translation automation 2020-09-29 08:53:18 -04:00
Jorge Vallecillo
b335f698e4 Fix a few typos in awx/ui 2020-09-28 19:00:25 -06:00
softwarefactory-project-zuul[bot]
d6201d9eb6 Merge pull request #8224 from tchellomello/import_db
Ability to import standard pgdump into Openshift

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-28 17:24:35 +00:00
softwarefactory-project-zuul[bot]
d6f0e16b4d Merge pull request #8242 from wenottingham/certifi-ably-unbundled
Replace certifi with an alternate version

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-28 16:10:30 +00:00
softwarefactory-project-zuul[bot]
0c7bfa543b Merge pull request #8001 from velzend/allow_skipping_provision_instance_and_register_queue
allow skipping provision instance and register queue

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-28 15:20:35 +00:00
softwarefactory-project-zuul[bot]
36d4f255a3 Merge pull request #8236 from ryanpetrello/more-callback-cleanup
refactor some callback receiver code

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-28 15:20:29 +00:00
softwarefactory-project-zuul[bot]
30fd418cc9 Merge pull request #8220 from mabashian/fix-padding-pol-fields
Fix padding on field labels with prompt on launch checkboxes

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-28 13:42:37 +00:00
softwarefactory-project-zuul[bot]
24e9484f55 Merge pull request #7338 from mabashian/cred-plugin-test-button
Hook up Test button on Metadata step in credential plugin wizard

Reviewed-by: John Hill <johill@redhat.com>
             https://github.com/unlikelyzero
2020-09-25 19:52:44 +00:00
Bill Nottingham
85b694410b Adjust included licenses 2020-09-25 15:51:55 -04:00
Bill Nottingham
d0ba59735c Replace certifi with an alternate version
This version just uses the system cert store.
2020-09-25 14:39:16 -04:00
beeankha
b34c1f4c79 Update integration tests 2020-09-25 13:23:34 -04:00
Ryan Petrello
baad765179 refactor some callback receiver code
the bigint migration removed the foreign key constraints for:

- host_id
- job_id (and projectupdate_id, etc...)

because of this, we don't really need to check explicitly for a host_id
IntegrityError anymore (because it won't occur)

additionally, while it's possible to insert an event with a mismatched
job_id now (for example, you can totally start a long-running job, and
delete the job record in the background using the ORM or psql), doing
so results in DoesNotExist errors in the code that handles the
playbook_on_stats events
2020-09-25 13:12:42 -04:00
softwarefactory-project-zuul[bot]
b4d6270eab Merge pull request #8232 from mabashian/8219-extra-GET-requests
Fix extra GET requests on Notif Template/Container Groups forms

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-25 13:37:43 +00:00
John Westcott IV
842e490ba6 Removing needs devel ad hoc entry 2020-09-25 08:51:28 -04:00
John Westcott IV
5b10482256 Fixing linting 2020-09-25 08:49:28 -04:00
John Westcott IV
baf3b617cb Initial commit of ad hoc module 2020-09-25 08:49:28 -04:00
softwarefactory-project-zuul[bot]
acc0ba570e Merge pull request #8205 from john-westcott-iv/tower_application_continuation
Tower application continuation

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-25 00:24:01 +00:00
mabashian
56ed2c6afa Autopopulate credential on container group form and organization on notification template form 2020-09-24 17:26:33 -04:00
mabashian
24a4236232 Wrap onChange functions passed to lookups in useCallback since these functions are eventually passed to a hook and used in a dependency array. 2020-09-24 17:07:58 -04:00
softwarefactory-project-zuul[bot]
ce65ed0ac6 Merge pull request #8191 from ryanpetrello/callback-directly-to-redis
remove multiprocessing.Queue usage from the callback receiver

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-24 18:21:49 +00:00
Ryan Petrello
cd0b9de7b9 remove multiprocessing.Queue usage from the callback receiver
instead, just have each worker connect directly to redis
this has a few benefits:

- it's simpler to explain and debug
- back pressure on the queue keeps messages around in redis (which is
  observable, and survives the restart of Python processes)
- it's likely notably more performant at high loads
2020-09-24 13:53:58 -04:00
John Westcott IV
a9ea2523c9 Fixing linting/doc issues 2020-09-24 13:33:35 -04:00
softwarefactory-project-zuul[bot]
d97f80df43 Merge pull request #8221 from beeankha/job_timeout_notification_bugfix
Enable "On Fail" Notifications to Send Upon Timeout of Job Templates

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-24 13:53:04 +00:00
Marcelo Moreira de Mello
f1b8a63d91 Ability to import standard pgdump into Openshift 2020-09-23 22:33:57 -04:00
beeankha
c855ce95aa Fix JT timeout notification bug 2020-09-23 15:45:11 -04:00
mabashian
b714a0dc7e Fix padding on field labels with prompt on launch checkboxes 2020-09-23 15:27:31 -04:00
softwarefactory-project-zuul[bot]
aac17b9d2c Merge pull request #8206 from ryanpetrello/more-bulk-update-last-job
change host -> last_job_id bulk update query to avoid locking issues

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-23 15:18:42 +00:00
softwarefactory-project-zuul[bot]
d7ca49ce4a Merge pull request #8193 from ryanpetrello/ws-broadcast-limited
add a few additional optimizations to the callback receiver

Reviewed-by: Shane McDonald <me@shanemcd.com>
             https://github.com/shanemcd
2020-09-23 14:58:41 +00:00
John Westcott IV
4a4e62e035 Removing tower_application from needs_development in completeness test 2020-09-23 09:54:06 -04:00
softwarefactory-project-zuul[bot]
e5f5ad198a Merge pull request #8212 from branic/add_postgres_custom_root_ca
Add custom root ca certificate via configmap

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-23 13:41:13 +00:00
softwarefactory-project-zuul[bot]
ee3f835ea9 Merge pull request #8213 from ryanpetrello/galaxy-ignore-certs-ui
expose GALAXY_IGNORE_CERTS in the job settings UI

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-23 13:15:28 +00:00
John Westcott IV
cb1ba9e3a4 Fixing zuul issues 2020-09-23 09:03:03 -04:00
Ryan Petrello
1f0cd8df71 expose GALAXY_IGNORE_CERTS in the job settings UI 2020-09-23 08:36:52 -04:00
Brant Evans
512da5a01c Add custom root ca certificate via configmap
Signed-off-by: Brant Evans <bevans@redhat.com>
2020-09-22 16:42:39 -07:00
Ryan Petrello
89ff8e1f3e change host -> last_job_id bulk update query to avoid locking issues
see: https://github.com/ansible/awx/issues/8145
2020-09-22 16:04:28 -04:00
softwarefactory-project-zuul[bot]
3184bccb33 Merge pull request #8204 from marshmalien/words-matter-pt2
Replace google oauth2 setting with more inclusive language

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-22 19:43:40 +00:00
John Westcott IV
c5df37777b Addig tests and updating minor module bugs 2020-09-22 15:22:35 -04:00
Marliana Lara
0732b047b5 Replace setting term with inclusive language 2020-09-22 15:09:55 -04:00
Geoffrey Bachelot
1c729518a5 Delete depcreated username parameter 2020-09-22 14:54:35 -04:00
Geoffrey Bachelot
5a374585de delete deprecated parameters and add missing skip_authorization 2020-09-22 14:54:35 -04:00
Geoffrey Bachelot
b9d2e431a6 Create tower_application module 2020-09-22 14:54:35 -04:00
Ryan Petrello
b370e8389e add a few additional optimizations to the callback receiver 2020-09-22 08:51:01 -04:00
Jake McDermott
b6afc085a7 Reload on stats when live updates are disabled 2020-09-21 20:42:44 -04:00
Ryan Petrello
bed2dea04d don't broadcast ws:// events when UI_LIVE_UPDATES_ENABLED is False 2020-09-21 20:42:39 -04:00
softwarefactory-project-zuul[bot]
31cd36b768 Merge pull request #8104 from mabashian/4254-auto-pop-lookup
Auto populate various required lookups on various forms

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-21 21:37:02 +00:00
softwarefactory-project-zuul[bot]
dc492d0cfd Merge pull request #8179 from nixocio/ui_fix_undefined_variable
Fix issue with undefined variable

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-21 18:28:15 +00:00
softwarefactory-project-zuul[bot]
9a8580144c Merge pull request #8189 from kdelee/analytics_logging
Need log level info to show up with new settings

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-21 17:52:15 +00:00
mabashian
10ae6c9042 Cleans up console error thrown from this test. Also fixed the last test as it wasn't actually testing the desired behavior. 2020-09-21 13:24:23 -04:00
mabashian
8bee409a4a Auto populate various required lookups on various forms 2020-09-21 13:24:23 -04:00
Elijah DeLee
7c7d15a8be Need log level info to show up with new settings 2020-09-21 11:22:43 -04:00
softwarefactory-project-zuul[bot]
9eb8ac620f Merge pull request #8180 from jakemcdermott/deps-autofix
Upgrade lingui-cli to 2.9.2

Reviewed-by: John Hill <johill@redhat.com>
             https://github.com/unlikelyzero
2020-09-21 15:08:19 +00:00
softwarefactory-project-zuul[bot]
44d1e15ef4 Merge pull request #8177 from ryanpetrello/rrule-bug
fix an rrule bug that causes improper HOURLY/MINUTELY calculation

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-18 20:02:10 +00:00
softwarefactory-project-zuul[bot]
0c81b83080 Merge pull request #8078 from nixocio/ui_issue_8073
Add Container Group details

Reviewed-by: Kersom
             https://github.com/nixocio
2020-09-18 19:15:14 +00:00
softwarefactory-project-zuul[bot]
a2408892a8 Merge pull request #8152 from AlanCoding/import_fix
Fix AWX collection import test interference with Default organization

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-18 19:05:22 +00:00
softwarefactory-project-zuul[bot]
deab7395f2 Merge pull request #8150 from keithjgrant/7878-notification-websockets
Update status after sending test notification

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-18 17:52:38 +00:00
Keith Grant
3ed05e9d9b fix NotificationTemplateItem test 2020-09-18 10:20:17 -07:00
Jake McDermott
34579226ef Upgrade lingui-cli to 2.9.2 2020-09-18 13:01:04 -04:00
nixocio
9d0b37e96c Fix issue with undefined variable
Fix issue with undefined variable when data related to `me` is not
available.
2020-09-18 12:30:53 -04:00
softwarefactory-project-zuul[bot]
256123dc9d Merge pull request #8168 from keithjgrant/3321-session-management
Logout session if config returns 401

Reviewed-by: John Hill <johill@redhat.com>
             https://github.com/unlikelyzero
2020-09-18 16:08:06 +00:00
Ryan Petrello
bf1d93168b fix an rrule bug that causes improper HOURLY/MINUTELY calculation
see: https://github.com/ansible/awx/issues/8071
2020-09-18 12:06:07 -04:00
softwarefactory-project-zuul[bot]
39497fa502 Merge pull request #8178 from ryanpetrello/callback-status-sos
report callback receiver status in the sosreport

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-18 15:15:21 +00:00
Ryan Petrello
a1ddbd760d report callback receiver status in the sosreport 2020-09-18 10:49:50 -04:00
softwarefactory-project-zuul[bot]
c17bb36bcd Merge pull request #8167 from ryanpetrello/callback-cleanup
Add support for a `--status` to the callback receiver (and improve our approach to stats collection in general)

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-18 13:58:30 +00:00
Keith Grant
43d339d1cd fix test 2020-09-17 13:46:43 -07:00
softwarefactory-project-zuul[bot]
56c5a39087 Merge pull request #8159 from john-westcott-iv/lookup_plugin_fix
Fixing issue with lookup plugin not able to load host, user, etc

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-17 20:03:15 +00:00
Ryan Petrello
57f8e48894 make --status more robust for dispatcher, and add support for receiver
make the --status flag work by fetching a periodically recorded snapshot
of internal process state; additionally, update the callback receiver to
*also* record these statistics so we can gain more insight into any
performance issues
2020-09-17 15:33:37 -04:00
Keith Grant
cde8cb57da allow app skeleton to display while config is loading 2020-09-17 12:31:13 -07:00
softwarefactory-project-zuul[bot]
969f75778c Merge pull request #8166 from wenottingham/log-log-log
Fix analytics logging

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-17 18:42:29 +00:00
Bill Nottingham
18c27437b7 Fix analytics logging
The analytics change PR adjusted the logging for awx.analytics,
which solved the issue, but should have used the targeted awx.main.analytics.

Also flip a couple of loggers to use the regular awx.analytics (awx analytics)
logger instead of awx.main.analytics (the automation anayltics task system).
2020-09-17 13:39:14 -04:00
John Westcott IV
baa00bd582 Truthy strikes again 2020-09-17 07:51:01 -04:00
Keith Grant
6c4f9364ee kick back to login page if config gets 401 response 2020-09-16 15:35:02 -07:00
John Westcott IV
ee3a90d193 Adding example of specifying connection info 2020-09-16 14:52:41 -04:00
John Westcott IV
24bdbd8c58 Fixing issue with lookup plugin not able to load host, user, etc 2020-09-16 14:41:04 -04:00
Ryan Petrello
0df6409244 remove task state tracking from the callback receiver
we don't have support for displaying these stats anyways, so there's
no point in using resources tracking them, especially for high-volume
installs
2020-09-16 13:40:42 -04:00
softwarefactory-project-zuul[bot]
aceb8229ba Merge pull request #8153 from AlanCoding/delete_things
Remove out of date collection testing tools

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-16 15:05:56 +00:00
Alan Rominger
e177432b8f Do not expect failure in tower_import test 2020-09-16 10:34:11 -04:00
softwarefactory-project-zuul[bot]
1860a2f71d Merge pull request #8087 from AlanCoding/update_secrets
Add new option update_secrets to allow lazy or strict updating

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-16 03:19:55 +00:00
Alan Rominger
05fb47dece Remove out of date collection testing tools 2020-09-15 22:59:12 -04:00
Alan Rominger
3aec1a115d fix wording 2020-09-15 22:38:37 -04:00
Alan Rominger
2f1a9a28ea streamline credential test 2020-09-15 22:38:37 -04:00
Alan Rominger
362d6a3204 Add new option update_secrets to allow lazy or strict updating 2020-09-15 22:38:37 -04:00
Nicolas Payart
8e97214309 Add option update_password (always, on_create) to tower_user module 2020-09-15 22:37:50 -04:00
Alan Rominger
48f30c5106 Fix AWX collection import test interference with Default organization 2020-09-15 22:03:37 -04:00
Keith Grant
a10f52c70e poll for notification status after sending test 2020-09-15 15:37:44 -07:00
softwarefactory-project-zuul[bot]
ef3a497c42 Merge pull request #8147 from ryanpetrello/py-path
move an optional import for awxkit

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-15 19:32:26 +00:00
softwarefactory-project-zuul[bot]
4b72630087 Merge pull request #8136 from neoaggelos/awxkit-import-yaml-loader
Support `!import` and `!include` in `awx import -f yaml` command

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-15 18:56:06 +00:00
softwarefactory-project-zuul[bot]
432e167930 Merge pull request #8105 from keithjgrant/7877-notification-custom-messages
Notification Detail: show custom messages

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-15 18:53:41 +00:00
Ryan Petrello
1a533a2a23 move an optional import for awxkit
I'm not sure that this function is actually in use anywhere anymore, but
it shouldn't be a top-level import because it represents an optional
dependency.
2020-09-15 14:50:01 -04:00
Keith Grant
fa0abc0dd8 notification templates: fix un-select all 2020-09-15 10:56:55 -07:00
softwarefactory-project-zuul[bot]
b0875965db Merge pull request #8138 from moreiramarti/devel
K8s ServiceAccount variabilization

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-15 14:35:08 +00:00
nixocio
d3d3fe8892 Add Container Group details
Add Container Group details.

See: https://github.com/ansible/awx/issues/8073
2020-09-15 09:11:34 -04:00
Keith Grant
236ae6c5b6 handle null messages.workflow_approval some more 2020-09-14 16:05:03 -07:00
Keith Grant
b27d9b680a handle null messages.workflow_approval 2020-09-14 15:17:39 -07:00
softwarefactory-project-zuul[bot]
22bff7adec Merge pull request #8141 from kdelee/fix_analytics_tests
Print one targz per line (analytics gather)

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-14 22:04:23 +00:00
softwarefactory-project-zuul[bot]
a90bb36b72 Merge pull request #8055 from mabashian/8052-workflow-viz-rbac
Fixes some rbac issues in the workflow toolbar and start screen

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-14 21:14:12 +00:00
Elijah DeLee
d8e4ac773b Print one tarball per line
Printing out a python like list is hard to process for tests
Better to print out one tarball per line
2020-09-14 17:00:31 -04:00
softwarefactory-project-zuul[bot]
1a581a79ea Merge pull request #8070 from nixocio/ui_add_edit_container_groups
Add/Edit Container Groups

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-14 20:48:05 +00:00
softwarefactory-project-zuul[bot]
99da5770a7 Merge pull request #8139 from ansible/jakemcdermott-remove-self-closing-tag-tags
Remove self-closing tags for tag component

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-14 16:59:55 +00:00
Martinho Moreira
8d5914b3f1 K8s ServiceAccount variabilization 2020-09-14 17:37:45 +02:00
Jake McDermott
c6aeb755a4 Remove self-closing tags for tag component 2020-09-14 11:28:52 -04:00
softwarefactory-project-zuul[bot]
9d66b41e84 Merge pull request #7991 from bbayszczak/hashivault_auth_path_in_inputs
hashivault_kv auth_path moved from metadata to inputs

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-09-14 15:28:07 +00:00
Aggelos Kolaitis
b8cf644959 Add name to StringIO object to fix failing test 2020-09-13 17:41:53 +03:00
Aggelos Kolaitis
9918b2581c Support !import and !include in awx import -f yaml command 2020-09-13 17:01:12 +03:00
softwarefactory-project-zuul[bot]
b69fad83b1 Merge pull request #7709 from wenottingham/so-many-del-toros
Adjust analytics gathering

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-11 21:41:05 +00:00
softwarefactory-project-zuul[bot]
424bf94a15 Merge pull request #8101 from ansible/jakemcdermott-expand-nav
Start with navigation expanded

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-11 20:16:02 +00:00
softwarefactory-project-zuul[bot]
9d4bad559f Merge pull request #8102 from jakemcdermott/remove-dead-projects-code
Remove dead projects code

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-11 20:09:25 +00:00
softwarefactory-project-zuul[bot]
1e9fb6b640 Merge pull request #8133 from fosterseth/update_task_manager_system_docs
Update task manager docs

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-11 18:50:10 +00:00
mabashian
ad1c4b1586 Add unique ID to cred field external plugin button(s) 2020-09-11 14:17:35 -04:00
softwarefactory-project-zuul[bot]
412a294461 Merge pull request #7940 from mabashian/6616-workflow-results-sockets
Update job status and workflow node job status based on websocket events

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-11 17:31:47 +00:00
Seth Foster
3606b4e334 these rules no longer apply as of PRs 5519 and 5489 2020-09-11 12:59:18 -04:00
softwarefactory-project-zuul[bot]
0c5aaa2872 Merge pull request #8132 from wenottingham/halfway-there
Make ansible venv psutil match awx venv version

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-11 16:52:23 +00:00
Bill Nottingham
f1c59477c0 Make ansible venv psutil match awx venv version 2020-09-11 12:02:00 -04:00
softwarefactory-project-zuul[bot]
0a871c6107 Merge pull request #8119 from soomsoom/unarchive-rpm-pacakges
Adding unzip dnf package

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-11 15:57:38 +00:00
softwarefactory-project-zuul[bot]
61c4c5292c Merge pull request #8125 from jakemcdermott/fix-api-urls
Fix malformed urls

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-11 15:53:39 +00:00
softwarefactory-project-zuul[bot]
88c691fd6e Merge pull request #7993 from mabashian/7364-jobs-list-cancel
Adds cancel button to jobs list

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-11 15:07:30 +00:00
mabashian
68426daaff Fix residual error from merge conflict 2020-09-11 10:50:27 -04:00
mabashian
d654af77cf Moves cred plugin test button down into wizard footer 2020-09-11 10:50:27 -04:00
mabashian
5cfca7896f Adds proptypes to CredentialPluginTestAlert component 2020-09-11 10:50:27 -04:00
mabashian
9f8691dbea Add the credential id and metadata from the form to the dependency array of useCallback when testing cred plugin configuration. This allows us to remove the variables passed in to the request. 2020-09-11 10:50:27 -04:00
mabashian
62054bbfc8 Pulls CredentialPlugins out of CredentialFormFields and into the root of the shared dir 2020-09-11 10:50:27 -04:00
mabashian
aed96de195 Fix merge conflict 2020-09-11 10:50:27 -04:00
mabashian
67f46b4d7e Hook up Test button on Metadata step in credential plugin wizard 2020-09-11 10:50:27 -04:00
mabashian
8fab4559b9 Add data-job-status attr to all StatusIcons so that automated tests can determine whether or not a status has been updated via websockets. 2020-09-11 09:27:44 -04:00
mabashian
45ca9976f3 Fix merge conflict error 2020-09-11 09:17:42 -04:00
mabashian
5b56bda0bb Fix tests after changing node data structure 2020-09-11 09:17:42 -04:00
mabashian
c318a17590 Refresh nodes after workflow has finished running so that we can display all job info for relevant nodes. 2020-09-11 09:17:42 -04:00
mabashian
e28c9bb3c4 Remove unnecessary constant variable 2020-09-11 09:17:42 -04:00
mabashian
c209c98e3f Update job for job detail/workflow details based on websockets. Re-fetch job after job finishes running to display all available info. 2020-09-11 09:17:42 -04:00
mabashian
af77116f1e Convert Job.jsx to functional component in preparation for socket hook usage 2020-09-11 09:17:42 -04:00
mabashian
328e503f5b Update workflow node job status based on websocket messages 2020-09-11 09:17:42 -04:00
mabashian
5d4ef86db7 Rename inv/inv source ws functions 2020-09-11 09:17:42 -04:00
mabashian
3e99e94b8c Redirect user to visualizer page after successful workflow creation 2020-09-11 09:17:42 -04:00
Bill Nottingham
13802fcf2b Don't return error messages for license errors
Just log the exception and return None.
2020-09-10 21:19:07 -04:00
Jake McDermott
b2ad75a1b7 Fix malformed urls 2020-09-10 18:31:49 -04:00
mabashian
130a43f5c4 Simplify kebab modal open logic 2020-09-10 15:32:30 -04:00
mabashian
0fc6affe85 Refactor kebab modal tracking logic in delete/cancel buttons 2020-09-10 15:32:29 -04:00
mabashian
c8a07309ee Fix typo 2020-09-10 15:32:29 -04:00
mabashian
2b60759edc Fix bug where delete/cancel buttons in kebab would not actually make delete/cancel requests 2020-09-10 15:32:29 -04:00
mabashian
225f57fefd Remove use of i18n.plural in favor of low level i18n._. 2020-09-10 15:32:29 -04:00
mabashian
bae10718d5 Remove RelatedAPI model in favor of JobsAPI. Adds cancel method to JobsAPI and uses that on the jobs list. 2020-09-10 15:32:29 -04:00
mabashian
f27b541396 Adds cancel button to jobs list toolbar 2020-09-10 15:32:29 -04:00
mabashian
6889128571 Peel axios instantiation out into it's own file so that it can be used in the RelatedAPI model 2020-09-10 15:32:29 -04:00
softwarefactory-project-zuul[bot]
4b51c71220 Merge pull request #8109 from AlanCoding/hack_null_org
Hack to delete orphaned organizations, consolidate get_one methods

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-10 18:15:45 +00:00
Jake McDermott
59ecefb1c5 Start with navigation expanded 2020-09-10 13:48:32 -04:00
Jake McDermott
c3f9993e18 Remove dead projects code 2020-09-10 13:28:00 -04:00
softwarefactory-project-zuul[bot]
328b270c9f Merge pull request #8121 from ryanpetrello/galaxy-cred-collection
address a few follow-up issues for Org -> Galaxy Credentials support

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-10 15:58:27 +00:00
Ryan Petrello
af238be377 address a few follow-up issues for Org -> Galaxy Credentials support
- add support for managing galaxy creds in the tower organization module
- fix a minor serializer bug
2020-09-10 11:00:21 -04:00
softwarefactory-project-zuul[bot]
4bb851ca66 Merge pull request #8118 from mjeffin/postres-volume-typo
Update docker-compose.yml.j2

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-10 14:39:43 +00:00
Alan Rominger
2e1f5cebb7 Further refine error message and update integration tests
Fix test with spaces

pep8 failure

More test tweaks

Even more test fixes
2020-09-10 09:49:27 -04:00
Alan Rominger
a73323f3d6 Hack to delete orphaned organizations, consolidate get_one methods
minor test update

Updating the message if more than one object is found

Update test to new message
2020-09-10 09:00:50 -04:00
soomsoom
014a38682d Adding unzip dnf package
Adding unzip DNF package to resolve an issue with the unarchive module when run locally
2020-09-10 06:26:07 -04:00
mjeffin
38fd652f89 Update docker-compose.yml.j2
Add quotes around volume value for posgres data. I installed via docker without changing any values and the UI was stuck in upgrading for long time. Browsed around and figured out that issue was due to postgres volume as a query was getting error. Inspected the template and found that there was no quotes around volume, unlike volumes for others. 
I added the quotes and docker compose was working
2020-09-10 13:53:52 +05:30
softwarefactory-project-zuul[bot]
ff7c2e9180 Merge pull request #8111 from ryanpetrello/bye-bye-boto
remove boto as an awx dependency

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-10 01:39:00 +00:00
softwarefactory-project-zuul[bot]
e39622d42e Merge pull request #8058 from sean-m-sullivan/workflow_label
Workflow label

Reviewed-by: Alan Rominger <arominge@redhat.com>
             https://github.com/AlanCoding
2020-09-10 01:21:06 +00:00
Bill Nottingham
05ad85e7a6 Remove the model for the now unused TowerAnalyticsState. 2020-09-09 20:18:04 -04:00
Bill Nottingham
a604ecffb8 Adjust query_info to set the collection time based on what's passed. 2020-09-09 20:05:48 -04:00
Bill Nottingham
09f7d70428 Use isoformat() rather than strftime
Reformat SQL in unit tests because sqlite.
2020-09-09 20:05:32 -04:00
Bill Nottingham
d4ba62695f Put awx analytics logs also in the task system logger
Errors/warnings when gathering analytics are about 50/50 split between
the gathering code in analytics and the task code that calls it, so
they should be in the same place for debugging sanity.
2020-09-09 17:42:40 -04:00
Bill Nottingham
c753324872 Move back to less frequent collections, and split large event tables
This should ensure we stay under 100MB at all times.
2020-09-09 17:42:40 -04:00
Bill Nottingham
9f67b6742c Fail more gracefully if analytics.ship() is called with a bad path,
or it's deleted out from under us.
2020-09-09 17:42:40 -04:00
Bill Nottingham
1a15f18be3 Stop using the TowerAnalyticsState solo model
This is now tracked in the AUTOMATION_ANALYTICS_LAST_GATHER setting.
2020-09-09 17:42:40 -04:00
Bill Nottingham
40309e6f70 Ensure we do not send large bundles, or empty bundles
Collect expensive collectors separately, and in a loop
where we make smaller intermediate dumps.

Don't return a table dump if there are no records, and
don't put that CSV in the manifest.

Fix up unit tests.
2020-09-09 17:42:40 -04:00
Bill Nottingham
1c4b06fe1e Refactor analytics collectors.
- Only have one registration class
- Add description fields
- Add automation collector information to /api/v2/config
2020-09-09 17:10:14 -04:00
softwarefactory-project-zuul[bot]
dff7667532 Merge pull request #7905 from AlexSCorey/6603-AdHocCommands
Add Ad Hoc Commands

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-09 20:21:41 +00:00
Daniel Sami
da58db7431 grammar fix 2020-09-09 15:42:02 -04:00
Alex Corey
3402e5db35 updates tooltip component, fixes formik configuration on ad hoc qizard 2020-09-09 15:20:18 -04:00
Daniel Sami
fe115fdd16 dropped translation tag 2020-09-09 14:39:54 -04:00
Ryan Petrello
a817708d70 remove boto as an awx dependency
see: https://github.com/ansible/awx/issues/2115
2020-09-09 14:33:33 -04:00
Alex Corey
678dcad437 updates tooltip component, fixes formik configuration on ad hoc qizard 2020-09-09 12:46:19 -04:00
Alex Corey
0e3fbb74d4 updates keys 2020-09-09 12:46:19 -04:00
Alex Corey
94469cc8c0 Adds Proptypes and updates tooltips to make them more translatable 2020-09-09 12:46:19 -04:00
Alex Corey
e6ae171f4b Adds Ad Hoc Commands Wizard 2020-09-09 12:46:19 -04:00
softwarefactory-project-zuul[bot]
caa7b43fe0 Merge pull request #7817 from ryanpetrello/galaxy-credentials
Support Organization-scoped Galaxy installs

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-09 16:17:18 +00:00
mabashian
19886f7ec3 Hide edit button on workflow node details view for users that don't have the ability to edit the workflow 2020-09-09 09:44:09 -04:00
mabashian
945dfbb648 Fixes some rbac issues in the workflow toolbar and start screen. Add/edit-related buttons should be hidden for users that cannot edit the workflow. 2020-09-09 09:07:46 -04:00
Sean Sullivan
470b7aaeea Merge pull request #10 from ansible/devel
Rebase from devel
2020-09-09 07:49:37 -05:00
Keith Grant
6af427d4e1 update test snapshot 2020-09-08 14:45:20 -07:00
softwarefactory-project-zuul[bot]
a3e08a3d09 Merge pull request #8072 from john-westcott-iv/get_one_fix
Modify get_one method to allow IDs in addition to names

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-08 21:30:59 +00:00
Keith Grant
e0e48bf922 add custom messages to Notification Detail 2020-09-08 14:04:38 -07:00
Keith Grant
7042542e6a add ArrayDetail 2020-09-08 14:00:57 -07:00
softwarefactory-project-zuul[bot]
3f63800f58 Merge pull request #7967 from keithjgrant/7876-notifications-form
Notifications form

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-08 20:56:21 +00:00
softwarefactory-project-zuul[bot]
800cf30d92 Merge pull request #8089 from rooftopcellist/update_analytics_job_test
Provide a distinct column name for inventory_name in unifiedjob analy…

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-08 20:04:31 +00:00
John Westcott IV
570251dc3d Modifying get_item_name to handle a None object 2020-09-08 15:28:57 -04:00
John Westcott IV
faa33efdd2 Fixing registered name 2020-09-08 15:28:37 -04:00
John Westcott IV
09b8f82bbb Fixing test issue and 'modornizing' test 2020-09-08 15:28:21 -04:00
sean-m-sullivan
cfdfa911e8 update lint 2020-09-08 14:00:12 -05:00
softwarefactory-project-zuul[bot]
cd8c74e28f Merge pull request #8094 from ryanpetrello/upgrade-django-libs
Update Django and channels_redis

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-08 17:46:35 +00:00
John Westcott IV
4c0e288fee Touching up to missing sport of get_one returning multiple params 2020-09-08 13:38:44 -04:00
Keith Grant
13e6757666 add ids to CodeMirror FormGroup containers 2020-09-08 10:17:18 -07:00
softwarefactory-project-zuul[bot]
90c3bfc6ae Merge pull request #8074 from fosterseth/fix-7655_task_manager_times_out
Prevent task manager timeout by limiting number of jobs to start

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-08 16:42:20 +00:00
Seth Foster
e09274e533 PR #8074 - limit how many jobs the task manager can start on a given run 2020-09-08 12:16:06 -04:00
John Westcott IV
c2cfaec7d1 Fixing name -> username 2020-09-08 11:52:53 -04:00
John Westcott IV
d6f35a71d7 Adding allow_unknown option for get_item_name 2020-09-08 11:51:47 -04:00
John Westcott IV
6467d34445 Touching up tower_inventory_source after rebase 2020-09-08 11:36:33 -04:00
Christian M. Adams
0681444294 Provide a distinct column name for inventory_name in unifiedjob analytics csv 2020-09-08 11:14:24 -04:00
John Westcott IV
0a8db586d1 Changing how get_one returns 2020-09-08 11:10:18 -04:00
John Westcott IV
106157c600 get_one now also returns the name field, and modifying modules for get_one and added in some IDs in a handful of unit tests 2020-09-08 11:06:01 -04:00
John Westcott IV
4c4d6dad49 Adding get_item_name and making static methods 2020-09-08 11:03:10 -04:00
John Westcott IV
24ec129235 Modifying credential for new get_one 2020-09-08 11:03:10 -04:00
John Westcott IV
5042ad3a2b Updating user module for new get_one 2020-09-08 11:03:10 -04:00
John Westcott IV
51959b29de Adding name_or_id to get_one to make module more uniform 2020-09-08 11:03:10 -04:00
Ryan Petrello
c862b3e5a2 Revert "work around a memory leak in channels_redis"
This reverts commit e25da217e8.
2020-09-08 10:40:47 -04:00
Ryan Petrello
f81560b12c update Django and channels_redis
see: https://github.com/ansible/tower/issues/4439
also, addresses CVE-2020-24583 and CVE-2020-24584
2020-09-08 10:39:26 -04:00
softwarefactory-project-zuul[bot]
68265ea9b5 Merge pull request #8092 from nixocio/ui_issue_8091
List jobs for container groups

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-09-08 14:33:57 +00:00
softwarefactory-project-zuul[bot]
6e6aa1fdab Merge pull request #8033 from beeankha/update_inv_src_module
Add New tower_inventory_source_update Module

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-08 14:04:32 +00:00
Benoit Bayszczak
08c9219f48 rename 'approle_auth_path' to 'default_auth_path' & fix kwargs.get 2020-09-08 10:39:12 +02:00
beeankha
c7114b2571 Add specific lookup data to error message 2020-09-07 11:43:44 -04:00
softwarefactory-project-zuul[bot]
127ca4bc54 Merge pull request #7975 from AlexSCorey/7973-DisableTemplateFormFields
Disables template and workflow template fields.

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-06 21:26:23 +00:00
Alex Corey
b51f013880 disables prompt on launch checkbox 2020-09-05 08:32:15 -04:00
Alex Corey
fc4060778b Disables template and workflow template fields for users that do not have permissions for those fields. 2020-09-05 08:32:15 -04:00
Keith Grant
40d3e4ee8b handle error string in FormSubmitError 2020-09-04 16:24:09 -07:00
beeankha
a0b8f6a25d Make org an optional parameter for both inv source and inv source update modules 2020-09-04 18:56:58 -04:00
Keith Grant
9711c33675 fix multiple notification form bugs 2020-09-04 15:50:04 -07:00
Keith Grant
b119bc475f convert http headers field to string for codemirror 2020-09-04 15:50:04 -07:00
Keith Grant
055abd57cd fix new test from rebase 2020-09-04 15:50:04 -07:00
Keith Grant
95c4b6c922 trying to force tests to re-run 2020-09-04 15:50:04 -07:00
Keith Grant
7ab9d899e4 mark text for translation 2020-09-04 15:49:11 -07:00
Keith Grant
c700d07a0a fix lint error 2020-09-04 15:49:11 -07:00
Keith Grant
4a616d9f81 ensure notification template re-loads after saving 2020-09-04 15:49:11 -07:00
mabashian
e830da97f3 Fix broken credential form tests after id change 2020-09-04 15:49:11 -07:00
Keith Grant
43ac5a0574 add some notification form tests; notification add screen 2020-09-04 15:49:11 -07:00
Keith Grant
9bb834a422 create ArrayTextField component 2020-09-04 15:49:11 -07:00
Keith Grant
458d29a579 only submit customized notification messages if changed 2020-09-04 15:49:11 -07:00
Keith Grant
19fc0d9a96 reset notification messages to defaults when switching to new type 2020-09-04 15:49:11 -07:00
Keith Grant
ba95775ded add custom notification messages subform 2020-09-04 15:49:11 -07:00
Keith Grant
bb12e0a3a9 fix initial values for notification type fields 2020-09-04 15:49:10 -07:00
Keith Grant
09178dd5f2 flush out notification form and type subform 2020-09-04 15:49:10 -07:00
nixocio
d4b2e1998e List jobs for container groups
Add list of jobs related to container groups.

See: https://github.com/ansible/awx/issues/8091
2020-09-04 16:21:32 -04:00
softwarefactory-project-zuul[bot]
9c90804300 Merge pull request #7974 from AlexSCorey/6561-WFJTDeetsNotLoad
Adds fix to load template details 

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-04 20:16:30 +00:00
softwarefactory-project-zuul[bot]
95b43c0087 Merge pull request #8075 from ryanpetrello/redis-capacity-check
if redis is unreachable, set instance capacity to zero

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-04 20:06:21 +00:00
softwarefactory-project-zuul[bot]
3f8cd21233 Merge pull request #8084 from ryanpetrello/bye-fact-scanning
remove old fact scanning plugins

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-04 19:13:56 +00:00
softwarefactory-project-zuul[bot]
e6cd27a858 Merge pull request #7960 from mabashian/6113-6703-cred-file-upload
Support file upload/drag and drop on credential mutliline fields

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-04 17:27:43 +00:00
beeankha
4133ec974b Follow same pattern as project update module, add task to integration test 2020-09-04 13:05:34 -04:00
softwarefactory-project-zuul[bot]
70f1bffe42 Merge pull request #8069 from ryanpetrello/saml-autopop
add the ability to prevent SAML auto-population behavior

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-04 16:01:23 +00:00
mabashian
77c211dabe Adds id's to credential form buttons 2020-09-04 11:22:34 -04:00
Ryan Petrello
013b411a0a remove old fact scanning plugins 2020-09-04 10:51:34 -04:00
beeankha
7764f1c1a5 Fix inv source org lookup, adjust unit tests (since org is now required for inv source module), update README, edit typos in test-related README 2020-09-04 10:19:56 -04:00
beeankha
b78dea3e4b Add wait ability to the module 2020-09-04 10:19:56 -04:00
beeankha
1ce5d7d539 Add ability to look up inventory sources by org name/ID 2020-09-04 10:19:56 -04:00
beeankha
65e0ed8c77 Fix linter error 2020-09-04 10:19:56 -04:00
beeankha
72dbd10c2a Initial commit for new inventory sync module 2020-09-04 10:19:56 -04:00
mabashian
e5f9ed827b Undo commenting out of strictmode 2020-09-04 09:20:09 -04:00
mabashian
2d2108b1de Support file upload/drag and drop on credential mutliline fields 2020-09-04 09:20:09 -04:00
Ryan Petrello
b01d204137 if redis is unreachable, set instance capacity to zero 2020-09-03 15:11:53 -04:00
Ryan Petrello
a6d26d7dab add the ability to prevent SAML auto-population behavior 2020-09-03 11:21:14 -04:00
nixocio
adffa29346 Add/Edit Container Groups
Add/Edit container groups.

See: https://github.com/ansible/awx/issues/7955
2020-09-03 10:13:24 -04:00
softwarefactory-project-zuul[bot]
cce66e366f Merge pull request #8065 from e-desouza/patch-1
Update from pip to pip3

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-03 12:35:07 +00:00
Elton de Souza
371276b2e1 Update from pip to pip3 2020-09-02 21:11:46 -04:00
softwarefactory-project-zuul[bot]
77b1afe6fd Merge pull request #7873 from sean-m-sullivan/project_update
Project update

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-02 15:39:23 +00:00
sean-m-sullivan
5478c5f2fb linting 2020-09-02 08:30:09 -05:00
sean-m-sullivan
e2bf3a0287 update to use isdigit and updated tests 2020-09-02 07:19:11 -05:00
sean-m-sullivan
a17eedd9fe update to not use organizations 2020-09-01 23:08:15 -05:00
sean-m-sullivan
d05c7d6cc5 update to use organizations 2020-09-01 22:54:08 -05:00
sean-m-sullivan
6200467629 add label to workflow templates 2020-09-01 18:58:39 -05:00
Sean Sullivan
dbd8431b14 Merge pull request #6 from ansible/devel
Rebase to devel
2020-09-01 18:50:03 -05:00
softwarefactory-project-zuul[bot]
b11a5c1190 Merge pull request #8057 from ryanpetrello/proj-archive-py2
update the project archive sync support for py2 compatability

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-01 23:40:58 +00:00
sean-m-sullivan
532447ed40 update to tower module 2020-09-01 16:43:58 -05:00
sean-m-sullivan
300a4510ac update completness 2020-09-01 15:59:53 -05:00
sean-m-sullivan
d269a6d233 update 2020-09-01 15:59:04 -05:00
softwarefactory-project-zuul[bot]
967e35fec9 Merge pull request #8056 from ryanpetrello/dead-code-ansible-path
remove some dead code

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-01 20:33:43 +00:00
softwarefactory-project-zuul[bot]
fcd1169093 Merge pull request #8043 from john-westcott-iv/instance_groups_module
Adding tower_instance_group module

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-01 20:26:44 +00:00
sean-m-sullivan
d95d8121f9 added to no endpoints for module 2020-09-01 15:22:14 -05:00
sean-m-sullivan
5d4413041e update to wait 2020-09-01 14:59:16 -05:00
Ryan Petrello
798f6371af update the project archive sync support for py2 compatability
playbook runs in AWX are still supported in python2, so this adds
support for archive-based project syncs in py2
2020-09-01 15:58:43 -04:00
Sean Sullivan
8e317cabc0 Merge pull request #5 from ansible/devel
Rebase from devel
2020-09-01 14:42:23 -05:00
Ryan Petrello
3edaa6bc14 remove some dead code 2020-09-01 15:26:38 -04:00
softwarefactory-project-zuul[bot]
30616c1fce Merge pull request #8022 from sean-m-sullivan/wait_function
Add wait function and update collection modules

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
             https://github.com/beeankha
2020-09-01 19:13:12 +00:00
softwarefactory-project-zuul[bot]
57eed5863a Merge pull request #8054 from ryanpetrello/postgres-upgrade-note
add a changelog note about upgrade issues from 13.0 -> 14.0

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-01 19:10:55 +00:00
softwarefactory-project-zuul[bot]
1c55d10d81 Merge pull request #7965 from rebeccahhh/devel
adding in inventory to unified job query for analytics

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-01 18:27:27 +00:00
Ryan Petrello
f4af74dabe renumber the Galaxy credential migration after rebasing 2020-09-01 13:47:26 -04:00
Elyézer Rezende
ad85b176f4 Update awxkit to manage Org galaxy credentials
Add the new credential type to the Credential page object and helper
methods to manage the galaxy credentials for the Organization page
object.
2020-09-01 13:46:47 -04:00
Ryan Petrello
4046b18eff properly handle Galaxy credentials if a Project is orphaned 2020-09-01 13:45:03 -04:00
Ryan Petrello
a869d7da35 create the Galaxy credential for new installs in the preload script
doing this in the migration *before* any Organizations actually exist
is stirring up RBAC dragons that I don't have time to fight

this commit meanst that *new* installs will pre-create the default
Galaxy (public) credential in create_preload_data, while
*upgraded/migrations* installs will do so via the migration
2020-09-01 13:45:03 -04:00
mabashian
895010c675 Pre-populate organization galaxy credential field with the default galaxy credential 2020-09-01 13:45:03 -04:00
Ryan Petrello
a30ca9c19c don't run ansible-galaxy installs if there are no Galaxy credentials 2020-09-01 13:45:03 -04:00
Ryan Petrello
30da93a64e update the help text for Organization galaxy credentials 2020-09-01 13:45:03 -04:00
mabashian
458807c0c7 Add a Galaxy Credential multi-select field to the Organizations form 2020-09-01 13:45:03 -04:00
Ryan Petrello
011822b1f0 make a global "managed by AWX/Tower" Credential to represent Galaxy 2020-09-01 13:45:03 -04:00
Ryan Petrello
e5552b547b properly migrate settings.FALLBACK_GALAXY_SERVERS 2020-09-01 13:45:02 -04:00
Ryan Petrello
1b4dd7c783 enforce Organization ownership of Galaxy credentials 2020-09-01 13:45:02 -04:00
Ryan Petrello
25a9a9c3ba remove redaction exclusions for Galaxy URLs (basic auth support is gone) 2020-09-01 13:45:02 -04:00
Ryan Petrello
130e279012 add a data migration for Galaxy credentials
see: https://github.com/ansible/awx/issues/7813
2020-09-01 13:45:02 -04:00
Ryan Petrello
b8e0d087e5 add model support, an API, and a migration for Org -> Galaxy credentials
see: https://github.com/ansible/awx/issues/7813
2020-09-01 13:44:59 -04:00
softwarefactory-project-zuul[bot]
8996d0a464 Merge pull request #7763 from chrismeyersfsu/feature-inv_plugin_conf
Feature inv plugin conf

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-01 17:44:22 +00:00
Ryan Petrello
40ac719d6d add a changelog note about upgrade issues from 13.0 -> 14.0 2020-09-01 13:32:09 -04:00
John Westcott IV
5f29b4bc18 Fixing typo 2020-09-01 13:17:24 -04:00
Ryan Petrello
059999c7c3 update the inventory source module to respect new fields 2020-09-01 13:15:07 -04:00
Chris Meyers
924273f589 more get_ansible_version test failure fixes 2020-09-01 12:50:59 -04:00
Chris Meyers
72fc314da1 flake8 fix 2020-09-01 12:50:59 -04:00
Chris Meyers
043a7f8599 more get_ansible_version removal 2020-09-01 12:50:59 -04:00
Chris Meyers
a6712cfd60 bump inv plugin migration to avoid conflict 2020-09-01 12:50:59 -04:00
Alan Rominger
99aff93930 Get rid of ansible version checking 2020-09-01 12:50:59 -04:00
Chris Meyers
03ad1aa141 remove backwords migraiton support for inv plugins
* Do not write out inventory source_vars to a file on disk as they _may_
contain sensitive information. This also removes support for backwards
migrations. This is fine, backwards migration is really only useful
during development.
2020-09-01 12:50:59 -04:00
Jake McDermott
dcf5917a4e Check that host_filter is regexp 2020-09-01 12:50:58 -04:00
Jake McDermott
f04aff81c4 Add details to inv source field help text 2020-09-01 12:50:58 -04:00
Chris Meyers
a9cdf07690 push global invsource fields onto invsource obj 2020-09-01 12:50:58 -04:00
Chris Meyers
d518891520 inventory plugin inventory parameter take precedence over env vars 2020-09-01 12:50:58 -04:00
Chris Meyers
48fb1e973c overwrite plugin: at runtime
* Before, we were re-writing `plugin:` when users updated the
InventorySource via the API. Now, we just override at run-time. This
makes for a more sane API interaction
2020-09-01 12:50:58 -04:00
Chris Meyers
c7794fc3e4 fix missed import 2020-09-01 12:50:58 -04:00
Jake McDermott
2fdeba47a5 Add new common inventory source fields 2020-09-01 12:50:58 -04:00
Chris Meyers
12cf607e8a simplify InventorySourceOption inheritance hack 2020-09-01 12:50:58 -04:00
Chris Meyers
7d4493e109 rename inventory migration 2020-09-01 12:50:57 -04:00
Jake McDermott
b253540047 Add new common inventory source fields 2020-09-01 12:50:57 -04:00
Jake McDermott
42e70bc852 Delete inventory source fields 2020-09-01 12:50:57 -04:00
Jake McDermott
dce946e93f Delete inventory source fields 2020-09-01 12:50:57 -04:00
Chris Meyers
2eec1317bd safer migrations 2020-09-01 12:50:57 -04:00
Chris Meyers
b7efad5640 do not enforce plugin: for source=scm
* InventorySource w/ source type scm point to an inventory file via
source_file. source_vars are ignored.
2020-09-01 12:50:57 -04:00
Chris Meyers
35d264d7f8 forgot to add migration helper
* move models/inventory.py plugin injector logic to a place frozen in
time useable by the migration code.
2020-09-01 12:50:57 -04:00
Chris Meyers
34adbe6028 fix tests for new inv plugin behavior
* Enforce plugin:
2020-09-01 12:50:57 -04:00
Chris Meyers
a8a47f314e remove source_regions 2020-09-01 12:50:56 -04:00
Chris Meyers
f32716a0f1 remove instance_filter 2020-09-01 12:50:56 -04:00
Chris Meyers
7278e7c025 remove group_by from inventory source
* Does not remove group_by testing
2020-09-01 12:50:56 -04:00
Chris Meyers
e11040f421 migrate to new style inv plugin 2020-09-01 12:50:53 -04:00
sean-m-sullivan
9f3635be07 update test to timeout message change 2020-09-01 10:45:41 -05:00
sean-m-sullivan
50637807fc fixed typo 2020-09-01 10:38:15 -05:00
John Westcott IV
d01f2d6caf Converting policy_instance_list from dict to list 2020-09-01 11:02:39 -04:00
softwarefactory-project-zuul[bot]
2fa8b7e594 Merge pull request #8007 from ryanpetrello/defer-artifacts
defer loading Job.artifacts and .extra_vars on host views to improve performance

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-01 14:08:00 +00:00
John Westcott IV
36ab0dd03e Fixing white spaces 2020-09-01 09:24:36 -04:00
softwarefactory-project-zuul[bot]
671c571628 Merge pull request #8047 from AlanCoding/less_mounting
Remove more special access to folders outside job private_data_dir

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-09-01 02:42:15 +00:00
Alan Rominger
0b371b4340 Copy library folder to job private data dir
Remove inventory scripts show because they no longer exist

Remove reference to non-existent callback directory

Remove more references to removed path
2020-08-31 22:14:59 -04:00
John Westcott IV
72bdd17518 Fixing regression 2020-08-31 16:56:42 -04:00
John Westcott IV
574c3b65b2 Converting from string to array 2020-08-31 16:56:42 -04:00
John Westcott IV
5a8bcd357b Fixing linting issues 2020-08-31 16:56:42 -04:00
John Westcott IV
1bd8f4ad3e Removing tower_instance_group from completness 2020-08-31 16:56:42 -04:00
John Westcott IV
2369bcb25c Removing forward feature needed for testing locally 2020-08-31 16:56:42 -04:00
John Westcott IV
9e29dd08fb Adding tower_instance_group module 2020-08-31 16:56:42 -04:00
sean-m-sullivan
cd45cfec30 updated doc and pep8 2020-08-31 15:53:54 -05:00
sean-m-sullivan
d9d454d435 Merge branch 'wait_function' of github.com:sean-m-sullivan/awx into wait_function 2020-08-31 15:24:40 -05:00
sean-m-sullivan
0bc927820b updated legacy messages 2020-08-31 15:24:32 -05:00
softwarefactory-project-zuul[bot]
e1095a0a94 Merge pull request #8046 from nixocio/ui_fix_date_projects
Update date format for project list item

Reviewed-by: John Hill <johill@redhat.com>
             https://github.com/unlikelyzero
2020-08-31 18:46:51 +00:00
Sean Sullivan
d0ab307787 Merge pull request #4 from ansible/devel
Rebase from Dev
2020-08-31 13:45:49 -05:00
softwarefactory-project-zuul[bot]
6c9e417eb9 Merge pull request #7730 from mabashian/7339-test-button
Adds support for a Test button on the credential form when the credential type is 'external'

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-31 18:43:00 +00:00
softwarefactory-project-zuul[bot]
2837eb7027 Merge pull request #8049 from john-westcott-iv/fix_notification_tests
Cleaning up tower_notification references

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-31 18:19:12 +00:00
softwarefactory-project-zuul[bot]
ad28a36cdf Merge pull request #8048 from AlanCoding/notification_name
correct name of tower_notification redirect

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-31 16:20:37 +00:00
John Westcott IV
ff4ed64978 Cleaning up tower_notification references 2020-08-31 11:57:01 -04:00
Alan Rominger
b84343d292 correct name of tower_notification redirect 2020-08-31 10:18:08 -04:00
nixocio
970ecde0ea Update date format for project list item
Update date format for project list item.

See: https://github.com/ansible/awx/issues/7694
2020-08-30 20:58:58 -04:00
softwarefactory-project-zuul[bot]
ddad5095a4 Merge pull request #8024 from velzend/regsiter_typo
typo: regsiter -> register

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-30 19:53:33 +00:00
softwarefactory-project-zuul[bot]
730cabe597 Merge pull request #8038 from john-westcott-iv/check_token_pre_del
Adding check that we are authenticated and also have a token

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-30 17:54:13 +00:00
softwarefactory-project-zuul[bot]
07ebf677de Merge pull request #8039 from john-westcott-iv/transaction_check
Adding transaction to mock requests

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-30 17:54:07 +00:00
softwarefactory-project-zuul[bot]
c7f4c4bdc1 Merge pull request #8029 from AlanCoding/project_cwd
Run project updates from a copy of the playbook vendoring directory

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-29 03:48:01 +00:00
mabashian
9d511a4c04 Fix id on credential select fields 2020-08-28 17:02:25 -04:00
softwarefactory-project-zuul[bot]
bd4b009bea Merge pull request #8035 from nixocio/ui_update_instance_groups
Update instance groups

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-28 20:37:34 +00:00
mabashian
ae4f1a15d3 Add ID's to the buttons in the external test modal for cred form 2020-08-28 15:43:44 -04:00
mabashian
e93aa34864 Adds support for a Test button on the credential form when the credential type is 'external' 2020-08-28 15:43:44 -04:00
softwarefactory-project-zuul[bot]
bebd882688 Merge pull request #8040 from rooftopcellist/be_more_accepting
Accept all responses <300 from Insights API

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-28 19:43:27 +00:00
Christian M. Adams
4ea648307e Accept all responses <300 from Insights API 2020-08-28 12:45:50 -04:00
John Westcott IV
feb9bcff4d Adding transaction to mock requests 2020-08-28 12:43:33 -04:00
softwarefactory-project-zuul[bot]
40603c213a Merge pull request #8037 from bbayszczak/fix_typo_comment_hashivault
[credential_plugin/hashivault] fix typo

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-28 16:40:46 +00:00
Benoit Bayszczak
e8b54abec4 [credential_plugin/hashivault] edit tests 2020-08-28 17:39:37 +02:00
Benoit Bayszczak
878b754d9f [credential_plugin/hashivault] fix typo 2020-08-28 17:33:19 +02:00
Benoit Bayszczak
16fdf0e28f [credential_plugin/hashivault] add approle_auth_path in inputs 2020-08-28 17:22:07 +02:00
nixocio
21330a54cb Update instance groups
* Simplify criteria to instance group to be considered unavailable
* Round values for used capacity

See: https://github.com/ansible/awx/issues/7467
2020-08-28 11:07:03 -04:00
John Westcott IV
51f4aa2b48 Adding check that we are authenticated and also have a token 2020-08-28 11:04:15 -04:00
softwarefactory-project-zuul[bot]
fe5fb0c523 Merge pull request #7997 from mabashian/7480-webhook-disable
Fixes bug where users were unable to turn webhooks off when editing templates

Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
             https://github.com/tiagodread
2020-08-28 14:27:56 +00:00
sean-m-sullivan
b3ec080e08 updated output 2020-08-28 08:25:21 -05:00
sean-m-sullivan
fd77a8aca5 updated output 2020-08-28 08:22:44 -05:00
sean-m-sullivan
7bd3f9d63c updated to error if finished not in result 2020-08-28 07:37:29 -05:00
sean-m-sullivan
d971375907 updated to error if finished not in result 2020-08-28 07:35:13 -05:00
sean-m-sullivan
007b0d841e updated parameters and errors 2020-08-28 07:19:39 -05:00
softwarefactory-project-zuul[bot]
aa637d515a Merge pull request #7929 from nixocio/ui_associate_instances
Associate instances to instance groups

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-27 17:49:00 +00:00
softwarefactory-project-zuul[bot]
ad3e2cbfcd Merge pull request #8028 from dsesami/8027-workflow-sparkline
Change WFJT details sparkline hyperlink

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-27 16:29:42 +00:00
softwarefactory-project-zuul[bot]
f1ee44b6c2 Merge pull request #8016 from john-westcott-iv/inventory_insights
Adding insights credential to tower_inventory

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-27 16:14:37 +00:00
Daniel Sami
dc7e721968 Change WFJT details sparkline hyperlink 2020-08-27 11:54:38 -04:00
nixocio
632204de83 Associate instances to instance groups
Associate instances to instance groups.

See: https://github.com/ansible/awx/issues/7801
2020-08-27 11:33:45 -04:00
Alan Rominger
e811711a49 Put project playbook in runner project folder 2020-08-27 11:07:10 -04:00
John Westcott IV
64d98a120c Removing debugging end play 2020-08-27 09:47:48 -04:00
Benoit Bayszczak
cf5d1a2d03 restore previous tests as we need to keep backward compatibility
This reverts commit 7c8e5ace52.
2020-08-27 11:06:14 +02:00
tp48cf
5cd12b8088 typo: regsiter -> register 2020-08-27 09:23:41 +02:00
sean-m-sullivan
49e2a3fa5a update documentation 2020-08-26 23:44:31 -05:00
sean-m-sullivan
0c18587851 update to use time function 2020-08-26 23:30:18 -05:00
softwarefactory-project-zuul[bot]
f18d9212cb Merge pull request #7987 from nixocio/ui_add_adv_search
Add advanced search keys for InstanceGroup and CredentialType Lists

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-27 02:55:19 +00:00
softwarefactory-project-zuul[bot]
9b353c70f3 Merge pull request #8019 from mabashian/7663-workflow-viz-button
Adds visualizer button to workflow template rows on templates list

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-27 02:54:03 +00:00
Sean Sullivan
243c2cfe15 Merge pull request #3 from ansible/devel
rebase to devel
2020-08-26 20:53:39 -05:00
beeankha
0f3aefe592 Fix pep8 errors, rebase 2020-08-26 19:51:10 -04:00
John Westcott IV
7afd84dc49 Resolving issue in test_completness 2020-08-26 19:50:04 -04:00
John Westcott IV
1b1a14f220 Fixing linting spacing issue 2020-08-26 19:50:04 -04:00
John Westcott IV
2690fcec31 Adding insights credential to tower_inventory
Fixed a spacing issue in documentation

Enhanced integration test to include a block to ensure cleanup of assets
2020-08-26 19:50:04 -04:00
softwarefactory-project-zuul[bot]
9323156f4c Merge pull request #7983 from beeankha/collections_pylint_fixes
Fix pylint Errors in Collections Modules

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-26 22:31:22 +00:00
mabashian
73d21a01cb Adds visualizer button to workflow template rows on templates list 2020-08-26 17:03:48 -04:00
Rebeccah
9a6f641df0 adding in inventory to unified job query for analytics 2020-08-26 16:32:02 -04:00
beeankha
3ddee3072b Add errors to ignore file, remove noqa directives 2020-08-26 16:09:42 -04:00
softwarefactory-project-zuul[bot]
1514a5ac23 Merge pull request #7963 from john-westcott-iv/tools
Collections Completeness Tests

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-26 19:34:52 +00:00
softwarefactory-project-zuul[bot]
ccb1e0a748 Merge pull request #8008 from mabashian/8002-plurals
Use low level i18n._ instead of i18n.plural for plurals on the schedule form

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-08-26 18:11:04 +00:00
Ryan Petrello
73baf3fcf9 defer loading Job.artifacts on host views to improve performance
see: https://github.com/ansible/awx/issues/8006

this data can be *really* large, and we don't actually need it for the summary fields on this API endpoint
2020-08-26 13:34:15 -04:00
mabashian
c731e4282b Use low level i18n._ instead of i18n.plural for plurals on the schedule form. This fixes a bug where the page would crash on static builds when a frequency was selected. 2020-08-26 13:18:07 -04:00
softwarefactory-project-zuul[bot]
57949078bb Merge pull request #7945 from beeankha/tower_role_id_fix
Get tower_role Module to Accept IDs for Related Objects

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-26 14:21:32 +00:00
John Westcott IV
2b6e4fe353 Permissions change, spell check, pep8, etc 2020-08-26 10:16:37 -04:00
John Westcott IV
b7b304eb84 Changing how we check modules
Options which are not in the API POST and are marked in the module as deprecated are ignored

If an option is not in the API POST but is marked as a list we assume its a relation
2020-08-26 10:16:37 -04:00
John Westcott IV
8f97109ac7 Fixing PY2 compile issues 2020-08-26 10:16:37 -04:00
John Westcott IV
730a9b25ac Fixing pep8 and other issues 2020-08-26 10:16:37 -04:00
John Westcott IV
a36d942f67 Migrating old test_notification test to test_notification_template 2020-08-26 10:16:37 -04:00
John Westcott IV
b1ffbf1e39 Change module from tower_notification to tower_notification_template 2020-08-26 10:16:37 -04:00
John Westcott IV
f8290f0ce3 Fixing flake8 and adding more module OKs 2020-08-26 10:16:37 -04:00
John Westcott IV
41ca20dc99 Changing scm_credential to credential to match API 2020-08-26 10:16:37 -04:00
John Westcott IV
3b6152a380 Changing job_timeout to an aliase of timeout to match the API 2020-08-26 10:16:37 -04:00
John Westcott IV
1ad4c4ab86 Fixing pep8 issues 2020-08-26 10:16:37 -04:00
John Westcott IV
9353e94629 Spell checking 2020-08-26 10:16:37 -04:00
John Westcott IV
85a1233764 Adding read-only endpoint check, fixing typo, adding needs_development check 2020-08-26 10:16:37 -04:00
John Westcott IV
c2cdd8e403 Initial commit of test_completeness 2020-08-26 10:16:37 -04:00
softwarefactory-project-zuul[bot]
96e1920d36 Merge pull request #7988 from nixocio/add_more_styles_delete_button
Update styles to delete button to be secondary 

Reviewed-by: Michael Abashian
             https://github.com/mabashian
2020-08-26 14:02:46 +00:00
tp48cf
d9e09f482d allow skipping provision instance and register queue 2020-08-26 15:56:01 +02:00
sean-m-sullivan
bed3a9ee41 added id lookup 2020-08-26 08:11:51 -05:00
Benoit Bayszczak
7c8e5ace52 fix tests 2020-08-26 11:14:04 +02:00
softwarefactory-project-zuul[bot]
b8a04f05d1 Merge pull request #7992 from AlexSCorey/RemovesColonOnListItem
Removes colon from survey list item

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-26 00:48:50 +00:00
softwarefactory-project-zuul[bot]
2b18eee92a Merge pull request #7969 from nixocio/ui_add_isolate_job_label
Add label to identify isolated instance group JobDetail screen

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-26 00:48:43 +00:00
mabashian
8fac722b10 Fixes bug where users were unable to turn webhooks off when editing job templates/workflow job templates 2020-08-25 16:02:55 -04:00
beeankha
4bc1a128ec Add noqa directive for super calls 2020-08-25 15:49:20 -04:00
beeankha
da732a3941 Add unit test, update lookup method to favor ID over name 2020-08-25 14:57:02 -04:00
Alex Corey
c0a2a69835 removes colon from suvery list item 2020-08-25 13:32:57 -04:00
softwarefactory-project-zuul[bot]
48f00587f8 Merge pull request #7990 from ryanpetrello/build-needs-facts
gather facts for image builds so we can detect arch

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
             https://github.com/rooftopcellist
2020-08-25 16:12:12 +00:00
Benoit Bayszczak
00fc5f6b93 hashivault_kv auth_path moved from metadata to inputs
The auth_path is used with the approle auth method
It's not linked to the secret we are reading but to the auth method,
this parameter has to be moved to inputs
2020-08-25 18:01:09 +02:00
Ryan Petrello
04229ba14b gather facts for image builds so we can detect arch
related: https://github.com/ansible/awx/pull/7607/
2020-08-25 11:36:26 -04:00
softwarefactory-project-zuul[bot]
e8cc4cee52 Merge pull request #7985 from ryanpetrello/release-14.1.0
Bump version to 14.1.0

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
             https://github.com/rooftopcellist
2020-08-25 14:57:57 +00:00
softwarefactory-project-zuul[bot]
5507f264e3 Merge pull request #7919 from marshmalien/7806-smart-inv-detail
Add smart inventory host detail view

Reviewed-by: Daniel Sami
             https://github.com/dsesami
2020-08-25 14:47:04 +00:00
nixocio
6794f331c3 Update styles to delete button to be secondary
Update styles to delete button to be secondary.

See: https://github.com/ansible/awx/issues/7041
Also: https://github.com/ansible/awx/issues/7984
2020-08-25 10:39:28 -04:00
softwarefactory-project-zuul[bot]
3236f50fe7 Merge pull request #7950 from ryanpetrello/fix-channels-memory-leak
work around a memory leak in channels_redis

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-25 14:26:47 +00:00
softwarefactory-project-zuul[bot]
d0e0dbea24 Merge pull request #7986 from kldavis52/api_status_405_error
Api status 405 error message update, address issue#5744

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-25 14:00:24 +00:00
Ryan Petrello
e0acf73ac6 add a changelog note about the channels_redis memory leak 2020-08-25 09:58:04 -04:00
Ryan Petrello
e25da217e8 work around a memory leak in channels_redis
see: https://github.com/django/channels_redis/issues/212
see: https://github.com/django/channels_redis/pull/219/
2020-08-25 09:58:03 -04:00
Ryan Petrello
04188aa2d6 Bump version to 14.1.0 2020-08-25 09:45:05 -04:00
softwarefactory-project-zuul[bot]
35efbb043d Merge pull request #7966 from ryanpetrello/vanishing-instance
improve job reaping for jobs that were started on a missing Instance

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-25 13:36:35 +00:00
Ryan Petrello
64da67fa2e mprove error message when changing an inventory from regular -> smart
see: https://github.com/ansible/awx/issues/5744
Co-Authored-By: kldavis52 <kyle.linnard.davis@gmail.com>
2020-08-25 09:25:54 -04:00
sean-m-sullivan
13f3292af0 updated test 2020-08-25 07:04:27 -05:00
nixocio
de130eb798 Add advanced search keys for InstanceGroup and CredentialType Lists
Add advanced search keys for `InstanceGroup` and `CredentialType` Lists.

See: https://github.com/ansible/awx/pull/7895/files
2020-08-24 21:27:44 -04:00
Marliana Lara
febfb985a4 Add smart inventory host detail view
* Remove host toggle from smart inv host list
2020-08-24 17:19:22 -04:00
beeankha
75a0c0ab1e Prioritize integer names over IDs more effectively 2020-08-24 17:13:22 -04:00
beeankha
54317236f3 Fix pep8 error, remove redundant var assignment 2020-08-24 17:13:22 -04:00
John Westcott IV
0fd618d88b Changing test suite and fixing user issue in tower_api 2020-08-24 17:13:21 -04:00
beeankha
e9d66df77a Initial commit for tower_role name vs id lookup bug fix 2020-08-24 17:13:21 -04:00
beeankha
ef7a74c4a3 Initial commit of pylint fixes 2020-08-24 16:47:16 -04:00
softwarefactory-project-zuul[bot]
5248ac4498 Merge pull request #7921 from mabashian/6172-schedule-detail-vars
Adds extra variables to schedule details

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-24 20:45:32 +00:00
softwarefactory-project-zuul[bot]
1a033653ae Merge pull request #7978 from jakemcdermott/fix-7977
Don't display facts until facts are loaded

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-24 19:33:26 +00:00
softwarefactory-project-zuul[bot]
45f7e4a663 Merge pull request #7911 from AmadeusITGroup/archive_url_scm_type
Add Remote Archive SCM Type to support using artifacts and releases as projects

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-24 17:16:12 +00:00
Jake McDermott
0af9e01610 Don't display facts until facts are loaded 2020-08-24 12:55:32 -04:00
softwarefactory-project-zuul[bot]
6ef27e5458 Merge pull request #7962 from hit0ri/fix-broadcast-websocket-secret-length
Fix broadcast_websocket_secret length

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-24 16:11:13 +00:00
Alex Corey
90e8d5697e Adds fix to load template details screen even for users without webhook key permissions 2020-08-24 11:39:29 -04:00
nixocio
447bde95e3 Add label to identify isolated instance group JobDetail screen
Add label to identify isolated instance group JobDetail screen as per
mock up.

See: https://tower-mockups.testing.ansible.com/patternfly/jobs/jobs-detail/
2020-08-23 14:58:06 -04:00
Sean Sullivan
cda05c4f03 Updated test for lint
Updated test for lint
2020-08-22 20:16:27 -05:00
sean-m-sullivan
3794f095cf update to tower_project_update 2020-08-22 13:43:14 -05:00
Philip Douglass
6dc41f54fc Ensure scm credentials are passed for archive scm type 2020-08-22 11:16:04 -04:00
Ryan Petrello
de59d1d3f6 improve job reaping for jobs that were started on a missing Instance
see: https://github.com/ansible/awx/issues/7848
2020-08-21 16:32:17 -04:00
softwarefactory-project-zuul[bot]
2a824fc1d5 Merge pull request #7964 from nixocio/ui_update_button
Update disassociate button variant

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-21 19:36:43 +00:00
nixocio
17a40808b4 Update disassociate button variant
Update disassociate button variant.

See: https://github.com/ansible/awx/issues/7041

Also: https://tower-mockups.testing.ansible.com/patternfly/instance-groups/instance-groups-instances/
2020-08-21 14:46:15 -04:00
softwarefactory-project-zuul[bot]
fb381c18da Merge pull request #7961 from mabashian/fix-audit-warnings
Fix npm audit warnings

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-21 18:14:47 +00:00
Philip Douglass
30ae0f53ec Reject setting scm_branch for Remote Archive projects 2020-08-21 13:09:09 -04:00
Philip Douglass
2d23748971 Add Remote Archive SCM Type feature to CHANGELOG.md
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-21 12:53:51 -04:00
softwarefactory-project-zuul[bot]
3c39067d7d Merge pull request #7958 from shanemcd/fix-container-groups
Fix container groups

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-21 13:59:27 +00:00
Taras Dyshkant
e4095a0c27 Fix broadcast_websocket_secret length
Password lookup parameters must be within the same set of quotes.
Otherwise a default value of length is used (20).
2020-08-21 16:43:07 +03:00
mabashian
80fe98b8d6 Fix npm audit warnings 2020-08-21 09:20:29 -04:00
Shane McDonald
8ae328e427 Switch back to built-in kubectl connection plugin
There's a bug in the upstream community.kubernetes plugin. We can open up a
follow-up PR once that has been patched.
2020-08-20 21:42:07 -04:00
softwarefactory-project-zuul[bot]
51029a8b7a Merge pull request #7910 from nixocio/ui_issue_5684
Add type column to users list

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-20 21:13:00 +00:00
softwarefactory-project-zuul[bot]
5458411b19 Merge pull request #7803 from mabashian/6425-approval-notif
Adds support for toggling approval notifications on orgs and wfjts

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-20 20:23:50 +00:00
softwarefactory-project-zuul[bot]
bfe00d46ad Merge pull request #7903 from jlmitch5/searchableKeysPt3
update newly useRequested lists to get advanced searchableKeys

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-20 19:59:54 +00:00
softwarefactory-project-zuul[bot]
b92fab2048 Merge pull request #7866 from nixocio/ui_add_isolated_instance_groups_marker
Add label to show isolated group 

Reviewed-by: Kersom
             https://github.com/nixocio
2020-08-20 18:32:52 +00:00
mabashian
222a65c875 Adds extra variables to schedule details. Updates parameters by which we display prompt fields on schedule details. Extend VariableDetails component to be able to handle values that come in raw JSON form. 2020-08-20 14:29:24 -04:00
mabashian
daeb5a8de8 Only disable single notification row when toggling, not all rows 2020-08-20 14:24:05 -04:00
nixocio
6ed65a9c81 Add label to show isolated group
Add label to show isolated group.

See: https://tower-mockups.testing.ansible.com/patternfly/instance-groups/instance-groups/
2020-08-20 13:59:56 -04:00
Philip Douglass
d259500332 Implement Remote Archive SCM Type for ui_next
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 13:52:31 -04:00
Philip Douglass
70cbccd2ef Add migration for new Remote Archive SCM Type 2020-08-20 13:38:10 -04:00
Philip DOUGLASS
f72b777b07 Add plugin to cleanly manage possibly versioned project archives
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 13:38:10 -04:00
Philip Douglass
6720cd9bda Add block to download and unpack a remote archive
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 13:38:10 -04:00
Philip Douglass
b011e34fae Show fields for archive when selected as scm_type
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 13:38:10 -04:00
mabashian
681b765b9a Adds support for toggling approval notifications on orgs and wfjts 2020-08-20 13:36:32 -04:00
John Mitchell
d03448aa9d add searchable keys support for AssociateModal and SelectResourceStep lists 2020-08-20 12:53:35 -04:00
John Mitchell
aee2a81b27 update newly useRequested lists to get advanced searchableKeys 2020-08-20 12:53:35 -04:00
nixocio
8402cf97de Add type column to users list
Add type column to users list. Also, update `UserListItem` to be a
functional component.

See: https://github.com/ansible/awx/issues/5684
2020-08-20 12:50:13 -04:00
Philip Douglass
8157ab2fa9 Hide scm_branch field when scm_type is archive
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 12:34:35 -04:00
Philip Douglass
2f3f6e60d1 Add archive to scm_type expected test results
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 12:34:35 -04:00
Philip Douglass
d224aa09f0 Add archive to TestProjectUpdateCredentials test parametrize
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 12:34:35 -04:00
Philip Douglass
997351eee3 Add archive project data to Dashboard view
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 12:34:35 -04:00
Philip Douglass
47cabc4229 Add archive SCM url handling to update_scm_url()
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 12:34:35 -04:00
Philip Douglass
2cfa4eb60a Add archive option to SCM_TYPE_CHOICES for Remote Archives
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-08-20 12:34:35 -04:00
softwarefactory-project-zuul[bot]
a659b9d994 Merge pull request #7851 from mabashian/5910-workflow-prompt
Support workflow prompting on launch

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-08-20 16:30:29 +00:00
softwarefactory-project-zuul[bot]
780b2be8bf Merge pull request #7943 from mabashian/7660-workflow-details
Adds workflow detail tab to workflow results

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-08-20 16:30:23 +00:00
softwarefactory-project-zuul[bot]
a2a8c47166 Merge pull request #7864 from nixocio/ui_issue_7767
Add feature to edit instance group

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-08-20 16:30:16 +00:00
softwarefactory-project-zuul[bot]
6fcd017d48 Merge pull request #7951 from nixocio/ui_issue_7930
Add list of jobs for instance groups

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-20 16:22:35 +00:00
softwarefactory-project-zuul[bot]
bd093b8999 Merge pull request #7947 from nixocio/ui_instance_group_update_css_red
Use a patternfly CSS variable instead of red

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-20 16:22:29 +00:00
softwarefactory-project-zuul[bot]
cae45cec21 Merge pull request #7949 from ryanpetrello/even-more-changelog
more changelog updates

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-20 15:59:25 +00:00
nixocio
70295c3e75 Add list of jobs for instance groups
Add list of jobs for instance groups.

See: https://github.com/ansible/awx/issues/7930
2020-08-20 11:40:04 -04:00
Sean Sullivan
d6815e5114 Removed reference to sync
Updated references to sync in favour of update.
2020-08-20 10:30:43 -05:00
Ryan Petrello
0266ed3836 more changelog updates 2020-08-20 10:44:06 -04:00
softwarefactory-project-zuul[bot]
9ff4712844 Merge pull request #7948 from ryanpetrello/arm-changelog
changelog for arm64 builds

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-20 14:34:33 +00:00
Ryan Petrello
821cfba88a changelog for arm64 builds 2020-08-20 10:05:27 -04:00
nixocio
efa12b12ec Use a patternfly CSS variable instead of red
Use a patternfly CSS variable instead of red.

See: https://pf4.patternfly.org/documentation/overview/global-css-variables
2020-08-20 09:53:39 -04:00
softwarefactory-project-zuul[bot]
070c7e611c Merge pull request #7936 from AlexSCorey/FixesCredentialLookupNotfetchingdata
Adds fix to allow look up to fetch data

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-20 13:42:25 +00:00
softwarefactory-project-zuul[bot]
5d208cc14e Merge pull request #7607 from agaffney/arm_image_build
ARM image build support

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-19 22:07:32 +00:00
softwarefactory-project-zuul[bot]
e22d32c96b Merge pull request #7705 from anxstj/custom_environments
Change Dockerfile to copy custom venv

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-19 21:55:01 +00:00
softwarefactory-project-zuul[bot]
cf116d18b4 Merge pull request #7799 from john-westcott-iv/import-export-collecion-modules
Adding import/export modules around AWX Kit features

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-19 20:51:05 +00:00
softwarefactory-project-zuul[bot]
a3eff133fe Merge pull request #7942 from ryanpetrello/iso-removal
fix a bug that prevents the explicit removal of instances from groups

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-19 19:16:20 +00:00
John Westcott IV
a5afe0214a Trying to make AWXKIT tests not run on python2 2020-08-19 14:29:42 -04:00
John Westcott IV
b93319e359 Updating to remove auth_type since its not longer required 2020-08-19 14:27:02 -04:00
John Westcott IV
2c8c1ff595 Fixing sanity error 2020-08-19 14:14:49 -04:00
John Westcott IV
3abd77c4c0 Fixing oauth token login and making module respect token over username/password 2020-08-19 14:12:50 -04:00
John Westcott IV
a2eab45d61 Trying to gobble up logs incase there are errors 2020-08-19 14:12:50 -04:00
beeankha
76f08744f6 Fix linter whitespace error 2020-08-19 14:12:50 -04:00
John Westcott IV
01e08ba0e1 Fixing exit_module -> exit_json 2020-08-19 14:12:50 -04:00
John Westcott IV
c2e0c0655b Fixing validate-module errors 2020-08-19 14:12:50 -04:00
John Westcott IV
8688740e93 Fixing ansible pep8 issues 2020-08-19 14:12:50 -04:00
John Westcott IV
3fe61cfa4f Fixing linting issues 2020-08-19 14:12:50 -04:00
John Westcott IV
5107f164a2 Expanding examples 2020-08-19 14:12:50 -04:00
John Westcott IV
9bf19daa5e Another linting issue 2020-08-19 14:12:50 -04:00
John Westcott IV
f2b9bdd552 Removed default: '' and updated [] to '' per specification 2020-08-19 14:12:50 -04:00
John Westcott IV
8a0cd747e1 Fixing truthy linting issues 2020-08-19 14:12:50 -04:00
John Westcott IV
748bdbd2dd Fix python3 Zuul error with awxkit 2020-08-19 14:12:50 -04:00
John Westcott IV
08e5dd87e6 Adding integration tests and example in import 2020-08-19 14:12:50 -04:00
John Westcott IV
40f6741474 Adding import/export awx kit features
Changed library structure

Origional TowerModule becomes TowerLegacyModule

TowerModule from tower_api becomes TowerAPIModule

A real base TowerModule is created in tower_module.py

A new TowerAWXKitModule is created in tower_awxkit

TowerAWXKitModule and TowerAPIModule are child classes of TowerModule
2020-08-19 14:12:50 -04:00
mabashian
c0cb1dee91 Adds workflow detail tab to workflow results 2020-08-19 13:55:42 -04:00
Alex Corey
7bff11379c Update awx/ui_next/src/components/Lookup/CredentialLookup.jsx
Co-authored-by: Jake McDermott <yo@jakemcdermott.me>
2020-08-19 13:32:48 -04:00
Ryan Petrello
b14515b287 fix a bug that prevents the explicit removal of instances from groups 2020-08-19 13:22:31 -04:00
softwarefactory-project-zuul[bot]
383f8aa8f9 Merge pull request #7937 from ryanpetrello/only-bearer
clean up old authtoken support

Reviewed-by: John Westcott IV
             https://github.com/john-westcott-iv
2020-08-19 17:10:51 +00:00
softwarefactory-project-zuul[bot]
9d2498cf6b Merge pull request #7934 from ryanpetrello/deprecate-mercurial
add a deprecation warning for mercurial project syncs

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-19 16:32:32 +00:00
Ryan Petrello
815d691622 clean up old authtoken support
just use Bearer tokens - those are the only type of tokens we support
2020-08-19 12:23:00 -04:00
Alex Corey
8a2bf8c1fc adds fix to allow look up to fetch data 2020-08-19 12:18:04 -04:00
softwarefactory-project-zuul[bot]
fb66766463 Merge pull request #7933 from jakemcdermott/fix-7756
Use organization api to create users

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-19 15:36:27 +00:00
Ryan Petrello
612bb81976 add a deprecation warning for mercurial project syncs
see: https://github.com/ansible/awx/issues/7932
2020-08-19 11:19:03 -04:00
Jake McDermott
dc9f2441df Embolden user organization name 2020-08-19 11:02:22 -04:00
Jake McDermott
806a468600 Use organization api to create users
This ensures that the user will be related to the chosen organization
when it is created.
2020-08-19 11:02:11 -04:00
softwarefactory-project-zuul[bot]
d452c1d7a9 Merge pull request #7918 from ryanpetrello/surro-get-outta-here
make event stdout encoding more resilient to UTF-16 surrogate pairs

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-18 14:48:11 +00:00
Ryan Petrello
33e2c059ed make event stdout encoding more resilient to UTF-16 surrogate pairs
see: https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Surrogates
2020-08-18 10:23:20 -04:00
softwarefactory-project-zuul[bot]
e7281a753f Merge pull request #7922 from shanemcd/pin-xdist
Fix API tests

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-18 12:52:45 +00:00
Shane McDonald
54e87378d5 Pin pytest-xdist 2020-08-17 20:43:02 -04:00
mabashian
1e9a71a2e4 Run prettier 2020-08-13 11:55:57 -04:00
mabashian
98b7f3b618 Support workflow prompting on launch 2020-08-13 11:36:58 -04:00
softwarefactory-project-zuul[bot]
54f8742747 Merge pull request #7070 from JoelKle/fix_rerun_ability
Installer - local_docker - fixed the ability to rerun the playbook

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-13 14:12:08 +00:00
softwarefactory-project-zuul[bot]
06efba6f72 Merge pull request #7800 from AlexSCorey/7789-UserTokenDetails
Adds User Token Details page

Reviewed-by: Daniel Sami
             https://github.com/dsesami
2020-08-12 21:00:38 +00:00
Alex Corey
15fda43a10 Utilizes UserDateDetail, Capitalizes Scope value, fixes spelling errors 2020-08-12 16:34:59 -04:00
Alex Corey
19d6a3f65e Adds User Token Details page 2020-08-12 16:33:32 -04:00
softwarefactory-project-zuul[bot]
f86697536c Merge pull request #7807 from marshmalien/7683-smart-inv-hosts
Add smart inventory host list view

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-12 18:41:51 +00:00
softwarefactory-project-zuul[bot]
d17266fae0 Merge pull request #7895 from jlmitch5/searchOptionsRequestsPass2
update existing relatedSearchKey requests to new convention and fix U…

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-12 17:19:17 +00:00
John Mitchell
dd68b6ed73 update existing relatedSearchKey requests to new convention and fix UJT searchKeys 2020-08-12 12:21:10 -04:00
Marliana Lara
214cb76e1e Add custom host toggle tooltip for smart inventory hosts 2020-08-12 10:40:59 -04:00
softwarefactory-project-zuul[bot]
9c13c07169 Merge pull request #7894 from ansible/chrismeyersfsu-patch-2
Update websockets.md

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-12 14:23:33 +00:00
softwarefactory-project-zuul[bot]
1d5bdedc9b Merge pull request #7893 from AlanCoding/awx_awx_141
Add changelog preparing for awx.awx 14.1.0 bug fix

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-12 14:16:31 +00:00
softwarefactory-project-zuul[bot]
019ad9da73 Merge pull request #7880 from jlmitch5/kebabifyAdvancedSearch
kebabify additional controls when advanced search is displayed

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-12 13:53:52 +00:00
Chris Meyers
5dd2cb10b4 Update websockets.md 2020-08-12 09:52:10 -04:00
Chris Meyers
aa8d3d5ae4 Update websockets.md
Add more details about backplane websocket functionality.
2020-08-12 09:49:24 -04:00
Alan Rominger
dfad5117fa Add changelog preparing for awx.awx 14.1.0 bug fix 2020-08-12 09:47:52 -04:00
John Mitchell
54d13b6397 remove unnecessary selectors from kebabification test 2020-08-12 09:26:46 -04:00
John Mitchell
1323626d5e add onShowAdvancedSearch callback test 2020-08-12 09:26:46 -04:00
John Mitchell
a352de3da7 change name of hook to be useKebabifiedMenu 2020-08-12 09:26:46 -04:00
John Mitchell
8f04026404 kebabify additional controls when advanced search is displayed 2020-08-12 09:26:46 -04:00
softwarefactory-project-zuul[bot]
0adb9cfd45 Merge pull request #7888 from nixocio/ui_remove_undefined_prop
Remove undefined prop from SelectedList call

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-12 13:14:26 +00:00
nixocio
aace8f5032 Remove undefined prop from SelectedList call
Remove undefined prop from `SelectedList` call.
2020-08-11 16:44:03 -04:00
Marliana Lara
8a4d45ddb6 Add smart inventory host list view 2020-08-11 14:48:39 -04:00
softwarefactory-project-zuul[bot]
025a979cb2 Merge pull request #7867 from keithjgrant/5651-notification-templates
Notification templates list & details

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-11 18:10:35 +00:00
Keith Grant
d27d4e4f28 workaround import/dependency bug in tests 2020-08-11 10:36:42 -07:00
softwarefactory-project-zuul[bot]
1dfc9d224c Merge pull request #7875 from ryanpetrello/more-changes
changelog updates for recent additions

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-11 17:24:32 +00:00
Ryan Petrello
5fb1b1ceea changelog updates for recent additions 2020-08-11 12:52:52 -04:00
Keith Grant
65d4c347c9 add ObjectDetails for HTTP Headers display 2020-08-11 09:36:11 -07:00
Keith Grant
4c555815b3 add notification list tests 2020-08-11 09:36:11 -07:00
Keith Grant
8bb1c985c0 send test notifications 2020-08-11 09:36:11 -07:00
Keith Grant
1405f6ca51 add notification status indicator 2020-08-11 09:36:10 -07:00
Keith Grant
a9451c9864 more template details; add template delete button 2020-08-11 09:36:10 -07:00
Keith Grant
ab4628b199 flush out template detail 2020-08-11 09:36:10 -07:00
Keith Grant
182dce3dc3 flushing out notification template detail 2020-08-11 09:36:10 -07:00
Keith Grant
fbd1147cff start notification template list 2020-08-11 09:36:10 -07:00
softwarefactory-project-zuul[bot]
0e730311bb Merge pull request #7871 from ryanpetrello/upgrade-ldap
update to a newer python-ldap to address a bug

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-11 16:29:30 +00:00
softwarefactory-project-zuul[bot]
9d4c05b15e Merge pull request #7872 from AlanCoding/devel_version
Fix awx.awx version replacement regex

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-11 15:47:16 +00:00
sean-m-sullivan
69dc0a892f fix lint 2020-08-11 09:56:08 -05:00
sean-m-sullivan
813e38636a fix documentation 2020-08-11 09:38:18 -05:00
nixocio
e3fe680d14 Add feature to edit instance group
Add feature to edit instance group.

See: https://github.com/ansible/awx/issues/7767
2020-08-11 10:37:08 -04:00
softwarefactory-project-zuul[bot]
3ca43e63b5 Merge pull request #7808 from zedr/feat-yaml-import
Allow YAML as a CLI import format

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-11 14:31:01 +00:00
sean-m-sullivan
262b2bf8ff Merge branch 'project_update' of github.com:sean-m-sullivan/awx into project_update 2020-08-11 09:28:31 -05:00
sean-m-sullivan
af1fc5a9e9 add tests 2020-08-11 09:28:17 -05:00
Alan Rominger
2a0c61de63 Change regex to match what is in source 2020-08-11 10:04:14 -04:00
Sean Sullivan
8af315cf29 Create tower_project_update
Add module to update tower project and wait until synced.
2020-08-11 08:54:10 -05:00
Ryan Petrello
987c7d48a0 minor cleanup up CLI import -f yaml support 2020-08-11 09:44:13 -04:00
Ryan Petrello
5e9d372db2 update to a newer python-ldap to address a bug
see: https://github.com/ansible/awx/issues/7868
2020-08-11 09:34:04 -04:00
Sean Sullivan
7089c5f06e Merge pull request #2 from ansible/devel
Rebase
2020-08-11 07:56:11 -05:00
Rigel Di Scala
579604d2c6 Allow YAML as a CLI import format
This changset allows the import of YAML formatted resources. The CLI
user can indicate which format to use with the `-f, --format` option.
The CLI help text has been amended to reflect the new feature.

The AWX CLI `export` subcommand offers the option of formatting the output
as YAML or JSON, so it makes sense that the `import` subcommand reflects
this.

A simple test is also provided. In order to ease the task of testing
commands that import resources by reading the stdin, the CLI has been
extended to allow specifying an alternative file descriptor for stdin,
similarly to stdout and stderr.
2020-08-10 23:43:53 +02:00
softwarefactory-project-zuul[bot]
ddb6c5d0cc Merge pull request #7644 from marshmalien/smart-inventory-forms
Add smart inventory add/edit forms and host filter lookup

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-10 19:08:36 +00:00
softwarefactory-project-zuul[bot]
9bd6a323aa Merge pull request #7860 from AlanCoding/upgrade_gitpython
Upgrade gitpython to pick up bug fix

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-10 19:07:26 +00:00
Alan Rominger
8aacd006e0 Revert updater changes to Ansible requirements 2020-08-10 14:29:07 -04:00
Alan Rominger
f269d5b2ed Upgrade gitpython to pick up bug fix 2020-08-10 14:29:05 -04:00
Marliana Lara
af218aaa0b Decode host filter chip values and fix boolean search filter chip bug 2020-08-10 14:19:55 -04:00
Marliana Lara
8e6d475a9d Add smart inventory edit form 2020-08-10 14:09:01 -04:00
Marliana Lara
6a304dce55 Add smart inventory add form and host filter lookup 2020-08-10 14:09:01 -04:00
Marliana Lara
5864d61b5b Refactor organization look to use useRequest hook 2020-08-10 14:08:57 -04:00
softwarefactory-project-zuul[bot]
fbb9998b68 Merge pull request #7776 from nixocio/ui_add_instance_group
Add feature to add instance group

Reviewed-by: Kersom
             https://github.com/nixocio
2020-08-10 17:35:01 +00:00
softwarefactory-project-zuul[bot]
c6317c0113 Merge pull request #7861 from ansible/chrismeyersfsu-patch-1
Update websockets.md

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-10 17:33:54 +00:00
softwarefactory-project-zuul[bot]
d48cc1ab43 Merge pull request #7847 from zedr/feat-workflow-labels
Export Workflow Job Template Node Labels

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-10 17:27:21 +00:00
softwarefactory-project-zuul[bot]
ccdb2b4ca3 Merge pull request #7856 from zedr/fix-related-import-return
Fix early return in assign related method

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-10 17:26:05 +00:00
nixocio
897c8b74a5 Add feature to add instance group
Add feature to add instance group.

See: https://github.com/ansible/awx/issues/7744
2020-08-10 13:06:56 -04:00
Chris Meyers
fdc53bd0d3 Update websockets.md
spelling
2020-08-10 12:58:49 -04:00
Chris Meyers
1cf48ffc9e Update websockets.md
Add documentation for websocket backplane secret key exchange logic.
2020-08-10 12:58:49 -04:00
Rigel Di Scala
0beff054af Export Workflow Job Template Node Labels
This change adds related Labels to the Workflow Job Template document that is
exported by the AWX CLI.

Previously, exporting and then importing Workflow Job Templates would
not retain their related Labels.
2020-08-10 12:56:52 -04:00
Rigel Di Scala
eeebd517d1 Fix early return in assign related method
This change fixes an erroneus early return in a private method that was
preventing more than one type of related object from being correctly
assigned to the parent object, and therefore imported.

Also, a minor spelling mistake was corrected.
2020-08-10 12:54:23 -04:00
softwarefactory-project-zuul[bot]
395b338221 Merge pull request #7863 from ryanpetrello/fix-tox
fix busted flake8 CI

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-10 16:53:08 +00:00
Ryan Petrello
32542021c6 fix busted flake8 CI 2020-08-10 12:26:12 -04:00
softwarefactory-project-zuul[bot]
52bb71b63e Merge pull request #7840 from beeankha/credential_input_idempotency
Make 'inputs' Unchanged When Blank in Credentials Module

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
             https://github.com/beeankha
2020-08-06 18:04:15 +00:00
softwarefactory-project-zuul[bot]
91df10dbb5 Merge pull request #7739 from jlmitch5/advSearch
Advanced search

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-06 17:57:24 +00:00
John Mitchell
61ce8cb029 delete inadverdently added back InventoryScriptLookup file 2020-08-06 13:21:00 -04:00
John Mitchell
cbea77a90c update rest of lookups to use correct searchableKeys props 2020-08-06 13:21:00 -04:00
John Mitchell
f8bd8abc82 make name default searchColumn for ProjectJobTemplatesList. also add helpful error message to tell you this is the issue 2020-08-06 13:21:00 -04:00
John Mitchell
f24654fb26 update searchablekeys prop names for project lookup 2020-08-06 13:21:00 -04:00
John Mitchell
495b4142c7 make sortColumnKey error message more clear 2020-08-06 13:21:00 -04:00
John Mitchell
f15325aebf add back in searchable keys props to user token list 2020-08-06 13:21:00 -04:00
John Mitchell
5b362ef162 add selectors for cypress tests 2020-08-06 13:21:00 -04:00
John Mitchell
0876b944ed fix AddRersourceRole sort column 2020-08-06 13:21:00 -04:00
John Mitchell
ede1260675 fix merge conflicts and failing test 2020-08-06 13:21:00 -04:00
John Mitchell
36585ad74e Move Search to hooks and excise PF Dropdown in favor of Select 2020-08-06 13:21:00 -04:00
John Mitchell
dc2bf503d1 Add AdvancedSearch propTypes and defaultProps 2020-08-06 13:21:00 -04:00
John Mitchell
2229d43e8b fix duplicate variable and key usng array index issues 2020-08-06 13:21:00 -04:00
John Mitchell
5ffc2e4188 Updates to support advanced search changes:
- make set type and lookup prefixes/suffixes on searchColumns explicitly defined
- send possible search keys from options requests on (most) lists
2020-08-06 13:21:00 -04:00
John Mitchell
b46a87209a Add advanced search to UI 2020-08-06 12:17:49 -04:00
softwarefactory-project-zuul[bot]
c7dd0bc2b9 Merge pull request #7842 from nixocio/ui_remove_not_defined_props
Remove showExpandCollapse prop from the DataListToolbar calls

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-06 16:16:00 +00:00
softwarefactory-project-zuul[bot]
0b38a8be7e Merge pull request #7747 from marshmalien/add-settings-framework
Add settings navigation skeleton

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-06 16:14:33 +00:00
softwarefactory-project-zuul[bot]
6d9aed35d7 Merge pull request #7810 from mabashian/7564-access-add-btn
Fix rbac on Add button on User Access/Team Roles lists

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-06 16:10:55 +00:00
softwarefactory-project-zuul[bot]
16ce7b4647 Merge pull request #7821 from mabashian/7814-form-error
Handle form submission errors that may be deeply nested in the return object

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-06 16:09:29 +00:00
softwarefactory-project-zuul[bot]
d58a66d587 Merge pull request #7838 from ryanpetrello/bump-14-0-0
Bump version to 14.0.0

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-06 15:45:35 +00:00
nixocio
03274db695 Remove showExpandCollapse prop from the DataListToolbar calls
Remove showExpandCollapse prop from the DataListToolbar calls. This is
not an expected prop to be passed to this component.

Inside DataListToolbar.

```
  const showExpandCollapse = onCompact && onExpand;
```

In order to use this feature, `onCompact` and `onExpand` props should
be passed.

...
2020-08-06 10:58:20 -04:00
softwarefactory-project-zuul[bot]
2c5d3ff64a Merge pull request #7477 from AlanCoding/ee_req
Add execution environment metadata to AWX collection

Reviewed-by: Alan Rominger <arominge@redhat.com>
             https://github.com/AlanCoding
2020-08-06 14:24:39 +00:00
AlanCoding
f953e6ab55 Add execution environment metadata to AWX collection 2020-08-05 22:46:23 -04:00
beeankha
dcc500e7bb Make 'inputs' idempotent in credentials module, add test to check this works 2020-08-05 16:44:22 -04:00
Ryan Petrello
99e417d748 Bump version to 14.0.0 2020-08-05 16:22:03 -04:00
softwarefactory-project-zuul[bot]
1c0dc1cccb Merge pull request #7836 from ryanpetrello/downstream-merge
merge in a few downstream fixes

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-05 19:42:53 +00:00
Ryan Petrello
6067fc36f6 begin a 14.0.0 changelog 2020-08-05 14:53:01 -04:00
Ryan Petrello
0c6be1f4d7 Merge branch 'downstream' into devel 2020-08-05 14:48:36 -04:00
softwarefactory-project-zuul[bot]
57732d4630 Merge pull request #7824 from shanemcd/fix-isolated-dev-env
Fix isolated dev env

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-04 23:30:56 +00:00
softwarefactory-project-zuul[bot]
3af31df2c9 Merge pull request #7823 from john-westcott-iv/cancel_500_error
Catching runtime error

Reviewed-by: Ryan Petrello
             https://github.com/ryanpetrello
2020-08-04 22:25:50 +00:00
Shane McDonald
00ea453ccd Fix isolated dev env 2020-08-04 17:25:57 -04:00
John Westcott IV
27676b0634 Adding RuntimeError which is returned from a connection error in awx/main/dispatch/control.py 2020-08-04 17:17:38 -04:00
mabashian
4a3e4af0d9 Updated import/export names for consistency 2020-08-04 15:29:59 -04:00
mabashian
b145f97e0e Handle form submission errors that may be deeply nested in the return object 2020-08-04 14:30:42 -04:00
softwarefactory-project-zuul[bot]
2a9804e589 Merge pull request #7768 from wenottingham/add-some-nozzles
Create marginally more realistic event data with firehose

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-04 16:02:27 +00:00
softwarefactory-project-zuul[bot]
b990271dec Merge pull request #7811 from ryanpetrello/deprecate-galaxy-basic-auth
mark PRIMARY_GALAXY_USERNAME and PRIMARY_GALAXY_PASSWORD as deprecated

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-04 14:45:58 +00:00
Ryan Petrello
76ba363513 mark PRIMARY_GALAXY_USERNAME and PRIMARY_GALAXY_PASSWORD as deprecated 2020-08-04 10:18:40 -04:00
mabashian
4ce2235f68 Fix rbac on Add button on User Access/Team Roles lists 2020-08-04 08:49:51 -04:00
Bill Nottingham
bd6cac966a Create marginally more realistic event data with firehose 2020-08-03 20:57:10 -04:00
softwarefactory-project-zuul[bot]
15c4ab3a9b Merge pull request #7802 from ryanpetrello/vnnn-minus
remove vNNN from example migration files

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-03 20:09:24 +00:00
Ryan Petrello
820c0782ad remove vNNN from example migration files 2020-08-03 15:30:37 -04:00
softwarefactory-project-zuul[bot]
b11908ed1f Merge pull request #7577 from AlexSCorey/RemovesInventoryScripts
Removes Inventory Script screens, routes, stubs etc.

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-03 18:37:25 +00:00
softwarefactory-project-zuul[bot]
e20ea5edba Merge pull request #7724 from AlexSCorey/7434-UserTokensDelete
Adds delete functionality to user tokens list

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-03 18:14:28 +00:00
Alex Corey
3d08754be5 Removes Inventory Script screens, routes, stubs etc. 2020-08-03 14:07:44 -04:00
Alex Corey
164d4e6419 Adds delete functionality to user tokens list 2020-08-03 13:46:34 -04:00
softwarefactory-project-zuul[bot]
d5ab54977c Merge pull request #7796 from zedr/fix-py3-yaml-bytes-decoded
Fix garbage being printed when exporting as YAML - related #7795

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-08-03 16:38:16 +00:00
Rigel Di Scala
490746fe8c Fix garbage being printed when exporting as YAML - related #7795
This resolves issue #7795, by passing the `encoding` keyword argument
only when the code is run on a Python 2 interpreter.

related #7795.
2020-08-03 11:57:45 -04:00
softwarefactory-project-zuul[bot]
def79de72b Merge pull request #7785 from mabashian/convert-NotificationList-functional
Converts NotificationList to functional component and now uses useRequest

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-31 19:29:56 +00:00
softwarefactory-project-zuul[bot]
f2fa28e9dc Merge pull request #7786 from mabashian/convert-OrganizationLookup-useRequest
Updates OrganizationLookup to use useRequest

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-31 19:29:50 +00:00
Andrew Gaffney
02252f3f97 ARM image build support
* upgrade `chromedriver` for ARM support
* upgrade `pynacl` to fix `libsodium` build issue on ARM
* remove unnecessary i686-specific `libstdc++.so.6` package
* install `kubectl` and `tini` from upstream binaries for ARM support
* use upstream `postgres` and `alpine` docker images for `postgresql` helm chart

Fixes #7051
2020-07-31 14:22:35 -04:00
softwarefactory-project-zuul[bot]
fed02ef14a Merge pull request #7634 from norpol/patch-1
Fix requirements updater.sh "sourcing" snippet

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-31 17:54:17 +00:00
softwarefactory-project-zuul[bot]
1077e218bd Merge pull request #7782 from ryanpetrello/galaxy-collection-install-29
only support ansible-galaxy collection in 2.9+

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-31 17:54:10 +00:00
softwarefactory-project-zuul[bot]
76f75f1745 Merge pull request #7787 from squidboylan/collection_test_fix
Fix collection test inventory

Reviewed-by: Alan Rominger <arominge@redhat.com>
             https://github.com/AlanCoding
2020-07-31 17:26:25 +00:00
softwarefactory-project-zuul[bot]
1bb597bba4 Merge pull request #7788 from ryanpetrello/eff-string
fix a typo in an f-string

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-31 17:22:35 +00:00
Ryan Petrello
a0e5e74cab fix a typo in an f-string 2020-07-31 12:48:45 -04:00
Caleb Boylan
d935e3c5a3 Fix collection test inventory 2020-07-31 09:47:10 -07:00
mabashian
460ce7fcfa Updates OrganizationLookup to use useRequest 2020-07-31 12:01:55 -04:00
softwarefactory-project-zuul[bot]
ec8725d54f Merge pull request #7614 from vjanssens/5626-add-item-count
Add pagination/item count to DataListToolbar

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-31 14:58:29 +00:00
mabashian
d8af8baae3 Converts NotificationList to functional component and now uses useRequest 2020-07-31 10:49:27 -04:00
softwarefactory-project-zuul[bot]
d36999acc7 Merge pull request #7784 from ryanpetrello/comments
make these issue template sentences comments

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-31 14:34:06 +00:00
Ryan Petrello
5b8cfa353f make these issue template sentences comments
(because people are filing issues and leaving this text at the top)
2020-07-31 09:58:52 -04:00
softwarefactory-project-zuul[bot]
07e86adbb7 Merge pull request #7750 from Orabig/devel
Allow to use an existing PVC for postgresql install with Helm

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-31 13:53:09 +00:00
Ryan Petrello
1ad623f253 only support ansible-galaxy collection in 2.9+
see: https://github.com/ansible/awx/issues/7769
2020-07-31 09:42:07 -04:00
softwarefactory-project-zuul[bot]
c0a0e16ba0 Merge pull request #7742 from nixocio/ui_rebased_issue_7640
Add details page for instance group

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-30 20:07:54 +00:00
softwarefactory-project-zuul[bot]
91d3f954cd Merge pull request #7772 from mabashian/convert-ResourceAccessList-functional
Converts ResourceAccessList to functional component

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-30 18:10:29 +00:00
softwarefactory-project-zuul[bot]
b5f87b1bac Merge pull request #7774 from ryanpetrello/bug-filing-extra
update the bug report and feature templates w/ additional instructions

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-30 18:03:43 +00:00
Ryan Petrello
173628c709 update the bug report and feature templates w/ additional instructions 2020-07-30 13:24:54 -04:00
softwarefactory-project-zuul[bot]
2cabaf8727 Merge pull request #7732 from AlexSCorey/7728-TeamsUsers
Adds Teams Access List and renames Tabs and files under teams

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-30 16:09:14 +00:00
softwarefactory-project-zuul[bot]
d38b3afd21 Merge pull request #7764 from fosterseth/add-kubernetes_web_svc_type
Add kubernetes_web_svc_type variable to installer/inventory

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-30 14:59:39 +00:00
softwarefactory-project-zuul[bot]
162aab7272 Merge pull request #7738 from mabashian/test-console-cleanup
Test console cleanup

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-30 14:20:20 +00:00
mabashian
dcaab9bc8b Converts ResourceAccessList to functional component 2020-07-30 10:10:56 -04:00
softwarefactory-project-zuul[bot]
8f1c071acf Merge pull request #7733 from nixocio/ui_update_delete
Update delete button variant to secondary

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-30 14:03:36 +00:00
softwarefactory-project-zuul[bot]
efdee6ed1f Merge pull request #7770 from AlanCoding/falsy_inv
Handle not-provided falsy values in tower_inventory_source

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-30 12:24:20 +00:00
AlanCoding
750c22a150 Handle not-provided falsy values in tower_inventory_source 2020-07-29 21:55:20 -04:00
softwarefactory-project-zuul[bot]
b444d10369 Merge pull request #7745 from mabashian/convert-WFJTList-useRequest
Converts WorkflowJobTemplatesList to use useRequest in preparation for advanced search

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-29 23:48:10 +00:00
softwarefactory-project-zuul[bot]
2f81a1d803 Merge pull request #7752 from mabashian/convert-ProjectList-useRequest
Converts ProjectsList to use useRequest in preparation for advanced search

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-29 23:12:51 +00:00
softwarefactory-project-zuul[bot]
902566ccfb Merge pull request #7761 from mabashian/convert-OrganizationTeamList-useRequest
Converts OrganizationTeamList to use useRequest in preparation for advanced search

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-07-29 23:04:23 +00:00
softwarefactory-project-zuul[bot]
dd828cba26 Merge pull request #7754 from mabashian/convert-JobTemplatesList-useRequest
Converts JobTemplatesList to use useRequest in preparation for advanced search

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-07-29 23:04:18 +00:00
softwarefactory-project-zuul[bot]
45809abc6f Merge pull request #7743 from mabashian/convert-UserList-functional
Converts UserList to functional component

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-07-29 22:52:45 +00:00
softwarefactory-project-zuul[bot]
3bcad7be81 Merge pull request #7759 from mabashian/convert-ProjectJobTemplatesList-hooks
Update ProjectJobTemplatesList to use useSelected, useRequest, useDeleteItems hooks

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-07-29 22:50:06 +00:00
softwarefactory-project-zuul[bot]
21a2b1a630 Merge pull request #7755 from mabashian/convert-InventorySourcesList-useRequest
Converts InventorySourcesList to use useRequest in preparation for advanced search

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
             https://github.com/jakemcdermott
2020-07-29 22:48:32 +00:00
softwarefactory-project-zuul[bot]
0d75e1540c Merge pull request #7765 from mabashian/convert-InventoryGroupsList-useRequest
Convert InventoryGroupsList to use useRequest and useSelected hooks

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-29 22:48:27 +00:00
softwarefactory-project-zuul[bot]
d43ea41b7f Merge pull request #7748 from jakemcdermott/noportal
Delete portal mode

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-29 20:45:04 +00:00
softwarefactory-project-zuul[bot]
aca1e73d84 Merge pull request #7753 from rooftopcellist/fix_unmarked_strings
Use quotations when marking strings for translation

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-29 19:37:05 +00:00
Christian Adams
6e75d25b74 Merge pull request #4492 from rooftopcellist/fix_broken_ui_links
Use quotations when marking strings for translation [3.7.2]
2020-07-29 15:28:18 -04:00
mabashian
ccecd90015 Convert InventoryGroupsList to use useRequest and useSelected hooks 2020-07-29 15:07:06 -04:00
softwarefactory-project-zuul[bot]
5c400b96fe Merge pull request #7762 from gamuniz/add_helpful_dialog_profilesql
Add helpful dialog profilesql

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-29 18:28:15 +00:00
Seth Foster
07160d9719 Add kubernetes_web_svc_type variable to installer/inventory
awx-web-svc is now settable, e.g. ClusterIP or NodePort. Default
is NodePort
2020-07-29 14:18:10 -04:00
Marliana Lara
42158dea59 Hide license route based on install and add useConfig hook 2020-07-29 14:11:49 -04:00
nixocio
a4dd20872c Add details page for instance group
This PR also:

* Modify routing system to add `container_groups` as well.
* Add `DetailBadge` component.
* Add container group files as placeholder.

See: https://github.com/ansible/awx/issues/7640
Also: https://github.com/ansible/awx/issues/7467
2020-07-29 13:27:57 -04:00
Gabe Muniz
0de900a021 fixed for flake8 compliance 2020-07-29 13:13:01 -04:00
mabashian
b35aa1ac83 Converts OrganizationTeamList to use useRequest in preparation for advanced search 2020-07-29 13:12:10 -04:00
Gabe Muniz
9b06fb1e6a added helpful messaging using profile sql 2020-07-29 12:48:01 -04:00
Alex Corey
24acacbcb6 Renames files to match the tabs better. 2020-07-29 12:24:09 -04:00
mabashian
98e44de7a1 Update capitalization to match PF guidelines 2020-07-29 11:45:58 -04:00
mabashian
b11f2f017f Update capitalization to match PF guidelines 2020-07-29 11:44:17 -04:00
mabashian
9d8a177c75 Update capitalization to match PF guidelines 2020-07-29 11:43:28 -04:00
mabashian
7d8963388f Update capitalization to match PF guidelines 2020-07-29 11:41:16 -04:00
mabashian
3e0d0ec62d Update capitalization to match PF guidelines 2020-07-29 11:39:32 -04:00
mabashian
a34953cd6c Update list to use useSelected, useRequest, useDeleteItems hooks 2020-07-29 11:32:08 -04:00
Marliana Lara
c24e169bf6 Add settings framework 2020-07-29 10:58:48 -04:00
mabashian
48b29352d7 Converts InventorySourcesList to use useRequest in preparation for advanced search 2020-07-29 10:08:45 -04:00
mabashian
8addc6bb59 Converts JobTemplatesList to use useRequest in preparation for advanced search 2020-07-29 09:48:54 -04:00
Christian Adams
76b25d8c96 Use quotations when marking strings for translation 2020-07-29 09:42:18 -04:00
mabashian
e343c9698d Converts ProjectsList to use useRequest in preparation for advanced search 2020-07-29 09:09:27 -04:00
mabashian
bc02321689 Adopt useSelected 2020-07-29 08:45:06 -04:00
Benoît Chauvet
e917cffb5f Allow to use an existing PersistanceVolumeClaim for postgresql install with Helm
Signed-off-by: Benoît Chauvet <benoit.chauvet@gmail.com>
2020-07-29 14:11:12 +02:00
Alan Rominger
b4c3da55d2 Merge pull request #4474 from AlanCoding/per_update_cache_37
[3.7] Per update roles and collections cache
2020-07-29 06:58:25 -04:00
Christian Adams
b1481ec6e3 Use quotations when marking strings for translation 2020-07-28 21:23:14 -04:00
Jake McDermott
3b597cd80a Delete portal mode 2020-07-28 20:27:25 -04:00
softwarefactory-project-zuul[bot]
b009b01251 Merge pull request #7707 from nixocio/ui_update_per_mockup
Update wording to equal mock up

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-29 00:06:59 +00:00
mabashian
2409bc5ee3 Converts WorkflowJobTemplatesList to use useRequest in preparation for advanced search 2020-07-28 17:13:56 -04:00
mabashian
f775ed3f77 Converts UserList to functional component 2020-07-28 16:22:51 -04:00
nixocio
d373cbdca9 Update delete button variant to secondary
Update delete button variant to secondary, except in Modals.

see: https://github.com/ansible/awx/issues/7722
2020-07-28 14:05:12 -04:00
AlanCoding
daaa0c8efe Avoid using long name of option not in 2.8 2020-07-28 13:57:31 -04:00
Bill Nottingham
c6eb8cf59b Cache downloaded roles & collections
Populate the cache the first time the job is run for a revision
that needs them, and for future runs for that revision just
copy it into the private directory.

Delete the cache on project deletion.

Invalidate the cache on a new project revision

Also download roles/collections during the sync job

Since we're writing into a per-revision cache, we can do this easily now.

Don't try and install content if there aren't any requirements expecting it

Adjust pathing to the proper location.

Force install if doing a manual sync.

Requirements may be unversioned.

Remove the cache when delete-on-update is set

Integrate content caching with existing task logic

Revert the --force flags

use the update id as metric for role caching

Shift the movement of cache to job folder from rsync task to python

Only install roles and collections if needed

Deal with roles and collections for jobs without sync
Skip local copy if roles or collections turned off

update docs for content caching

Design pivot - use empty cache dir to indicate lack of content

Do not cache content if we did not install content

Test changes to allay concerns about reliability of local_path

Do not blow away cache for SCM inventory updates

Remove project update vars no longer used

Remove job pre-creation of content folders

code style edit, always use cache_id as property in tasks

Fix log message
2020-07-28 13:57:28 -04:00
Alex Corey
8e27e0ce28 Teams Access List using Resource Access component 2020-07-28 13:17:11 -04:00
Alex Corey
a070d57080 Adds Teams Roles List and Disassociate functionality 2020-07-28 13:17:11 -04:00
mabashian
721c8d98f8 Prevents debug messages from being logged while tests are running 2020-07-28 13:13:00 -04:00
softwarefactory-project-zuul[bot]
196368d89b Merge pull request #7736 from beeankha/rrule_module_minor_edits
Make Some Doc Edits in the rrule Collections Module

Reviewed-by: Ryan Petrello
             https://github.com/ryanpetrello
2020-07-28 16:27:22 +00:00
mabashian
8b2c98ffde Fixes console errors thrown about React state updates being be wrapped into act(...) on the job template add form 2020-07-28 12:08:40 -04:00
mabashian
1faaba4e6c Fixes console errors thrown about React state updates being be wrapped into act(...) on the inventory form 2020-07-28 12:05:02 -04:00
Ryan Petrello
7938bf58d4 Merge pull request #4485 from ryanpetrello/more-cred-failure-cleanup-372
properly obfuscate connection errors for credential lookup failure
2020-07-28 12:04:03 -04:00
beeankha
fe176a4f8c Match test playbook output to edited module output 2020-07-28 11:50:19 -04:00
mabashian
7e8d0b5883 Fixes console errors thrown about isValid on the workflow job template form 2020-07-28 11:49:17 -04:00
Ryan Petrello
91594a1ae8 properly obfuscate connection errors for credential lookup failure 2020-07-28 11:38:48 -04:00
mabashian
e6e79227e5 Fixes console errors thrown about isValid on the credential form 2020-07-28 11:26:48 -04:00
Ryan Petrello
b03b12163f Merge pull request #4486 from ryanpetrello/fix-372-unit-tests
pin pytest-forked to fix broken unit tests
2020-07-28 11:18:52 -04:00
Ryan Petrello
1c08206792 pin pytest-forked to fix broken unit tests 2020-07-28 11:16:52 -04:00
softwarefactory-project-zuul[bot]
3f0a8eb5bc Merge pull request #7633 from nixocio/ui_add_list_instance_group
Add feature list instance groups

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
             https://github.com/AlexSCorey
2020-07-28 14:57:02 +00:00
beeankha
95cf6aa6d0 Make minor edits to the rrule module 2020-07-28 10:36:52 -04:00
nixocio
c2b1209cf3 Add feature list instance groups
Add list and delete for instance groups/container groups.

See: https://github.com/ansible/awx/issues/7557
Also: https://github.com/ansible/awx/issues/7642
2020-07-27 16:51:34 -04:00
softwarefactory-project-zuul[bot]
7bec29bac7 Merge pull request #7726 from fosterseth/fix-helm-url
Update helm urls in install guide

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-27 18:55:40 +00:00
Seth Foster
053b7caf3a Update helm urls 2020-07-27 13:01:29 -04:00
softwarefactory-project-zuul[bot]
6b867e7d97 Merge pull request #7596 from nixocio/ui_set_strict_mode
Set React to Strict Mode

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-27 15:56:57 +00:00
softwarefactory-project-zuul[bot]
708244881c Merge pull request #7643 from AlanCoding/per_update_cache
Implement per-update cache for roles and collections

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-27 15:45:48 +00:00
Alan Rominger
967f3cc6a7 Merge pull request #4472 from AlanCoding/upgrade_vmware
Upgrade community.vmware for better error surfacing
2020-07-27 10:16:12 -04:00
softwarefactory-project-zuul[bot]
e1902b6fe1 Merge pull request #7713 from mabashian/fix-form-field-help
Fixes bug where help icon showed up beneath the form label

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-27 13:42:41 +00:00
Vadiem Janssens
36316ae9a5 Fix tests
Signed-off-by: Vadiem Janssens <info@vadiemjanssens.nl>
2020-07-26 20:56:40 +02:00
Vadiem Janssens
8e4edca85d Replace itemCount with DataListToolbar pagination 2020-07-26 20:33:43 +02:00
Vadiem Janssens
30a499b785 Add item count to DataListToolbar
Signed-off-by: Vadiem Janssens <info@vadiemjanssens.nl>
2020-07-26 20:33:43 +02:00
softwarefactory-project-zuul[bot]
68c62d74f6 Merge pull request #7671 from jlmitch5/pfUpdate0920
update pf to 09 2020 release

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-23 20:57:07 +00:00
Ryan Petrello
847d6c65bd Merge pull request #4480 from ryanpetrello/372-cred-plugin-30x
properly report 30x errors on credential plugin tests
2020-07-23 15:27:27 -04:00
Ryan Petrello
f29e7b9c81 properly report 30x errors on credential plugin tests 2020-07-23 14:50:35 -04:00
Ryan Petrello
32831794ee Merge pull request #4477 from ryanpetrello/372-signal-deadlock
force worker processes to have a different signal handler from the parent
2020-07-23 12:21:44 -04:00
Jeff Bradberry
6b82ae46bc Force worker processes to have a different signal handler from the parent
Situations have come up where the 5+ minute kill signal for
run_task_manager is emitted to the worker process running it, but
since the worker improperly inherited the AWXConsumerBase().stop()
handler a deadlock ultimately was triggered on the database
connection.
2020-07-23 12:09:59 -04:00
Ryan Petrello
26660fa82e Merge pull request #4464 from ryanpetrello/named-url-vuln-372
update the named URL code to properly return 404 vs 403
2020-07-23 12:07:33 -04:00
mabashian
45286ebf41 Fixes bug where help icon showed up beneath the form label. I believe the labelIcon prop was added in a recent update of PF and is what we should be using. 2020-07-23 10:43:10 -04:00
softwarefactory-project-zuul[bot]
71d3fd3dbc Merge pull request #7698 from geerlingguy/pg-data-use-default-path
Use default path for pgdata volume in docker-compose template

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-23 13:02:53 +00:00
softwarefactory-project-zuul[bot]
6527d23b42 Merge pull request #7696 from AmadeusITGroup/fix_invalid_quote_filter
Installer: remove quote filter from docker_registry_password

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-23 13:00:52 +00:00
nixocio
1b767daaf6 Update wording to equal mock up
Update wording used for 'Job Templates' and 'Credential Types' to be
equal mock up.

See: https://tower-mockups.testing.ansible.com/patternfly/cred-types/cred-types/
Also: https://tower-mockups.testing.ansible.com/patternfly/templates/templates/
2020-07-22 14:00:24 -04:00
Ryan Petrello
860183f178 update the named URL code to properly return 404 vs 403 2020-07-22 12:15:34 -04:00
softwarefactory-project-zuul[bot]
3e753a7315 Merge pull request #7702 from ansible/fix-broken-offline-builds
Fix broken offline builds

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-22 13:22:19 +00:00
Stefan Jakobs
58da3df03e Change Dockerfile to copy custom venv 2020-07-22 14:00:05 +02:00
Shane McDonald
606296f68b Fix broken offline builds 2020-07-21 18:19:51 -04:00
Jeff Geerling
06fd131637 Use default path for pgdata volume in docker-compose template 2020-07-21 15:35:24 -05:00
softwarefactory-project-zuul[bot]
cf6c36ecab Merge pull request #7697 from nixocio/ui_small_refactor_credential_type_tests
Small update CredentialTypeList

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-21 20:17:23 +00:00
nixocio
fc9f1a3518 Small update CredentialTypeList
Small update CredentialTypeList. Update naming of function to
`deleteCredentialTypes`.
2020-07-21 15:50:43 -04:00
Philip DOUGLASS
ab20b5bd10 Installer: remove quote filter from docker_registry_password
The docker_registry_password var isn't interpolated by the shell, so
it shouldn't be quoted

Fixes: #7695
Signed-off-by: Philip DOUGLASS <philip.douglass@amadeus.com>
2020-07-21 15:33:42 -04:00
AlanCoding
0e8f30a4a2 Upgrade community.vmware for better error surfacing 2020-07-21 13:03:24 -04:00
AlanCoding
ddb8c93f17 Fix log message 2020-07-21 11:21:21 -04:00
AlanCoding
425c70826f code style edit, always use cache_id as property in tasks 2020-07-21 10:50:13 -04:00
AlanCoding
8195bd7386 Remove job pre-creation of content folders 2020-07-20 19:45:22 -04:00
AlanCoding
300d54864d Remove project update vars no longer used 2020-07-20 19:45:21 -04:00
AlanCoding
fefab89815 Integrate content caching with existing task logic
Revert the --force flags

use the update id as metric for role caching

Shift the movement of cache to job folder from rsync task to python

Only install roles and collections if needed

Deal with roles and collections for jobs without sync
Skip local copy if roles or collections turned off

update docs for content caching

Design pivot - use empty cache dir to indicate lack of content

Do not cache content if we did not install content

Test changes to allay concerns about reliability of local_path

Do not blow away cache for SCM inventory updates
2020-07-20 19:45:21 -04:00
Bill Nottingham
72848fa097 Remove the cache when delete-on-update is set 2020-07-20 19:45:20 -04:00
Bill Nottingham
85ec3dd5c4 Force install if doing a manual sync.
Requirements may be unversioned.
2020-07-20 19:45:20 -04:00
Bill Nottingham
98de4cb35f Adjust pathing to the proper location. 2020-07-20 19:45:20 -04:00
Bill Nottingham
dab7889715 Don't try and install content if there aren't any requirements expecting it 2020-07-20 19:45:19 -04:00
Bill Nottingham
95e69124af Also download roles/collections during the sync job
Since we're writing into a per-revision cache, we can do this easily now.
2020-07-20 19:45:19 -04:00
Bill Nottingham
1f4c46d873 Invalidate the cache on a new project revision 2020-07-20 19:45:18 -04:00
Bill Nottingham
d272ee3521 Cache downloaded roles & collections
Populate the cache the first time the job is run for a revision
that needs them, and for future runs for that revision just
copy it into the private directory.

Delete the cache on project deletion.
2020-07-20 19:45:15 -04:00
softwarefactory-project-zuul[bot]
bedbafe0f9 Merge pull request #7613 from keithjgrant/6622-template-list-websockets
Add websocket support to TemplateList

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-20 20:19:57 +00:00
softwarefactory-project-zuul[bot]
676491134d Merge pull request #7620 from keithjgrant/6621-inventory-sources-sockets
Inventory sources websockets

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-20 20:18:51 +00:00
softwarefactory-project-zuul[bot]
b36c5d9209 Merge pull request #7652 from jakemcdermott/fix-7651
Check for required node version before build or install

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-20 19:54:21 +00:00
softwarefactory-project-zuul[bot]
7296415fd9 Merge pull request #7635 from tchellomello/user_API_created
Exposes created attribute via API for User django ORM

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-20 19:40:47 +00:00
John Mitchell
00b3ff6e51 update snapshot and tooltip test 2020-07-20 14:06:14 -04:00
John Mitchell
bfaa2abd31 update pf to 09 2020 release 2020-07-20 13:42:14 -04:00
Ryan Petrello
34be08d38e add tests for filtering User.created_by in the API 2020-07-20 11:28:32 -04:00
Jake McDermott
2992a5f5a4 Check node version before build or install 2020-07-20 09:13:43 -04:00
Marcelo Moreira de Mello
3803763c53 Exposes the User.created attribute via API
Signed-off-by: Marcelo Moreira de Mello <tchello.mello@gmail.com>
2020-07-17 15:47:17 -04:00
softwarefactory-project-zuul[bot]
f0aec0d444 Merge pull request #7641 from josephpisciotta/devel
Remove the NodePort type for the web svc.

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-17 19:01:27 +00:00
softwarefactory-project-zuul[bot]
765595fd11 Merge pull request #7629 from ryanpetrello/k8s-creds
add the ability to specify K8S/OCP credentials on a Job Template

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-17 17:07:46 +00:00
Joseph Pisciotta
75c6c068a7 Remove the NodePort type for the web svc. 2020-07-17 12:51:29 -04:00
softwarefactory-project-zuul[bot]
036780d337 Merge pull request #7559 from AlexSCorey/7513-SurveySelectAllBox
Removes unneeded select all checkbox in Survey List

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-16 22:39:41 +00:00
Phi|eas |ebada
a05aa20f24 Update updater.sh
I wrote this script a year ago and just realized that this sourcing won't work lol
2020-07-16 23:24:09 +02:00
softwarefactory-project-zuul[bot]
4db3cd0326 Merge pull request #7627 from jakemcdermott/fix-7512
Show grant and client type validation errors

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-16 21:00:29 +00:00
softwarefactory-project-zuul[bot]
2e07ac3c2c Merge pull request #7628 from jakemcdermott/fix-7511
Improve nav behavior

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-16 21:00:22 +00:00
softwarefactory-project-zuul[bot]
77717b6134 Merge pull request #7631 from jakemcdermott/fix-5236
Use summary job_type on host list

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-16 19:40:36 +00:00
Jake McDermott
bf74aae80e Use summary job_type on host list 2020-07-16 14:10:55 -04:00
Alex Corey
496862592a fixes erroneous render 2020-07-16 12:59:58 -04:00
Alex Corey
ad536ec3d9 Removes commented out line 2020-07-16 12:59:52 -04:00
Alex Corey
bc69406f31 removes unneeded select all checkbox 2020-07-16 12:59:52 -04:00
Ryan Petrello
959b81aec5 refactor k8s credential injectors to properly handle verify=f 2020-07-16 12:43:10 -04:00
Ryan Petrello
1a39cbc2f4 add tests for k8s credential usage in Job Templates 2020-07-16 12:22:11 -04:00
Ryan Petrello
715dc4ece8 add a license for ruamel.ordereddict (for openshift lib support) 2020-07-16 11:38:54 -04:00
Ryan Petrello
c44f8e9122 implement k8s credential selection in the new patternfly UI 2020-07-16 11:25:03 -04:00
Ryan Petrello
75a0382c31 show k8s credentials in the Job Template prompt on launch UI 2020-07-16 10:53:21 -04:00
Ryan Petrello
0b221a42c0 Add the ability to specify K8S/OCP credentials on a Job Template
see: https://github.com/ansible/awx/issues/5735
2020-07-15 17:44:07 -04:00
Jake McDermott
6f43462689 Improve nav behavior
* Use more selective route matching when determining if a nav item is
active

* Don't automatically collapse nav groups when user navigates to a
different group
2020-07-15 12:46:08 -04:00
Jake McDermott
d1a4f010b9 Show grant and client type validation errors 2020-07-15 12:05:51 -04:00
softwarefactory-project-zuul[bot]
79b95883a3 Merge pull request #7618 from jakemcdermott/update-deps-03
Fix most of this week's npm warnings

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-15 14:49:04 +00:00
Keith Grant
f1e3b4f4f0 add useWsInventorySources tests 2020-07-14 14:29:24 -07:00
Ryan Petrello
c410f1f344 Merge pull request #4458 from ryanpetrello/fifo-cred-plugin-hang-372
[3.7.2] remove the usage of create_temporary_fifo from credential plugins
2020-07-14 17:21:35 -04:00
Ryan Petrello
310a0f88e5 remove the usage of create_temporary_fifo from credential plugins
this resolves an issue that causes an endless hang on with Cyberark AIM
lookups when a certificate *and* key are specified

the underlying issue here is that we can't rely on the underyling Python
ssl implementation to *only* read from the fifo that stores the pem data
*only once*; in reality, we need to just use *actual* tempfiles for
stability purposes

see: https://github.com/ansible/awx/issues/6986
see: https://github.com/urllib3/urllib3/issues/1880
2020-07-14 16:24:03 -04:00
Keith Grant
4fca57dfd2 add ws support to inventory sources list 2020-07-14 11:43:59 -07:00
Jake McDermott
e89326dbf2 Fix vulnerable 2nd order dependency 2020-07-14 14:42:46 -04:00
softwarefactory-project-zuul[bot]
cd6df9299f Merge pull request #7286 from john-westcott-iv/lookup_plugins
Adding tower_api and tower_get_id lookup plugins

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-14 18:04:27 +00:00
softwarefactory-project-zuul[bot]
80a6d4a29d Merge pull request #7611 from ryanpetrello/host-recent-job-type
add job type to Host summary_fields.recent_jobs

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-14 14:04:58 +00:00
John Westcott IV
222e58dd34 Adding lookup to rrule plugin test logic for new tooling
This change is provided with the tower_api lookup plugin because the require tower_meta module is part of this commit
2020-07-14 09:38:26 -04:00
John Westcott IV
0be7d9b21a Removing redundant check 2020-07-14 09:38:26 -04:00
John Westcott IV
5a6c7a5788 Fixing copyrights and linting issues 2020-07-14 09:38:26 -04:00
John Westcott IV
3784f9515e More refinement of examples 2020-07-14 09:38:26 -04:00
John Westcott IV
6638d6c2bb Update examples 2020-07-14 09:38:26 -04:00
John Westcott IV
afbdeb5ff8 Fixing linting errors 2020-07-14 09:38:26 -04:00
John Westcott IV
381e9d2901 Reverting commit 81b192c3b0520be0897f95e2630edab295e6bf24, we should fail only if we are > max_objects 2020-07-14 09:38:26 -04:00
John Westcott IV
dd478af227 Overhaul of the testing suite 2020-07-14 09:38:26 -04:00
John Westcott IV
0424370d49 Revamp of the examples 2020-07-14 09:38:26 -04:00
John Westcott IV
1a4bb42ac5 When using return_ids send back a list of strings instead of ints.
When we used ints and passed this data into a nother call like:
    - name: Create a job template with a looked up credential from a folded lookup
      tower_job_template:
        name: "{{ job_template_name }}"
        credentials: >-
            {{ lookup(
                'awx.awx.tower_api',
                'credentials',
                query_params={ 'name' : credential_name },
                return_ids=True,
                expect_one=True,
                wantlist=True
            ) }}
        project: "{{ project_name }}"
        inventory: Demo Inventory
        playbook: hello_world.yml
        job_type: run
        state: present
      register: create_jt

Ansible would raise this warning:
[WARNING]: The value 30 (type int) in a string field was converted to '30' (type string). If this does not look like what you expect, quote the entire value to ensure it does not change.

Returning a list of strings prevents that.
2020-07-14 09:38:26 -04:00
John Westcott IV
fdb008fb8c Added note about exception if list view return is > max_objects 2020-07-14 09:38:26 -04:00
John Westcott IV
d793f0bc99 Making the count check >= instead of just > 2020-07-14 09:38:26 -04:00
John Westcott IV
a9c16a6c90 Fixing undefined variabe 2020-07-14 09:38:26 -04:00
Alan Rominger
34c23caed3 make lookup plugin compatible with ansible.tower namespace (#9) 2020-07-14 09:38:26 -04:00
AlanCoding
8239232d4d Delete the tower_get_id plugin and tests 2020-07-14 09:38:26 -04:00
AlanCoding
30ff112c87 Pull in functionality from lookup plugin get_id into tower_api itself 2020-07-14 09:38:26 -04:00
John Westcott IV
f4454a6c93 Make tower_api a generic GET'er 2020-07-14 09:38:26 -04:00
John Westcott IV
44a3057d16 Initial fixes from github comments 2020-07-14 09:38:26 -04:00
John Westcott IV
3c02265986 Fixing doc issue 2020-07-14 09:38:26 -04:00
beeankha
6715ea493f Fix documentation in api lookup plugin, fix typos in integration tests 2020-07-14 09:38:26 -04:00
John Westcott IV
96ae3268a5 Fixing linting issues 2020-07-14 09:38:26 -04:00
John Westcott IV
6d626b3793 Adding tower_api and tower_get_id lookup plugins 2020-07-14 09:38:26 -04:00
Keith Grant
350c585499 update useWsTemplates to use useWebsocket hook 2020-07-13 13:32:13 -07:00
Keith Grant
b76783791a add useWsTemplates tests 2020-07-13 13:27:38 -07:00
Keith Grant
981c9527b2 add template list websocket support 2020-07-13 13:27:38 -07:00
softwarefactory-project-zuul[bot]
09dcb91c09 Merge pull request #7598 from keithjgrant/6618-websocket-inventories-list
Add Websocket support to inventories list

Reviewed-by: Daniel Sami
             https://github.com/dsesami
2020-07-13 20:25:49 +00:00
Ryan Petrello
3ef07ee5f7 Merge pull request #4447 from ryanpetrello/372-master-main-links
fixed broken UI links
2020-07-13 15:49:11 -04:00
Gabe Muniz
1edae24644 fixed broken UI links 2020-07-13 15:36:07 -04:00
softwarefactory-project-zuul[bot]
d4b0251845 Merge pull request #7615 from gamuniz/remove_broken_links
fixed broken UI links

Reviewed-by: awxbot
             https://github.com/awxbot
2020-07-13 19:31:56 +00:00
Gabe Muniz
ff90e64448 fixed broken UI links 2020-07-13 14:53:34 -04:00
Ryan Petrello
ab11d3188d refactor the job type name into a single property 2020-07-13 09:43:43 -04:00
Ryan Petrello
f51774c06e add job type to Host summary_fields.recent_jobs
see: https://github.com/ansible/awx/issues/5236
2020-07-13 09:02:04 -04:00
softwarefactory-project-zuul[bot]
83458711cd Merge pull request #7605 from wenottingham/jobberry-fields-forever
Add artifacts field of jobs to the allowed list for notifications

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-10 21:01:08 +00:00
Bill Nottingham
46734f5c10 Add artifacts field of jobs to the allowed list for notifications 2020-07-10 16:34:25 -04:00
softwarefactory-project-zuul[bot]
b8b0812e13 Merge pull request #7604 from philipsd6/enable-html-custom-login-info
Update help_text for Custom Login Info to show support for HTML

Reviewed-by: awxbot
             https://github.com/awxbot
2020-07-10 19:08:48 +00:00
Keith Grant
38e0968690 useWsInventories cleanup 2020-07-10 08:33:35 -07:00
Philip Douglass
1ec2bd7ed2 Update help_text for Custom Login Info to show support for HTML
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-07-10 10:11:02 -04:00
softwarefactory-project-zuul[bot]
d10fdda453 Merge pull request #7575 from weltamdraht/add_extra_hosts
Adding inventory variable to set "extra_hosts" in generated compose file

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-10 14:05:26 +00:00
Jake McDermott
2737cded72 Merge pull request #4442 from jakemcdermott/fix-4440
[3.7.2] Include instance_id in host edit request
2020-07-10 09:43:50 -04:00
Jake McDermott
4f2ce90137 Include instance_id in host edit request 2020-07-10 09:39:54 -04:00
softwarefactory-project-zuul[bot]
d4305f734a Merge pull request #7585 from philipsd6/enable-html-custom-login-info
Safely enable HTML in Custom Login Info

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-10 12:57:17 +00:00
weltamdraht
347529a0cf Adding inventory variable to set "extra_hosts" in generated compose file
Signed-off-by: weltamdraht <andreas.aderhold@dwd.de>
2020-07-10 13:25:07 +02:00
softwarefactory-project-zuul[bot]
e4470f1200 Merge pull request #7592 from jakemcdermott/fix-7591
Include instance_id in host edit request

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-09 21:17:18 +00:00
Keith Grant
f225df1acd add useWsInventories tests 2020-07-09 14:12:56 -07:00
nixocio
01f210e392 Set React to Strict Mode
Set React to Strict Mode.

See: https://reactjs.org/docs/strict-mode.html
2020-07-09 15:37:19 -04:00
Keith Grant
455e018099 refactor shared WS logic into useWebsocket hook 2020-07-09 10:14:03 -07:00
Philip Douglass
4c98a1cb20 Set white-space style based on customLoginInfoIsHTML
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-07-09 18:56:19 +02:00
Philip Douglass
202a68aca0 Add customLoginInfoIsHTML test
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-07-09 18:56:19 +02:00
Philip Douglass
29666bf3b6 Remove white-space: pre-wrap from loginModalNotice
Signed-off-by: Philip Douglass <philip.douglass@amadeus.com>
2020-07-09 18:56:19 +02:00
Jake McDermott
ddbe20d41b Include instance_id in host edit request 2020-07-09 11:27:45 -04:00
Ryan Petrello
140d9ae3ee Merge pull request #4429 from wenottingham/label-maker
Reintroduce label filtering
2020-07-09 09:00:57 -04:00
Keith Grant
84bea3d348 websockets: show live inventory source sync status 2020-07-08 15:20:42 -07:00
softwarefactory-project-zuul[bot]
d0ac028265 Merge pull request #7489 from nixocio/ui_issue_7326
Add edit credential types

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-08 20:53:09 +00:00
Ryan Petrello
7322e13436 add tests for clarified label permissions 2020-07-08 16:53:05 -04:00
softwarefactory-project-zuul[bot]
9065b29bd6 Merge pull request #7584 from ryanpetrello/jinja2-sandbox
use jinja2.sandbox for credential type injectors

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-08 20:53:02 +00:00
softwarefactory-project-zuul[bot]
dbdc856ed3 Merge pull request #7576 from ryanpetrello/instance-group-capabilities
show user capabilities for instance groups

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-08 20:05:55 +00:00
Ryan Petrello
1cf2f009ed prevent unsafe jinja from being saved in the first place for cred types
see: https://github.com/ansible/tower-security/issues/21
2020-07-08 15:48:58 -04:00
Ryan Petrello
2bdd83e029 use jinja2.sandbox for credential type injectors 2020-07-08 15:48:47 -04:00
softwarefactory-project-zuul[bot]
e91395d517 Merge pull request #7497 from AlexSCorey/ApplicationTokens
Adds Application Token List with delete functionality

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-08 19:42:17 +00:00
softwarefactory-project-zuul[bot]
19115a157e Merge pull request #7555 from AlexSCorey/7433-UserTokensAdd
Adds User TokenAdd Functionality

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-08 19:33:06 +00:00
Alex Corey
a9d4046ec5 Adds Application Token List with delete functionality 2020-07-08 15:13:31 -04:00
Alex Corey
bbc4522063 Adds User TokenAdd Functionality 2020-07-08 14:47:23 -04:00
softwarefactory-project-zuul[bot]
fb3271da3c Merge pull request #7578 from squidboylan/raise_sleep_timeout
Raise job length for testing job wait

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-08 18:36:42 +00:00
Caleb Boylan
56d800e851 Raise job length for testing job wait 2020-07-08 09:28:19 -07:00
Ryan Petrello
319308193c show user capabilities for instance groups 2020-07-08 09:17:55 -04:00
Keith Grant
15ae0976dd add sync status indicator to inventory list 2020-07-07 16:37:08 -07:00
softwarefactory-project-zuul[bot]
f121dc59f6 Merge pull request #7529 from nixocio/ui_issue_7471
Add stub files for Instance Groups

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-07 21:12:23 +00:00
softwarefactory-project-zuul[bot]
f050b73560 Merge pull request #7568 from jakemcdermott/fix-7534
Update to ansible/angular-scheduler#v0.4.4

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-07 19:43:00 +00:00
Jake McDermott
bd624508e3 Update to ansible/angular-scheduler#v0.4.4 2020-07-07 15:04:07 -04:00
softwarefactory-project-zuul[bot]
b9fb9389e6 Merge pull request #7537 from jakemcdermott/fix-7483
Fix custom credential field validation

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-07 19:02:53 +00:00
softwarefactory-project-zuul[bot]
bf28bdecb7 Merge pull request #7540 from keithjgrant/6618-websocket-projects-list
Add Websocket support to Projects List

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-07 19:00:10 +00:00
softwarefactory-project-zuul[bot]
23cab61408 Merge pull request #7444 from AlexSCorey/7412-OrganizationEditButton
Adds edit icon to the OrganizationTeams list 

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-07 17:32:34 +00:00
nixocio
777d44ec34 Add edit credential types
Add feature to edit credential types.

See: https://github.com/ansible/awx/issues/7326
2020-07-07 13:30:54 -04:00
Ryan Petrello
bc14e995fd Merge pull request #4434 from ryanpetrello/jinja-injector-sandbox-validation
prevent unsafe jinja from being saved in the first place for cred types
2020-07-07 12:47:15 -04:00
Ryan Petrello
61d3a765ee prevent unsafe jinja from being saved in the first place for cred types
see: https://github.com/ansible/tower-security/issues/21
2020-07-07 10:59:14 -04:00
Ryan Petrello
f943277ef0 Merge pull request #4433 from ghjm/webhook_error_detail
Error detail in webhook and credential tests
2020-07-07 10:35:21 -04:00
softwarefactory-project-zuul[bot]
9a6da9cea7 Merge pull request #7552 from ikke-t/fix-7545
Allow anyone to start awx and awx_task [#7545]

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-07 14:34:16 +00:00
Ilkka Tengvall
8b4b1f5f81 Allow anyone to start awx and awx_task [#7545] 2020-07-07 15:04:23 +03:00
Graham Mainwaring
5a96af79d4 Reduce error detail in credential lookups 2020-07-06 21:41:28 -04:00
Graham Mainwaring
b7f37d5e26 Reduce error detail in webhook notification 2020-07-06 21:17:21 -04:00
Graham Mainwaring
d14aee70a1 Don't follow redirects in credential plugins 2020-07-06 17:18:30 -04:00
Ryan Petrello
8aa11f4848 Merge pull request #4430 from ryanpetrello/jinja2-injector-sandbox
use jinja2.sandbox for credential type injectors
2020-07-06 15:21:21 -04:00
Jake McDermott
05799d9795 Avoid non-unique field name collisions
Custom credentials can have input fields named 'name', 'organization',
'description', etc. Underscore these variables to make collisions
less likely to occur.
2020-07-06 14:08:53 -04:00
Jake McDermott
ea4b435ea7 Ignore required field validation for booleans 2020-07-06 14:08:46 -04:00
Ryan Petrello
2f1b4d81e1 use jinja2.sandbox for credential type injectors 2020-07-06 13:50:33 -04:00
Bill Nottingham
a88f03b372 Reintroduce label filtering
Labels are visible if you have a role on the org they are in, or
on a job template they're attached to.
2020-07-06 13:50:00 -04:00
softwarefactory-project-zuul[bot]
dbfb1780f1 Merge pull request #7553 from jakemcdermott/fix-7530
Fix self-closing tags for jquery 3.5 compat

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-06 17:01:46 +00:00
Jake McDermott
a89eff3c1a Remove self-closing tags
jquery doesn't like self-closing tags. jquery doesn't like anything.
2020-07-06 09:34:50 -04:00
JoelKle
699f186890 Fixed a bug, where the redis.conf first would be stored with mod 0600
and in the next task changed to 0666.
This has broke the ability to rerun the playbook.

Signed-off-by: JoelKle <34544090+JoelKle@users.noreply.github.com>
2020-07-03 08:59:28 +02:00
JoelKle
caab751215 Added the ability, to set the broadcast_websocket_secret variable.
This is nessesary if you would like to rerun the playbook.

Signed-off-by: JoelKle <34544090+JoelKle@users.noreply.github.com>
2020-07-03 08:59:28 +02:00
Keith Grant
2e3e1be22a add useWsProjects tests 2020-07-02 15:42:51 -07:00
softwarefactory-project-zuul[bot]
a74fbd6578 Merge pull request #7432 from elyezer/update-module-tests
Only pass either user or org on modules test

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-02 21:01:00 +00:00
Keith Grant
803ea322d6 update path to useThrottle in tests 2020-07-02 10:51:57 -07:00
Keith Grant
9657117941 add ProjectList websocket support 2020-07-02 09:29:56 -07:00
softwarefactory-project-zuul[bot]
b56c753613 Merge pull request #7525 from ryanpetrello/encrypted-keyword
don't allow users to specify $encrypted$ for encrypted credential fields

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-02 15:47:33 +00:00
softwarefactory-project-zuul[bot]
8b3dfae717 Merge pull request #7501 from ansible/jakemcdermott-no-modules-for-project-root
Delete node_modules in project root

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-02 00:36:56 +00:00
softwarefactory-project-zuul[bot]
8f50514b3d Merge pull request #7502 from nixocio/ui_lingui_prod
Add extraction of strings to be translated as part of build process

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-01 23:09:05 +00:00
Keith Grant
bdb97c173b move useThrottle to utils 2020-07-01 15:52:06 -07:00
nixocio
24f86cd0d1 Add stub files for Instance Groups
Add stub files for Instance Groups. Routing system, and screens layout.

closes: https://github.com/ansible/awx/issues/7471
2020-07-01 17:27:08 -04:00
softwarefactory-project-zuul[bot]
6e651ce275 Merge pull request #7519 from shanemcd/the-ol-copy-paste
Copy over some downstream changes

Reviewed-by: Shane McDonald <me@shanemcd.com>
             https://github.com/shanemcd
2020-07-01 20:22:51 +00:00
Alex Corey
650a97e989 Adds edit icon to the OrganizationTeams list and renames some files. 2020-07-01 16:08:41 -04:00
Ryan Petrello
1434e5812f don't allow users to specify $encrypted$ for encrypted credential fields
this keyword only has value when you _update_ an existing credential
2020-07-01 15:53:09 -04:00
Shane McDonald
e26387cdf3 Remove references to old images 2020-07-01 14:57:48 -04:00
Shane McDonald
7f81f530fa Copy over downstream change
Allows users to specify pg_username that has uppercase letters to restore succesfully
2020-07-01 14:40:38 -04:00
nixocio
fab94902a0 Add extraction of strings to be translated as part of build process
Add extraction of strings to be translated as part of build process for
ui_next.

Also, sets the source locale. See: https://lingui.js.org/tutorials/cli.html#configuring-source-locale

closes: https://github.com/ansible/awx/issues/7451
2020-07-01 12:05:37 -04:00
softwarefactory-project-zuul[bot]
e3e69b4c6b Merge pull request #7499 from nixocio/ui_translations_issues
Add strings to be translated

Reviewed-by: Kersom
             https://github.com/nixocio
2020-07-01 15:31:59 +00:00
softwarefactory-project-zuul[bot]
642803e471 Merge pull request #7484 from jakemcdermott/update-deps
Remove unused dependencies

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-01 15:14:58 +00:00
softwarefactory-project-zuul[bot]
26f2f159dd Merge pull request #7396 from AlexSCorey/7235-ApplicationsAddEdit
Adds Application edit functionality

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-07-01 15:08:23 +00:00
Jake McDermott
e962933148 Delete node_modules in project root 2020-07-01 10:51:29 -04:00
Alex Corey
169868b927 Adds edit functionality 2020-07-01 10:37:27 -04:00
nixocio
e0ebd5d46c Add strings to be translated
To identify those strings `npm run extract-strings`.
2020-07-01 10:22:45 -04:00
softwarefactory-project-zuul[bot]
d1f9f4dc86 Merge pull request #7457 from marshmalien/smart-inventory-detail
Add smart inventory detail view

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-30 21:45:17 +00:00
softwarefactory-project-zuul[bot]
5c12022529 Merge pull request #7479 from chris93111/patch-2
correction inventory endpoint tower_workflow_job_template_node.py

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-30 17:10:25 +00:00
softwarefactory-project-zuul[bot]
d8f6ea3fe8 Merge pull request #7485 from ryanpetrello/words-matter
replace certain terms with more inclusive language

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-30 17:00:58 +00:00
softwarefactory-project-zuul[bot]
719a4f8aad Merge pull request #7436 from AlexSCorey/7419-UserTokens
Adds Tokens List

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-30 16:51:56 +00:00
Jake McDermott
7bac7abd67 Fix variable names 2020-06-30 12:34:14 -04:00
Alex Corey
776ee43d90 Fixes missing name bug 2020-06-30 12:22:19 -04:00
Ryan Petrello
78229f5871 replace certain terms with more inclusive language
see: https://www.redhat.com/en/blog/making-open-source-more-inclusive-eradicating-problematic-language
2020-06-30 10:49:19 -04:00
Jake McDermott
b4198204a7 Add install step 2020-06-30 10:10:52 -04:00
Jake McDermott
86c1f4d772 Co-locate deps in file 2020-06-30 08:58:37 -04:00
Jake McDermott
e10fb71f93 Move react-scripts to dev dependencies 2020-06-30 08:58:32 -04:00
Jake McDermott
bae50e38da Remove unused dependencies 2020-06-30 08:58:27 -04:00
softwarefactory-project-zuul[bot]
66739a52d6 Merge pull request #7342 from keithjgrant/6618-job-list-ws
Jobs List websockets

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-29 21:51:14 +00:00
softwarefactory-project-zuul[bot]
f060002289 Merge pull request #7478 from ansible/jakemcdermott-fixreadme
Fix unescaped README code block

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-29 21:20:18 +00:00
chris93111
b6883ab64e Update tower_workflow_job_template_node.py
correction to lookup inventory
2020-06-29 22:58:18 +02:00
Jake McDermott
9dadb96d45 Fix unescaped README code block 2020-06-29 16:50:44 -04:00
Keith Grant
5304792949 update useWsJobs tests 2020-06-29 13:49:58 -07:00
Keith Grant
a3e0ae66ba clean up sorting order discrepancies 2020-06-29 13:49:58 -07:00
Keith Grant
9705f7bec6 sort jobs list by selection sort option 2020-06-29 13:49:58 -07:00
Keith Grant
5610309a88 fix sorting jobs by finished date 2020-06-29 13:49:58 -07:00
Keith Grant
25fe090e67 delete un-workable test for useThrottle 2020-06-29 13:49:58 -07:00
Keith Grant
a1f257bd4a fix joblist updating completed jobs lists 2020-06-29 13:49:58 -07:00
Keith Grant
638a6fdaa1 remove extra logging from JobList tests 2020-06-29 13:49:58 -07:00
Keith Grant
b4a6749699 refactor getJobsById into useWsJobs hook 2020-06-29 13:49:58 -07:00
Keith Grant
e50576c820 failed attempt at useThrottle tests 2020-06-29 13:49:58 -07:00
Keith Grant
0bedd6fbd8 mock websockets; test useWsJobs 2020-06-29 13:49:58 -07:00
Keith Grant
48977e50df change jobs debounce to throttle; prevent duplicate rows 2020-06-29 13:49:58 -07:00
Keith Grant
7aa8495d1a debounce fetching of individual jobs 2020-06-29 13:49:58 -07:00
Keith Grant
58b954df3e fetch individual jobs based on websocket messages 2020-06-29 13:49:58 -07:00
Keith Grant
38079b2ad5 don’t add still running jobs to some jobs lists 2020-06-29 13:49:58 -07:00
Keith Grant
b055d34139 update jobs in list based on websockets 2020-06-29 13:49:58 -07:00
Keith Grant
f2641de260 rough out jobs list websockets 2020-06-29 13:49:58 -07:00
Keith Grant
aa12e323b4 ignore .env.local file 2020-06-29 13:49:58 -07:00
softwarefactory-project-zuul[bot]
65a8a656f7 Merge pull request #7469 from jakemcdermott/fix-7454
Use a proxy config that works

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-29 20:21:26 +00:00
Alex Corey
73bb539b16 Adds Tokens List 2020-06-29 16:17:10 -04:00
softwarefactory-project-zuul[bot]
6e99b1cf85 Merge pull request #7452 from nixocio/ui_issue_7430
Add Crendential Type Details

Reviewed-by: Daniel Sami
             https://github.com/dsesami
2020-06-29 20:06:05 +00:00
Jake McDermott
bde1ff1187 Use a proxy config that works 2020-06-29 15:51:51 -04:00
nixocio
bd660254a5 Add Crendential Type Details
Add credential type Details

See: https://github.com/ansible/awx/issues/7430
2020-06-29 15:02:38 -04:00
softwarefactory-project-zuul[bot]
879ab50a12 Merge pull request #7426 from nixocio/ui_issue_7325
Add feature to add Credential Type

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-29 18:54:27 +00:00
nixocio
ad10f3581e Add feature to add Credential Type
Add feature to add Credential Type.

See: https://github.com/ansible/awx/issues/7325
2020-06-29 13:39:57 -04:00
Marliana Lara
eec2177315 Add unit tests that check activity stream is hidden appropriately 2020-06-29 13:20:44 -04:00
softwarefactory-project-zuul[bot]
f5d38f57d4 Merge pull request #7375 from vjanssens/5929-consistent-subforms-in-job-template-forms
Use consistent layout for subforms in job/template forms

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-29 17:15:23 +00:00
Vadiem Janssens
3f33f1c97d Fix failing test
Signed-off-by: Vadiem Janssens <info@vadiemjanssens.nl>
2020-06-29 12:08:48 -04:00
Vadiem Janssens
f9039703ee Remove enableWebhooks conditional in WebhookSubForm
Signed-off-by: Vadiem Janssens <info@vadiemjanssens.nl>
2020-06-29 12:08:48 -04:00
Vadiem Janssens
be33627755 Remove webhook_key and webhook_url from JT form payload
Signed-off-by: Vadiem Janssens <info@vadiemjanssens.nl>
2020-06-29 12:08:48 -04:00
Vadiem Janssens
c9cfaf65a0 Add headingLevels to Title, minor improvements
Signed-off-by: Vadiem Janssens <info@vadiemjanssens.nl>
2020-06-29 12:08:48 -04:00
Vadiem Janssens
12b87fca8c Use consistent layout for subforms in job/template forms
Signed-off-by: Vadiem Janssens <info@vadiemjanssens.nl>
2020-06-29 12:08:48 -04:00
Marliana Lara
b5bbfaab11 Add smart inv detail 2020-06-29 11:30:10 -04:00
softwarefactory-project-zuul[bot]
8ea31d8cdd Merge pull request #7462 from 90er/patch-2
Update ISSUES.md

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-29 13:20:02 +00:00
softwarefactory-project-zuul[bot]
5ae7aa7503 Merge pull request #7461 from 90er/patch-1
Update INSTALL.md

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-29 13:18:45 +00:00
90er
c89277358f Update ISSUES.md
Fixed typo
2020-06-29 09:16:06 +02:00
90er
7e2b3684e2 Update INSTALL.md
Fix typo
2020-06-29 09:11:45 +02:00
softwarefactory-project-zuul[bot]
c7d9d941e3 Merge pull request #7119 from thedoubl3j/hostnogroup
added change so that groups and host names cannot share the same name

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-26 20:19:53 +00:00
softwarefactory-project-zuul[bot]
5b9c19df8f Merge pull request #7115 from nixocio/ui_next_integration
UI next integration

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-26 19:42:30 +00:00
Jake Jackson
30757f8289 moved logic to the validate function and fixed tests accordingly 2020-06-26 15:04:48 -04:00
Jake Jackson
606d4e0ea2 added change so that groups and host names cannot share the same name in the same inventory. added tests to validate 2020-06-25 11:25:21 -04:00
Jake McDermott
1df91eece1 Add devel make targets for ui_next 2020-06-25 10:22:07 -04:00
Jake McDermott
01b8087cb3 Align prod and dev routing 2020-06-25 08:56:21 -04:00
nixocio
aef382862c Update NavItem to link to new basename
Update NavItem to link to the new basename, `next`. Thus avoiding to
redirec to the old ui.

See: https://www.patternfly.org/v4/documentation/react/components/nav
2020-06-25 08:56:19 -04:00
Jake McDermott
41d8edf94a Align imports to django collectstatic locations
Co-authored-by: nixocio <nixocio@gmail.com>
2020-06-25 08:56:11 -04:00
Jake McDermott
ddadf332cc Create static dir during bootstrap
Co-authored-by: nixocio <nixocio@gmail.com>
2020-06-25 08:56:07 -04:00
Jake McDermott
12a22d2442 Add basic django app and file serving for ui_next 2020-06-25 08:55:56 -04:00
softwarefactory-project-zuul[bot]
fa53cdf329 Merge pull request #7431 from ryanpetrello/bottleneck
add a tool for discovering which tasks/hosts are slow for a JT 

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-24 21:32:40 +00:00
softwarefactory-project-zuul[bot]
5445a3b567 Merge pull request #7308 from AlanCoding/in_place_everything
Allow for SCM installs of the AWX collection

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-24 19:41:43 +00:00
softwarefactory-project-zuul[bot]
2e37ffdb15 Merge pull request #6690 from john-westcott-iv/modify_tower_cred_type_for_token
Modifying tower credential type to include an oauth otken

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-24 16:55:25 +00:00
AlanCoding
3b5640aca3 fix test 2020-06-24 10:41:41 -04:00
softwarefactory-project-zuul[bot]
038688ca48 Merge pull request #7355 from AlexSCorey/ApplicationDetails
Adds application details view

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-24 14:37:21 +00:00
Elyézer Rezende
fb5d876b9b Only pass either user or org on modules test 2020-06-24 10:29:19 -04:00
Ryan Petrello
a62047809f update awx-manage bottleneck's help text 2020-06-24 10:25:09 -04:00
Ryan Petrello
b1fcc0578c default awx-manage bottleneck --threshold to 30s 2020-06-24 10:23:01 -04:00
Ryan Petrello
dd42f6351b minor refactoring of awx-manage bottleneck 2020-06-24 10:19:26 -04:00
Alex Corey
fad4b3ca5a Adds application details view 2020-06-24 10:00:12 -04:00
Ryan Petrello
ce65f994dc refactor some timedelta formatting in awx-manage bottleneck 2020-06-24 09:56:23 -04:00
Ryan Petrello
5532760ccf respect --no-color in awx-manage bottleneck 2020-06-24 09:52:30 -04:00
Ryan Petrello
21ea7eb5dc add the name of the task to awx-manage bottleneck output 2020-06-24 09:44:39 -04:00
Ryan Petrello
b01ac1bfa6 add support to the bottleneck script for configuring history size 2020-06-24 09:22:53 -04:00
John Westcott IV
f091de438e Adding help text 2020-06-24 09:14:30 -04:00
John Westcott IV
8a25f385e4 Modifying tower credential type to include an oauth otken 2020-06-24 09:14:30 -04:00
Ryan Petrello
180ed4cd3d add a tool for discovering which tasks/hosts are slow for a JT
this tool looks at the most recent jobs for a specific job template and
attempts to discover the _slowest_ tasks and hosts

$ awx-manage bottleneck --template N
$ awx-manage bottleneck --template N --threshold 1 --ignore yum
$ awx-manage bottleneck --template N --ignore pause --ignore yum
2020-06-24 08:59:48 -04:00
softwarefactory-project-zuul[bot]
c1bbeadf8d Merge pull request #7427 from ryanpetrello/awxkit-install
update instructions and metadata for awxkit/cli installs

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-23 22:23:56 +00:00
Ryan Petrello
b6c210ee97 update instructions and metadata for awxkit/cli installs 2020-06-23 17:53:14 -04:00
softwarefactory-project-zuul[bot]
f4514873cd Merge pull request #7425 from ghjm/no_traceback_on_keyboardinterrupt
Don't traceback on KeyboardInterrupt

Reviewed-by: awxbot
             https://github.com/awxbot
2020-06-23 20:45:19 +00:00
softwarefactory-project-zuul[bot]
2c59e83beb Merge pull request #7250 from nixocio/ui_issue_6810
Remove style overrides from Lookup component

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-23 20:39:58 +00:00
Graham Mainwaring
29da0abfc1 Don't traceback on KeyboardInterrupt 2020-06-23 16:14:02 -04:00
nixocio
14b2bd3445 Remove style overrides from Lookup component
Remove style overrides from Lookup component. Also, update related
tests.

closes: https://github.com/ansible/awx/issues/6810
2020-06-23 16:09:56 -04:00
softwarefactory-project-zuul[bot]
77ecb7b7d5 Merge pull request #7424 from ryanpetrello/changelog-tweak
minor CHANGELOG verbiage tweak

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-23 20:08:13 +00:00
Ryan Petrello
a9938c0e64 minor CHANGELOG verbiage tweak 2020-06-23 15:33:22 -04:00
softwarefactory-project-zuul[bot]
69589821ce Merge pull request #7420 from elyezer/update-credential-creation
Update awxkit credential creation

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-23 18:31:50 +00:00
softwarefactory-project-zuul[bot]
5ee865b051 Merge pull request #7416 from jakemcdermott/fix-cred-user-team-org-save
Don't send cred user with org

Reviewed-by: Elyézer Rezende
             https://github.com/elyezer
2020-06-23 16:49:21 +00:00
Elyézer Rezende
e80942f6cd Update awxkit credential creation
Does not have an organization by default. Let `create_payload` decide if
it should be automatically created or not. This will avoid having more
than one owner when either user or team is passed to `create`.
2020-06-23 12:32:51 -04:00
softwarefactory-project-zuul[bot]
d96cde91a3 Merge pull request #7418 from ryanpetrello/rsyslog-file-perm
properly write rsyslog configuration as 0640

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-23 16:01:26 +00:00
softwarefactory-project-zuul[bot]
0aa23a7d63 Merge pull request #7379 from AlanCoding/release_13
Bump AWX version, after notable inventory deprecation

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-23 15:55:57 +00:00
Jake McDermott
35e5c7f309 Don't send cred user with org 2020-06-23 11:38:08 -04:00
Ryan Petrello
8174516d3b properly write rsyslog configuration as 0640
see: https://github.com/ansible/tower/issues/4383
2020-06-23 11:25:39 -04:00
Ryan Petrello
d016de8103 adding a few CHANGELOG items 2020-06-23 11:24:22 -04:00
Jeff Bradberry
d8b9d48313 Add a note about import/export 2020-06-23 10:09:32 -04:00
softwarefactory-project-zuul[bot]
a669db989c Merge pull request #7305 from jlmitch5/pfv4upgrade
patternfly v4 upgrade

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-23 14:07:07 +00:00
John Mitchell
07ff3139d6 final fixes to tests and linting for pf v4 react upgrade 2020-06-23 09:37:50 -04:00
Alex Corey
88a38e30c3 Fixes some failing or skipped tests 2020-06-23 09:37:50 -04:00
John Mitchell
28e0ee8b7d fix a few tests with issues due to pf v4 react upgrade 2020-06-23 09:37:33 -04:00
John Mitchell
92937d1384 make divider show up between breadcrumbs 2020-06-23 09:37:20 -04:00
John Mitchell
9aab085b77 pin pf react core prerelease version to exact in package.json 2020-06-23 09:37:08 -04:00
John Mitchell
29bc6c8b48 make all detail view tabs full width - remove card close button pattern and move to back to resource pattern 2020-06-23 09:36:54 -04:00
John Mitchell
f161617755 add headingLevel prop to pf title components 2020-06-23 09:36:44 -04:00
John Mitchell
bb1687642c add in pre-release pf dep to fix issue with tests failing and fix the tests 2020-06-23 09:36:32 -04:00
John Mitchell
9f625d61f5 remove unused pf react token dependency 2020-06-23 09:36:20 -04:00
John Mitchell
173d058d88 make tabs of the project detail view card full width 2020-06-23 09:36:05 -04:00
John Mitchell
a5576d2ae9 fix issue where searchbar was always the mobile version at all widths 2020-06-23 09:35:53 -04:00
John Mitchell
957c0b31bf initial round of jest fixes post v4 update, more aria-labels for modals, more i18nHash filtering to rid warnings, fix of malformed ToolbarContent import, update snapshots 2020-06-23 09:35:36 -04:00
John Mitchell
826b03b78e make prettier adjustments to things the pf v4 codemod tool broke 2020-06-23 09:35:21 -04:00
John Mitchell
781869a436 adjust styled components for data toolbar overrides with new pf v4 names 2020-06-23 09:35:04 -04:00
John Mitchell
25916d983e update page header toolbar component names to new pf v4 names 2020-06-23 09:34:49 -04:00
John Mitchell
c762545c47 add aria label prop for alert modal pf component 2020-06-23 09:34:28 -04:00
John Mitchell
e49a99e0f6 after running pf code mod tool to auto update files to conform to v4 and a few manual tweaks 2020-06-23 09:34:04 -04:00
John Mitchell
475b733890 first pass of tweaks needed to compile pf v4 branch 2020-06-23 09:33:39 -04:00
John Mitchell
2a922861c3 update pf deps to v4 2020-06-23 09:33:25 -04:00
softwarefactory-project-zuul[bot]
2385e47ac3 Merge pull request #7392 from jladdjr/unpin_inventory_collections
unpin collections used for inventory plugins

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-22 16:44:05 +00:00
softwarefactory-project-zuul[bot]
729949e0d0 Merge pull request #7381 from elyezer/credentials-serializers-validation
Enforce single owner field when serializing creds

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-22 12:57:11 +00:00
Elyézer Rezende
37218e1695 Enforce single owner field when serializing creds
The CredentialSerializerCreate expect a single owner field according to
its help text but was not validating that. This makes it validate for a
single owner field when creating a Credential.
2020-06-21 11:31:35 -04:00
softwarefactory-project-zuul[bot]
e4eef82a39 Merge pull request #7369 from nixocio/ui_issue_7324
Add Credential Type List and Delete

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-19 19:51:50 +00:00
softwarefactory-project-zuul[bot]
bdd5efc2a9 Merge pull request #7390 from rooftopcellist/i18n_awx_translations_es_nl_6-19
UI translation strings for AWX 12.0.0+ for es and nl

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-19 19:47:02 +00:00
Christian Adams
f24b15dc2e Merge pull request #4415 from ansible/i18n_release_3.7.1_translations
UI translation strings for release_3.7.1 branch for es and nl
2020-06-19 15:25:33 -04:00
softwarefactory-project-zuul[bot]
a0413b7e0b Merge pull request #6125 from jbradberry/import-export
Import export

Reviewed-by: Jeff Bradberry
             https://github.com/jbradberry
2020-06-19 18:46:52 +00:00
Jim Ladd
71cfeda08f unpin collections used for inventory plugins
* unpins collections in requirements/collections_requirements.yml
2020-06-19 09:33:51 -07:00
softwarefactory-project-zuul[bot]
c5addd7c67 Merge pull request #7341 from AlexSCorey/7235-ApplicationsAddEdit
7235 applications add

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-19 15:36:04 +00:00
ansible-translation-bot
654675621c UI translation strings for AWX 12.0.0+ for es and nl 2020-06-19 10:41:53 -04:00
ansible-translation-bot
af199dff7a UI translation strings for release_3.7.1 branch for es and nl 2020-06-19 10:36:21 -04:00
nixocio
5e5aba59b0 Add Credential Type List and Delete
Add `Credential Type` List and Delete features.

See: https://github.com/ansible/awx/issues/7324
Also:https://github.com/ansible/awx/issues/7327
2020-06-19 09:50:59 -04:00
AlanCoding
0dbaf632dc Documentation updates 2020-06-19 09:49:37 -04:00
softwarefactory-project-zuul[bot]
89b087ffb6 Merge pull request #7389 from ryanpetrello/tmux-dev
move tmux to dev dependencies

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-19 13:46:40 +00:00
Alex Corey
ab1e991e01 adds application add functionality and applicatiion form 2020-06-19 09:38:56 -04:00
AlanCoding
a7fe5e1dd2 Fix yamllint error and sync version with module_utils 2020-06-19 09:08:58 -04:00
AlanCoding
96583e9e6b Make version recognizable as pre-release 2020-06-19 09:08:58 -04:00
AlanCoding
73ee11725d Add copy note to galaxy file 2020-06-19 09:08:58 -04:00
AlanCoding
721ed516a4 Separate folder for templating collection stuff 2020-06-19 09:08:57 -04:00
AlanCoding
4848f1298a Include a default galaxy.yml file 2020-06-19 09:08:57 -04:00
John Westcott IV
6c6c1e8488 Adding templating of README.md file for Tower vs AWX collections 2020-06-19 09:08:54 -04:00
Ryan Petrello
31ab386591 move tmux to dev dependencies 2020-06-19 08:47:11 -04:00
Jim Ladd
99b3997084 Merge pull request #4412 from jladdjr/foreman_backwards_compat_for_ssl_verify_3.7.2
add backwards support for ssl_verify in foreman
2020-06-18 18:25:53 -07:00
Jim Ladd
35fe255455 add backwards support for ssl_verify in foreman
* plugin changed option name from
  ssl_verify to validate_cert
2020-06-18 17:02:48 -07:00
softwarefactory-project-zuul[bot]
6682dcbc7c Merge pull request #7357 from mabashian/awx-dep-upgrades-June-15
UI dependency upgrades

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-18 22:03:19 +00:00
softwarefactory-project-zuul[bot]
defa334bd9 Merge pull request #7358 from rebeccahhh/devel
removing memchache mentions in comments

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-18 20:20:15 +00:00
softwarefactory-project-zuul[bot]
70f8a02a5e Merge pull request #7383 from ryanpetrello/tox-py2-bye-bye
awxkit dropped py2 support awhile ago; stop running tests in py2

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-18 20:14:32 +00:00
softwarefactory-project-zuul[bot]
3834125d09 Merge pull request #7378 from AlanCoding/minor_test_tweaks
Fix some minor issues in the AWX collection tests

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-18 20:00:35 +00:00
Rebeccah
118e1b8df1 removing memchache mentions in comments
remove memcached folder as it is no longer needed, also address a couple grammatical errors
2020-06-18 15:52:59 -04:00
Jeff Bradberry
393369adec First cut at examples of the import and export commands 2020-06-18 15:32:49 -04:00
Ryan Petrello
e732d03b20 awxkit dropped py2 support awhile ago; stop running tests in py2 2020-06-18 15:31:35 -04:00
AlanCoding
f76c57b1ec Bump AWX version, after notable inventory deprecation 2020-06-18 15:10:10 -04:00
AlanCoding
8fc3377fa6 Minor test fixes 2020-06-18 13:46:28 -04:00
Alan Rominger
3cf4f4729d [DO NOT PORT to AWX] Pin dev requirements (#4413) 2020-06-18 09:22:04 -04:00
softwarefactory-project-zuul[bot]
1321d298ee Merge pull request #6911 from AlanCoding/rm_all_scripts
Remove vendored inventory scripts

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-18 00:08:03 +00:00
softwarefactory-project-zuul[bot]
d6b9077f72 Merge pull request #7351 from nixocio/ui_add_docs_hooks
Add section related to custom hooks

Reviewed-by: Kersom
             https://github.com/nixocio
2020-06-17 21:31:32 +00:00
softwarefactory-project-zuul[bot]
0e274c3038 Merge pull request #7372 from shanemcd/support-wait-for-first-consumer
Support PVCs that were created w/ WaitForFirstConsumer

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-17 21:23:26 +00:00
Shane McDonald
43bf2989af Support PVCs that were created w/ WaitForFirstConsumer 2020-06-17 16:40:33 -04:00
nixocio
2e33c69e9c Add section related to custom hooks
Add section related to custom hooks, and their usage.
2020-06-17 16:39:23 -04:00
softwarefactory-project-zuul[bot]
9e118b8a0c Merge pull request #7360 from jladdjr/foreman_backwards_compat_for_ssl_verify
[foreman] add backwards support for ssl_verify in foreman plugin

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-17 19:46:53 +00:00
Jim Ladd
91cd5b359a add backwards support for ssl_verify in foreman
* plugin changed option name from
  ssl_verify to validate_cert
2020-06-17 12:18:31 -07:00
softwarefactory-project-zuul[bot]
2df67c4dc8 Merge pull request #7287 from marshmalien/6899-inv-src-subform
Hook up all inventory source subforms

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-17 18:44:30 +00:00
AlanCoding
e784a7c0a3 bump migrations 2020-06-17 14:25:16 -04:00
AlanCoding
401c5671c8 Remove things from tests specific to inventory scripts 2020-06-17 14:25:16 -04:00
AlanCoding
3c8c1858d4 Fix migration through manual testing 2020-06-17 14:25:15 -04:00
AlanCoding
b6a4c34b7a bump migration number 2020-06-17 14:25:15 -04:00
AlanCoding
71cf3198d8 Add data migration to convert cloudforms scripts to SCM 2020-06-17 14:25:15 -04:00
AlanCoding
b0ff763a0b flake8 fixes 2020-06-17 14:25:15 -04:00
AlanCoding
8f56042dcc rename migration 2020-06-17 14:25:15 -04:00
AlanCoding
ec3c4de1f7 Fix openstack and logic and update some tests 2020-06-17 14:25:14 -04:00
AlanCoding
b2bdb0c81d lose cloudforms as inventory source option 2020-06-17 14:25:14 -04:00
AlanCoding
bedb1f364d Remove inventory scripts 2020-06-17 14:25:11 -04:00
Marliana Lara
6ed611c27c Add inventory source subforms 2020-06-17 14:16:03 -04:00
softwarefactory-project-zuul[bot]
97dbfee162 Merge pull request #7359 from shanemcd/no-host-pg-port
Remove local port binding for postgres in dev env

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-17 18:10:35 +00:00
Shane McDonald
51b0c51605 Remove local port binding for postgres in dev env
I dont think we need to bind this port at the host level. This will allow us to
run the galaxy_ng dev tooling side-by-side with AWX.
2020-06-17 13:34:55 -04:00
softwarefactory-project-zuul[bot]
5ca66ac806 Merge pull request #7317 from shanemcd/redis-root-group
Force containers in k8s to run under root group

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-16 23:41:42 +00:00
Ryan Petrello
6376395c68 Merge pull request #4409 from ryanpetrello/371-host-summary-regression
fix a regression in how job host summaries are generated
2020-06-16 17:04:22 -04:00
softwarefactory-project-zuul[bot]
90bcb6d145 Merge pull request #7258 from mabashian/dynamic-credential-form
Dynamically render credential subform fields

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-16 20:43:53 +00:00
mabashian
3c27e1ca12 Revert "Gets rid of custom form reset function in favor of formik's resetForm in credential form"
This reverts commit 26fa94dc6f1f1c1306c32ba571eb2899e516b0a0.
2020-06-16 16:16:30 -04:00
mabashian
8aa6e9466f Fixes credential type dropdown item sort issue where Vault appeared after VMware 2020-06-16 16:16:30 -04:00
mabashian
9180334908 Adds a bit more unit test coverage around credential add/edit save functionality, making sure that we're making the correct calls with the correct payloads. 2020-06-16 16:16:30 -04:00
mabashian
9d63b679f9 Gets rid of custom form reset function in favor of formik's resetForm in credential form 2020-06-16 16:16:30 -04:00
mabashian
d5578d9744 Only render subform if cred type inputs.fields exists. This fixes a bug where an error was thrown when a custom credential type without an input configuration existed in the database. 2020-06-16 16:16:30 -04:00
mabashian
7fefea31c0 Removes nested ternary in CredentialField validate param by moving logic out to a function and making it a little more readable. 2020-06-16 16:16:30 -04:00
mabashian
b5ce1fe2f3 Changes CredentialSubForm to TypeInputsSubForm 2020-06-16 16:16:30 -04:00
mabashian
3dfc9328a9 Dynamically render credential subform fields based on options responses for each credential type 2020-06-16 16:16:30 -04:00
softwarefactory-project-zuul[bot]
dba55fec47 Merge pull request #7337 from rooftopcellist/i18n_awx_translations_6-15
UI translation strings for release_3.7.1 branch

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-16 20:16:02 +00:00
ansible-translation-bot
93498b2d7f UI translation strings for release_3.7.1 branch 2020-06-16 15:47:24 -04:00
mabashian
781b675837 Upgrade jquery to 3.5.1 2020-06-16 14:44:17 -04:00
mabashian
5e3ce7b7ea Update ngToast to most recent version 2020-06-16 14:44:16 -04:00
mabashian
34dd034f7c Upgrades to the latest angular-tz-extensions 2020-06-16 14:44:16 -04:00
mabashian
d5fcf733f0 Upgrades to the latest angular-codemirror 2020-06-16 14:44:16 -04:00
mabashian
8d63ebf0e0 Upgrade to the latest angular-scheduler 2020-06-16 14:44:16 -04:00
softwarefactory-project-zuul[bot]
de5f996358 Merge pull request #7352 from ryanpetrello/host-summary-optimization-bug
fix a regression in how job host summaries are generated

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-16 17:33:01 +00:00
softwarefactory-project-zuul[bot]
a54081de2e Merge pull request #7328 from Tompage1994/credential_input_source
Add tower_credential_input_source to awx_collection

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-16 17:27:45 +00:00
Ryan Petrello
eaadbe9730 fix a regression in how job host summaries are generated
this change fixes a bug introduced in the optimization at https://github.com/ansible/awx/pull/7352

1. Create inventory with multiple hosts
2. Run a playbook with a limit to match only one host
3. Run job, verify that it only acts on the one host
4. Go to inventory host list and see that all the hosts have last_job updated to point to the job that only acted on one host.
2020-06-16 13:18:14 -04:00
Ryan Petrello
70afbe0b8d fix a regression in how job host summaries are generated
this change fixes a bug introduced in the optimization at https://github.com/ansible/awx/pull/7352

1. Create inventory with multiple hosts
2. Run a playbook with a limit to match only one host
3. Run job, verify that it only acts on the one host
4. Go to inventory host list and see that all the hosts have last_job updated to point to the job that only acted on one host.
2020-06-16 13:06:22 -04:00
Tom Page
7bf1d4946e Fixed final lint issues
Signed-off-by: Tom Page <tpage@redhat.com>
2020-06-16 17:14:52 +01:00
Tom Page
fd18194b1b Fix pylint errors 2020-06-16 15:57:19 +01:00
Tom Page
73a39c1e55 Cleanup of debug and change test fixtures
Signed-off-by: Tom Page <tpage@redhat.com>
2020-06-16 14:30:28 +01:00
softwarefactory-project-zuul[bot]
415c39aabc Merge pull request #6938 from neb14/journald_logging_option
This allows for using different docker logging drivers

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-16 13:30:07 +00:00
Tom Page
1c78190385 Change cred_input_src to remove src_cred as primarykey
Signed-off-by: Tom Page <tpage@redhat.com>
2020-06-16 13:56:49 +01:00
Ben Schmitz
ea175ac5b6 Allows for docker logger support 2020-06-16 08:29:43 -04:00
softwarefactory-project-zuul[bot]
5527fc9115 Merge pull request #7343 from shanemcd/struggles
Make tests pass with current versions of things

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-16 12:24:39 +00:00
Tom Page
4c55685656 Add tower_credential_input_source to awx_collection
Signed-off-by: Tom Page <tpage@redhat.com>
2020-06-16 13:17:11 +01:00
Shane McDonald
de82c613fc Make tests pass with current versions of things 2020-06-15 23:13:44 -04:00
Christian Adams
186c54cb14 Merge pull request #4404 from ansible/i18n_release_3.7.1_translations
UI translation strings for release_3.7.1 branch
2020-06-15 17:10:10 -04:00
ansible-translation-bot
40eb3e43f8 UI translation strings for release_3.7.1 branch 2020-06-12 17:03:37 +00:00
softwarefactory-project-zuul[bot]
241931309e Merge pull request #7321 from jladdjr/instance_id_fallback
Instance id fallback

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-11 21:49:39 +00:00
softwarefactory-project-zuul[bot]
26083bdef6 Merge pull request #7304 from AlexSCorey/7233-ApplicationsList
Adds lists and list items and delete functionality

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-11 19:47:56 +00:00
Shane McDonald
e035eea95a Merge pull request #7188 from mo-saeed/devel
Reshape security context for AWX containers
2020-06-11 15:26:58 -04:00
Jim Ladd
e1f7a7619f Merge pull request #4398 from jladdjr/instance_id_fallback
Instance id fallback
2020-06-11 12:19:23 -07:00
Alex Corey
f211c70e69 fixes qs namespace, and location of proptypes 2020-06-11 15:16:14 -04:00
Alex Corey
08d9341704 Adds lists and list items and delete functionality 2020-06-11 15:16:14 -04:00
Jeff Bradberry
0fda9d2c56 Continue after failures to grant roles 2020-06-11 13:19:24 -04:00
Jim Ladd
43ab6acb84 revert EC2_INSTANCE_ID_VAR 2020-06-11 09:53:50 -07:00
Jim Ladd
8eee0d40dd revert EC2_INSTANCE_ID_VAR 2020-06-11 09:52:54 -07:00
Ryan Petrello
fe221c2473 Merge pull request #4399 from shanemcd/kube-queues
Add queue / instance group registration to heartbeat for k8s installs
2020-06-11 09:00:16 -04:00
softwarefactory-project-zuul[bot]
cb1a3e4199 Merge pull request #7312 from nixocio/ui_issue_7301
Add stub files for Credential Types

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-10 21:24:17 +00:00
Jim Ladd
3b61b82616 wrap --instance-id-var in quotes 2020-06-10 14:06:57 -07:00
Jim Ladd
9eaee801a7 update VMWARE_INSTANCE_ID_VAR
* Favor instanceUuid
* .. but fall back to instanceuuid if necessary
2020-06-10 14:06:54 -07:00
AlanCoding
1970fac989 Allow use of fallback instance_ids 2020-06-10 14:06:50 -07:00
softwarefactory-project-zuul[bot]
28164ad4cc Merge pull request #7319 from wenottingham/unused-perhaps
Remove active_counts_by_org

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-10 21:05:50 +00:00
Jim Ladd
9514adaf3a wrap --instance-id-var in quotes 2020-06-10 13:55:54 -07:00
Shane McDonald
85deb8711c Add queue / instance group registration to heartbeat for k8s installs
There is some history here.

https://github.com/ansible/awx/pull/7190 <- This PR was an attempt at fixing a
bug notting ran into where some jobs on k8s installs would get stuck in Waiting
forever.

The PR mentioned above introduced a bug where there are no instance groups on a
fresh k8s-based install. This is because this process currently happens in the
launch scripts, before the database is up.

With this patch, queue / instance group registration happens in the heartbeat,
right after auto-registering the instance.
2020-06-10 16:55:27 -04:00
nixocio
8eecfeaab4 Add stub files for Credential Types
Add stub files for Credential Types. Routing system, and screens layout.

closes: https://github.com/ansible/awx/issues/7301
2020-06-10 16:44:10 -04:00
Jim Ladd
17eaeb28a8 update VMWARE_INSTANCE_ID_VAR
* Favor instanceUuid
* .. but fall back to instanceuuid if necessary
2020-06-10 13:30:05 -07:00
Jeff Bradberry
bf6e8f8e83 Prioritize membership roles
since certain role grants will not be accepted by the api unless the user or team is part of the correct organization.
2020-06-10 15:27:15 -04:00
Bill Nottingham
a33c303765 Remove active_counts_by_org
I was trying to parse the difference between this and the
(directly above) org_active_count from the comment, and then I
grepped and realized this function appears unused.
2020-06-10 15:25:14 -04:00
Shane McDonald
423df6618d Force containers in k8s to run under root group
Normally containers belong to the 'root' group, but for some reason the
downstream red hat scl redis image only belongs to the 'redis' group by default. This fixes that.
2020-06-10 13:40:15 -04:00
softwarefactory-project-zuul[bot]
3ae4417af4 Merge pull request #7314 from nixocio/ui_fix_clipboard_error
Add required variables to ClipboardCopyButton test

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-10 16:43:28 +00:00
softwarefactory-project-zuul[bot]
2582036fc8 Merge pull request #7313 from kdelee/update_k8s_inv_docs
remove some references to memcached

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-10 16:33:08 +00:00
softwarefactory-project-zuul[bot]
b8e1f1b882 Merge pull request #7316 from ryanpetrello/tmi
remove a highly verbose log lines

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-10 16:23:30 +00:00
softwarefactory-project-zuul[bot]
dc3701b3d6 Merge pull request #7315 from ryanpetrello/redis-chmod-docker
set proper permissions for the redis socket

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-10 16:06:25 +00:00
softwarefactory-project-zuul[bot]
3818fb9b69 Merge pull request #7306 from AlexSCorey/6863-CopyProjectsAndInventories
Removes extra spacing from timeOfDay function

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-10 16:06:20 +00:00
Ryan Petrello
64ebfa75a8 remove a highly verbose log lines 2020-06-10 11:50:13 -04:00
Ryan Petrello
e81ccf10df set proper permissions for the redis socket 2020-06-10 11:36:09 -04:00
nixocio
9797c8e3c2 Add required variables to ClipboardCopyButton test
Add required variables to `ClipboardCopyButton` test to remove warnings
during test execution.
2020-06-10 11:25:39 -04:00
Elijah DeLee
a83a9c9723 remove dep on python-memcached 2020-06-10 11:18:48 -04:00
Elijah DeLee
6777b82d8e remove reference to memcached in k8s inv
we don't have memcached container anymore
2020-06-10 11:08:49 -04:00
softwarefactory-project-zuul[bot]
753b8c287c Merge pull request #7221 from AlexSCorey/6589-InventorySourceSchedules
Adds Inventory Sources Schedules

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2020-06-10 15:01:54 +00:00
mosad
eb5970b4a1 merge and resolve conflicts 2020-06-10 16:01:17 +02:00
Ryan Petrello
7c1959010a Merge pull request #4396 from jladdjr/foreman_script_should_not_use_reports_3.7.1
disable reports option for foreman (release_3.7.1)
2020-06-10 08:30:14 -04:00
AlanCoding
1dd9772e41 Allow use of fallback instance_ids 2020-06-09 22:51:42 -07:00
Jim Ladd
18d09f892d disable reports option for foreman 2020-06-09 22:37:35 -07:00
Jake McDermott
ee6f03515e Merge pull request #4340 from jakemcdermott/fix-4336
[3.7.1] Enable management job notications for admins
2020-06-09 16:27:07 -04:00
Jake McDermott
16f81154c0 Merge pull request #4338 from mabashian/4334-backport-v2
[3.7.1] Fixes bug where all_parents_must_converge was not being set for new or existing approval nodes
2020-06-09 15:36:40 -04:00
Jeff Bradberry
19b7c91486 Return the changed status of imports 2020-06-09 15:00:06 -04:00
Jeff Bradberry
aeeed4d371 Add more logging 2020-06-09 15:00:06 -04:00
Jeff Bradberry
1f7c1af64e Fix WFJT nodes endpoint to return node pages when posting
not the node list page.
2020-06-09 15:00:06 -04:00
Jeff Bradberry
65fc2db42f Recursively queue up related assets to be created and/or assigned 2020-06-09 14:59:49 -04:00
Alex Corey
82010e4ba2 removes extra spacing 2020-06-09 14:59:36 -04:00
Ryan Petrello
1d7e2a82c6 Merge pull request #4393 from kdelee/backport_dont_block_log_send
[3.7.1] don't block on log aggregator socket.send() calls
2020-06-09 14:49:43 -04:00
Jeff Bradberry
c8288af87f Make sure we have a cached version of existing objects
even if it isn't an object being directly imported.  We might need it
for relations of things that are being imported.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
76fb605dcd Deal with exports involving foreign keys where you don't have permission 2020-06-09 13:54:05 -04:00
Jeff Bradberry
a531b85b31 Redo waiting until Project updates are complete 2020-06-09 13:54:05 -04:00
Jeff Bradberry
86afa5cf42 Make more use of the PageCache for imports 2020-06-09 13:54:05 -04:00
Jeff Bradberry
57aff6394c Log an error and continue when a related object is not found 2020-06-09 13:54:05 -04:00
Jeff Bradberry
66bc947adb Reuse _import_list for import of related full objects
e.g. WFJT Nodes.  Also rename _import_list from _create_assets.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
301f15bfdd Rename some things for consistency 2020-06-09 13:54:05 -04:00
Jeff Bradberry
9fc1a4bb44 Change the method that exports list views to take a PageList or TentativePage
This will allow the related m2m views to also use this method, with a
bit of effort.  Also, remove the use of pk_or_name in favor of a new
method that reduces the number of api calls.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
f7825aefeb Avoid doing an OPTIONS call unless we know it is a related type we export 2020-06-09 13:54:05 -04:00
Jeff Bradberry
14b5f63bd8 Use the new PageCache to store and reuse Page.get results 2020-06-09 13:54:05 -04:00
Jeff Bradberry
1300d38e47 Introduce a new PageCache object
and split out get_post_fields into its own utility function.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
bb66e4633d Split _get_options into two pieces 2020-06-09 13:54:05 -04:00
Jeff Bradberry
201de4e18a Attempt to deal with foreign keys that get mislabeled as type integer
such as through the use of DeprecatedCredentialField.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
471dc2babf Deal with relations that we cannot resolve
such as due to a lack of permissions.  If there is a foreign key to
something where we don't have sufficient read permissions, we now drop
the parent object from the export.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
6387258da1 Only wait for Project updates
not other kinds of objects that have a status.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
6958815f6e Remove the $encrypted$ placeholders from export values 2020-06-09 13:54:05 -04:00
Jeff Bradberry
43b76f4575 Deal with unreadable mandatory foreign keys
by dropping the parent object.  Also, clarify some of the warning log
messages.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
53d81d42cc Hook up creation and attachment of related objects 2020-06-09 13:54:05 -04:00
Jeff Bradberry
385725e52a Fix the _create_assets method to use _get_options 2020-06-09 13:54:05 -04:00
Jeff Bradberry
1b264011a2 Enable interconnections between WFJT Nodes 2020-06-09 13:54:05 -04:00
Jeff Bradberry
719f0b407c Enable credential relations
but only when it is in an attach/detach list view.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
a5fa34bd3b Fall back to parsing the OPTIONS description
to determine the needed fields for constructing an object.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
eb10a1873d Drop objects that cannot be read or do not have a natural key
don't fail hard.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
ab15349c8c Remove the NoNaturalKey error
It's too awkward, and it makes more sense to return None instead.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
e053a58223 Handle some more bad cases when doing OPTIONS calls
- deprecated endpoints
- read-only endpoints
- insufficient privileges

The latter case currently just drops it on the floor, but ought to do
something better.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
4262dd38ba Change the NoNaturalKey exception to no longer derive from Common
which seems to be entirely use for response exceptions.  Maybe rename
Common?
2020-06-09 13:54:05 -04:00
Jeff Bradberry
0deacc4391 If attempting to link to a resource that is not yet complete, wait 2020-06-09 13:54:05 -04:00
Jeff Bradberry
329293dbf0 Tentatively enable inventory sources 2020-06-09 13:54:05 -04:00
Jeff Bradberry
e92c8cfdcc Remove the natural key lookup dict and make each Page responsible instead 2020-06-09 13:54:05 -04:00
Jeff Bradberry
07ba521b8b Enable schedules 2020-06-09 13:54:05 -04:00
Jeff Bradberry
972d3ab535 Export full related objects under some conditions 2020-06-09 13:54:05 -04:00
Jeff Bradberry
a1f7d0b781 Fix a bug with inventory.variables
Using Page[key] instead of Page.json[key] causes inner json blob
strings to automatically get parsed, which is not what we want with
this field.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
30a3e3e172 Deal with lack of permissions 2020-06-09 13:54:05 -04:00
Jeff Bradberry
01d575f833 Enable the remaining top-level exportable resources
and rearrange the import/export methods a bit.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
e0f6af4700 Enable the export of several relation field types 2020-06-09 13:54:05 -04:00
Jeff Bradberry
3860c7597f Move the import logic into methods on the ApiV2 class 2020-06-09 13:54:05 -04:00
Jeff Bradberry
e4146e9bc7 Move the export logic onto methods on the ApiV2 class
making it easier to invoke programmatically.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
19c92a7055 Enable notification templates 2020-06-09 13:54:05 -04:00
Jeff Bradberry
6a9add4fe3 Deal somewhat reasonably with missing fields as part of the natural key
- JobTemplate.organization has recently been added, we need to support
  with and without
- WorkflowJobTemplateNode is shortly going to get an identifier field,
  and we will need to support both with and without
2020-06-09 13:54:05 -04:00
Jeff Bradberry
ad574eb896 Enable credential export 2020-06-09 13:54:05 -04:00
Jeff Bradberry
55f79a4569 Fix a couple of flaws
- The dependency ordering may spit out page types that weren't in the import data set.  Make sure to be able to map those to resources anyway.
- freeze() needs to be able to deal with nullable foreign keys.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
d20fa03034 Create new Import.dependent_resources method
that yields up resource names, even ones that aren't explicitly in the
import data, in dependency order.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
868aafb263 Filter out managed credential types
since we cannot patch them upon import.
2020-06-09 13:54:05 -04:00
Jeff Bradberry
3f204659a8 Temporarily disable export of resources that may not work yet 2020-06-09 13:54:05 -04:00
Jeff Bradberry
ea5b810e87 Sort the asset groups to be imported by their dependency relationships 2020-06-09 13:54:04 -04:00
Jeff Bradberry
2c00d42ced Only use a default password if an import user doesn't already exist 2020-06-09 13:54:04 -04:00
Jeff Bradberry
d191edcaf1 Fix a Python 2 syntax error
it doesn't like multiple **kwargs, apparently.
2020-06-09 13:54:04 -04:00
Jeff Bradberry
65e16dc7ae Get and assign the related objects 2020-06-09 13:54:04 -04:00
Jeff Bradberry
95b22bf05b Begin to deal with existing matching assets
by using a registry allowing the lookup of Page objects by (frozen)
natural keys.
2020-06-09 13:54:04 -04:00
Jeff Bradberry
21e36ad19a Add the calculated natural key to the export data for each asset 2020-06-09 13:54:04 -04:00
Jeff Bradberry
f53920d3bf Begin changing Import to work with the structure created by Export 2020-06-09 13:54:04 -04:00
Jeff Bradberry
372570ce8e Extract out get_natural_key as a standalone function 2020-06-09 13:54:04 -04:00
Jeff Bradberry
6f28361bf5 Make serialize_asset use Pages to a greater extent 2020-06-09 13:54:04 -04:00
Jeff Bradberry
0877e5305c Modify get_natural_key to work on Pages 2020-06-09 13:54:04 -04:00
Jeff Bradberry
e4383c505f Make more use of the functionality of Page in get_assets
and related methods.  Also, rename get_resource_options -> get_options
and enhance_asset -> serialize_asset.
2020-06-09 13:54:04 -04:00
Jeff Bradberry
fb066eb52e Fold the other methods doing API calls into get_assets() 2020-06-09 13:54:04 -04:00
Jeff Bradberry
6162ff0439 Start to record the role membership
but not really, since it still isn't fully capturing the role content_object
2020-06-09 13:54:04 -04:00
Jeff Bradberry
dfe34563aa Resolve the natural keys of assets we've already collected 2020-06-09 13:54:04 -04:00
Jeff Bradberry
37cbf7691b Split out separate methods for the OPTIONS call and massaging each asset dict 2020-06-09 13:54:04 -04:00
Jeff Bradberry
9280198b0f Use a list of exportable resources to build up the parser
Also, handle an implicit export of everything.
2020-06-09 13:54:04 -04:00
Jeff Bradberry
2127f3c96d Add organizations as a resource type to export 2020-06-09 13:54:04 -04:00
Jeff Bradberry
9f7fecf8da Add basic import command 2020-06-09 13:54:04 -04:00
Jeff Bradberry
c1a07ff00b Limit export output to only those fields needed to create the resource 2020-06-09 13:54:04 -04:00
Jeff Bradberry
f21d6b1fc4 Actually query the API for the user or users requested 2020-06-09 13:54:04 -04:00
Jeff Bradberry
4312395a3a Normalize the requested resource into a pk
using the pk_or_name helper function.  Also, authenticate to the API.
2020-06-09 13:54:04 -04:00
Jeff Bradberry
c1f6fec532 Add skeleton of a custom 'export' resource
This only takes a flag for users at the moment, and does nothing in
particular with it.
2020-06-09 13:54:04 -04:00
Ryan Petrello
b7ac5f0ffb Merge pull request #4395 from fosterseth/fix-parents_converge_settable_api_backport
[backport] Make all_parents_must_converge settable when creating node
2020-06-09 11:29:34 -04:00
Seth Foster
0e5f68ef53 Make all_parents_must_converge settable when creating node
When targeting, ../workflow_job_templates/id#/workflow_nodes/ endpoint,
user could not set all_parents_must_converge to true.

3.7.1 backport for awx issue #7063
2020-06-09 11:07:22 -04:00
Ryan Petrello
a057a2e056 Merge pull request #4394 from ryanpetrello/mattermost-371
Send content-type with mattermost notifications, fixes #7264
2020-06-09 10:35:55 -04:00
Florian Apolloner
e9e410f4f8 Send content-type with mattermost notifications, fixes #7264 2020-06-09 10:32:32 -04:00
Ryan Petrello
71cc359ccf don't block on log aggregator socket.send() calls
see: https://github.com/ansible/tower/issues/4391
2020-06-09 10:10:32 -04:00
Sean Sullivan
104073af45 Merge pull request #1 from ansible/devel
Merging remote to devel
2020-06-09 07:50:36 -05:00
Chris Meyers
37c1c33ecd Merge pull request #4389 from chrismeyersfsu/fix-run_wsbroadcast_status_3_7_1
awx-manage run_wsbroadcast --status doesn't work in openshift
2020-06-08 20:18:32 -04:00
chris meyers
2f7ba75ae4 track stats by hostname not remote host/ip
* broadcast websockets have stats tracked (i.e. connection status,
number of messages total, messages per minute, etc). Previous to this
change, stats were tracked by ip address, if it was defined on the
instance, XOR hostname. This changeset tracks stats by hostname.
2020-06-08 16:35:17 -04:00
chris meyers
9c20b9412a delete and re-add host when ip address changes
* The websocket backplane interconnect is done via ip address for
Kubernetes and OpenShift. On init run_wsbroadcast reads all Instances
from the DB and makes a decision to use the ip address or the hostname
based, with preference given to the ip address if defined. For
Kubernetes and OpenShift the nodes can load the Instance before the
ip_address is set. This would cause the connection to be tried by
hostname rather than ip address. This changeset ensures that an ip
address set after an Instance record is created will be detected and
used.
2020-06-08 16:34:51 -04:00
Ryan Petrello
99c0a954e4 Merge pull request #4384 from ryanpetrello/rsyslog-chmod
properly write rsyslog configuration as 0640
2020-06-08 14:05:18 -04:00
Jim Ladd
0a0735344e Merge pull request #4342 from jladdjr/foreman_group_prefix_should_apply_to_all_groups_3.7.1
foreman: use group_prefix for all groups (release_3.7.1)
2020-06-05 15:25:22 -07:00
mo-saeed
0bfcacfcf4 Merge branch 'devel' into devel 2020-06-06 00:19:19 +02:00
mosad
1e6437b773 Resolve conflict 2 2020-06-06 00:17:26 +02:00
Jim Ladd
9ae344b772 foreman: use group_prefix for all groups
* awx's "compatibility layer" for the foreman plugin had the
  group_prefix hard-coded to 'foreman_'
2020-06-05 14:44:55 -07:00
mosad
7d0c49c043 Fix conflict 2020-06-05 23:41:20 +02:00
Jim Ladd
0c4adfb32e Merge pull request #4387 from jladdjr/bump_foreman_collection_0.8.1
Bump foreman collection to 0.8.1
2020-06-05 12:10:22 -07:00
Jim Ladd
4ce37ec849 Bump foreman collection to 0.8.1
* New release includes:
  'add host_filters and want_ansible_ssh_host like script used to have'
2020-06-05 11:13:01 -07:00
Alex Corey
49053d3473 Adds Inventory Sources Schedules 2020-06-05 11:50:53 -04:00
Ryan Petrello
c53e5bdbcf properly write rsyslog configuration as 0640
see: https://github.com/ansible/tower/issues/4383
2020-06-04 15:12:09 -04:00
Christian Adams
e0032f7705 Merge pull request #4367 from rooftopcellist/sumologic_conf
Correctly parse sumologic url paths
2020-06-01 01:36:20 -04:00
Christian Adams
ed05ce164f Merge pull request #4377 from rooftopcellist/cleanup_flake8
Fix misc. linter errors due to the flake8-3.8.1 release
2020-05-29 19:29:17 -04:00
Christian Adams
d98f2714cb Merge pull request #4376 from rooftopcellist/rm_label_3.7.1
Fix 500 on Label Removal for WFJT's [3.7.1]
2020-05-29 18:11:45 -04:00
beeankha
85426f76a5 Fix misc. linter errors due to the flake8-3.8.1 release
- [Ref] https://flake8.pycqa.org/en/latest/release-notes/
2020-05-29 17:58:27 -04:00
Christian Adams
c48da1b384 allow org admins to remove labels 2020-05-29 15:12:35 -04:00
mosad
4a9603a7ea Allow priv container for awx_task and option to create psp 2020-05-29 20:24:49 +02:00
mosad
b13a175668 Reshape security context for AWX containers 2020-05-29 12:35:45 +02:00
Christian Adams
aec7d3cc93 Correctly parse sumologic url paths
- Sumologic includes a token with a '==' at the end of it's host path.
   This adds rsyslog conf parsing tests and does not escape equals
   signs.
2020-05-27 13:05:31 -04:00
Ryan Petrello
bd23c41d25 Merge pull request #4361 from ryanpetrello/venv-try-except
[3.7.1] backport a change to address venv permission issues
2020-05-26 11:31:16 -04:00
gamuniz
563d3944ed removed pass per feedback 2020-05-26 11:21:58 -04:00
Gabe Muniz
492d01ff3b added try/except to virtual env 2020-05-26 11:21:49 -04:00
Elijah DeLee
3ded30411f Merge pull request #4341 from kdelee/backport_host_summary_optimization_3.7.1
Backport host summary optimization 3.7.1
2020-05-21 13:37:16 -04:00
Bill Nottingham
b38c62d37f Merge pull request #4353 from wenottingham/analytics-skip-3.7.1
Always check configuration before gathering data.
2020-05-21 13:23:08 -04:00
Bill Nottingham
4c499b2d80 Always check configuration before gathering data.
We shouldn't perform expensive operations if we won't be able to send it.
Only log at debug level, otherwise every node will log this every 5
minutes.
2020-05-20 17:24:38 -04:00
Ryan Petrello
3d02bd7a90 Merge pull request #4350 from ryanpetrello/371-os-walkdir-recursive
Revert "follow symlinks while discovering valid playbooks"
2020-05-20 16:50:28 -04:00
Ryan Petrello
71257c18c2 Revert "follow symlinks while discovering valid playbooks"
This reverts commit 3dd21d720e.
2020-05-20 16:47:38 -04:00
Ryan Petrello
d85df2e4a1 further optimize job host summary queries 2020-05-19 13:00:12 -04:00
Ryan Petrello
59d457207c properly update .failed, .last_job_id, and last_job_host_summary 2020-05-19 13:00:05 -04:00
Ryan Petrello
3ea642f212 properly handle host summary bulk updates if hosts go missing 2020-05-19 13:00:00 -04:00
Ryan Petrello
b6d3c3c1a3 drastically optimize job host summary creation
see: https://github.com/ansible/awx/issues/6991
2020-05-19 12:59:54 -04:00
Jake McDermott
b83db0500f Enable management job notications for admins 2020-05-19 10:52:09 -04:00
mabashian
c4d9b81c55 Fixes bug where all_parents_must_converge was not being set for new or existing approval nodes. 2020-05-18 15:16:05 -04:00
Shane McDonald
cdfc9e05d4 Fix offline RHEL 8 builds
This was causing our EL8 Brew builds to break, because it wasn't being
vendored. This is in fact required for python3. It was being resolved as a
dependency of other things (see list at end of line), so it was being downloaded
on-the-fly since our normal builds have internet access. It only broke when it
wasn't vendored for offline builds.
2020-05-15 17:52:08 -04:00
1168 changed files with 51415 additions and 23419 deletions

View File

@@ -3,6 +3,12 @@ name: "\U0001F41B Bug report"
about: Create a report to help us improve
---
<!-- Issues are for **concrete, actionable bugs and feature requests** only - if you're just asking for debugging help or technical support, please use:
- http://webchat.freenode.net/?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
- Bug Report

View File

@@ -3,6 +3,12 @@ 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://webchat.freenode.net/?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

6
.gitignore vendored
View File

@@ -29,8 +29,10 @@ awx/ui/client/languages
awx/ui/templates/ui/index.html
awx/ui/templates/ui/installing.html
awx/ui_next/node_modules/
awx/ui_next/src/locales/
awx/ui_next/coverage/
awx/ui_next/build/locales/_build
awx/ui_next/build
awx/ui_next/.env.local
rsyslog.pid
/tower-license
/tower-license/**
@@ -139,8 +141,8 @@ use_dev_supervisor.txt
# Ansible module tests
/awx_collection_test_venv/
/awx_collection/*.tar.gz
/awx_collection/galaxy.yml
/sanity/
/awx_collection_build/
.idea/*
*.unison.tmp

View File

@@ -2,12 +2,80 @@
This is a list of high-level changes for each release of AWX. A full list of commits can be found at `https://github.com/ansible/awx/releases/tag/<version>`.
## 15.0.0 (September 30, 2020)
- AWX now utilizes a version of certifi that auto-discovers certificates in the system certificate store - https://github.com/ansible/awx/pull/8242
- Added support for arbitrary custom inventory plugin configuration: https://github.com/ansible/awx/issues/5150
- Added improved support for fetching Ansible collections from private Galaxy content sources (such as https://github.com/ansible/galaxy_ng) - https://github.com/ansible/awx/issues/7813
- Added an optional setting to disable the auto-creation of organizations and teams on successful SAML login. - https://github.com/ansible/awx/pull/8069
- Added a number of optimizations to Ansible Tower's callback receiver to improve the speed of stdout processing for simultaneous playbooks runs - https://github.com/ansible/awx/pull/8193 https://github.com/ansible/awx/pull/8191
- Added the ability to use `!include` and `!import` constructors when constructing YAML for use with the AWX CLI - https://github.com/ansible/awx/issues/8135
- Fixed a bug that prevented certain users from being able to edit approval nodes in Workflows - https://github.com/ansible/awx/pull/8253
- Fixed a bug that broke password prompting for credentials in certain cases - https://github.com/ansible/awx/issues/8202
- Fixed a bug which can cause PostgreSQL deadlocks when running many parallel playbooks against large shared inventories - https://github.com/ansible/awx/issues/8145
- Fixed a bug which can cause delays in Ansible Tower's task manager when large numbers of simultaneous jobs are scheduled - https://github.com/ansible/awx/issues/7655
- Fixed a bug which can cause certain scheduled jobs - those that run every X minute(s) or hour(s) - to fail to run at the proper time - https://github.com/ansible/awx/issues/8071
- Fixed a performance issue for playbooks that store large amounts of data using the `set_stats` module - https://github.com/ansible/awx/issues/8006
- Fixed a bug related to AWX's handling of the auth_path argument for the HashiVault KeyValue credential plugin - https://github.com/ansible/awx/pull/7991
- Fixed a bug that broke support for Remote Archive SCM Type project syncs on platforms that utilize Python2 - https://github.com/ansible/awx/pull/8057
- Updated to the latest version of Django Rest Framework.
- Updated to the latest version of Django to address CVE-2020-24583 and CVE-2020-24584
- Updated to the latest verson of channels_redis to address a bug that slowly causes Daphne processes to leak memory over time - https://github.com/django/channels_redis/issues/212
## 14.1.0 (Aug 25, 2020)
- AWX images can now be built on ARM64 - https://github.com/ansible/awx/pull/7607
- Added the Remote Archive SCM Type to support using immutable artifacts and releases (such as tarballs and zip files) as projects - https://github.com/ansible/awx/issues/7954
- Deprecated official support for Mercurial-based project updates - https://github.com/ansible/awx/issues/7932
- Added resource import/export support to the official AWX collection - https://github.com/ansible/awx/issues/7329
- Added the ability to import YAML-based resources (instead of just JSON) when using the AWX CLI - https://github.com/ansible/awx/pull/7808
- Users upgrading from older versions of AWX may encounter an issue that causes their postgres container to restart in a loop (https://github.com/ansible/awx/issues/7854) - if you encounter this, bring your containers down and then back up (e.g., `docker-compose down && docker-compose up -d`) after upgrading to 14.1.0.
- Updated the AWX CLI to export labels associated with Workflow Job Templates - https://github.com/ansible/awx/pull/7847
- Updated to the latest python-ldap to address a bug - https://github.com/ansible/awx/issues/7868
- Upgraded git-python to fix a bug that caused workflows to sometimes fail - https://github.com/ansible/awx/issues/6119
- Worked around a bug in the channels_redis library that slowly causes Daphne processes to leak memory over time - https://github.com/django/channels_redis/issues/212
- Fixed a bug in the AWX CLI that prevented Workflow nodes from importing properly - https://github.com/ansible/awx/issues/7793
- Fixed a bug in the awx.awx collection release process that templated the wrong version - https://github.com/ansible/awx/issues/7870
- Fixed a bug that caused errors rendering stdout that contained UTF-16 surrogate pairs - https://github.com/ansible/awx/pull/7918
## 14.0.0 (Aug 6, 2020)
- As part of our commitment to inclusivity in open source, we recently took some time to audit AWX's source code and user interface and replace certain terminology with more inclusive language. Strictly speaking, this isn't a bug or a feature, but we think it's important and worth calling attention to:
* https://github.com/ansible/awx/commit/78229f58715fbfbf88177e54031f532543b57acc
* https://www.redhat.com/en/blog/making-open-source-more-inclusive-eradicating-problematic-language
- Installing roles and collections via requirements.yml as part of Project Updates now requires at least Ansible 2.9 - https://github.com/ansible/awx/issues/7769
- Deprecated the use of the `PRIMARY_GALAXY_USERNAME` and `PRIMARY_GALAXY_PASSWORD` settings. We recommend using tokens to access Galaxy or Automation Hub.
- Added local caching for downloaded roles and collections so they are not re-downloaded on nodes where they are up to date with the project - https://github.com/ansible/awx/issues/5518
- Added the ability to associate K8S/OpenShift credentials to Job Template for playbook interaction with the `community.kubernetes` collection - https://github.com/ansible/awx/issues/5735
- Added the ability to include HTML in the Custom Login Info presented on the login page - https://github.com/ansible/awx/issues/7600
- Fixed https://access.redhat.com/security/cve/cve-2020-14327 - Server-side request forgery on credentials
- Fixed https://access.redhat.com/security/cve/cve-2020-14328 - Server-side request forgery on webhooks
- Fixed https://access.redhat.com/security/cve/cve-2020-14329 - Sensitive data exposure on labels
- Fixed https://access.redhat.com/security/cve/cve-2020-14337 - Named URLs allow for testing the presence or absence of objects
- Fixed a number of bugs in the user interface related to an upgrade of jQuery:
* https://github.com/ansible/awx/issues/7530
* https://github.com/ansible/awx/issues/7546
* https://github.com/ansible/awx/issues/7534
* https://github.com/ansible/awx/issues/7606
- Fixed a bug that caused the `-f yaml` flag of the AWX CLI to not print properly formatted YAML - https://github.com/ansible/awx/issues/7795
- Fixed a bug in the installer that caused errors when `docker_registry_password` was set - https://github.com/ansible/awx/issues/7695
- Fixed a permissions error that prevented certain users from starting AWX services - https://github.com/ansible/awx/issues/7545
- Fixed a bug that allows superusers to run unsafe Jinja code when defining custom Credential Types - https://github.com/ansible/awx/pull/7584/
- Fixed a bug that prevented users from creating (or editing) custom Credential Types containing boolean fields - https://github.com/ansible/awx/issues/7483
- Fixed a bug that prevented users with postgres usernames containing uppercase letters from restoring backups succesfully - https://github.com/ansible/awx/pull/7519
- Fixed a bug which allowed the creation (in the Tower API) of Groups and Hosts with the same name - https://github.com/ansible/awx/issues/4680
## 13.0.0 (Jun 23, 2020)
- Added import and export commands to the official AWX CLI, replacing send and receive from the old tower-cli (https://github.com/ansible/awx/pull/6125).
- Removed scripts as a means of running inventory updates of built-in types (https://github.com/ansible/awx/pull/6911)
- Ansible 2.8 is now partially unsupported; some inventory source types are known to no longer work.
- Fixed an issue where the vmware inventory source ssl_verify source variable was not recognized (https://github.com/ansible/awx/pull/7360)
- Fixed a bug that caused redis' listen socket to have too-permissive file permissions (https://github.com/ansible/awx/pull/7317)
- Fixed a bug that caused rsyslogd's configuration file to have world-readable file permissions, potentially leaking secrets (CVE-2020-10782)
## 12.0.0 (Jun 9, 2020)
- Removed memcached as a dependency of AWX (https://github.com/ansible/awx/pull/7240)
- Moved to a single container image build instead of separate awx_web and awx_task images. The container image is just `awx` (https://github.com/ansible/awx/pull/7228)
- Official AWX container image builds now use a two-stage container build process that notably reduces the size of our published images (https://github.com/ansible/awx/pull/7017)
- Removed support for HipChat notifications ([EoL announcement](https://www.atlassian.com/partnerships/slack/faq#faq-98b17ca3-247f-423b-9a78-70a91681eff0)); all previously-created HipChat notification templates will be deleted due to this removal.
- Fixed a bug which broke AWX installations with oc version 4.3 (https://github.com/ansible/awx/pull/6948/files)
- Fixed a bug which broke AWX installations with oc version 4.3 (https://github.com/ansible/awx/pull/6948/)
- Fixed a performance issue that caused notable delay of stdout processing for playbooks run against large numbers of hosts (https://github.com/ansible/awx/issues/6991)
- Fixed a bug that caused CyberArk AIM credential plugin looks to hang forever in some environments (https://github.com/ansible/awx/issues/6986)
- Fixed a bug that caused ANY/ALL converage settings not to properly save when editing approval nodes in the UI (https://github.com/ansible/awx/issues/6998)

View File

@@ -80,7 +80,7 @@ For Linux platforms, refer to the following from Docker:
If you're not using Docker for Mac, or Docker for Windows, you may need, or choose to, install the Docker compose Python module separately, in which case you'll need to run the following:
```bash
(host)$ pip install docker-compose
(host)$ pip3 install docker-compose
```
#### Frontend Development

View File

@@ -43,7 +43,7 @@ This document provides a guide for installing AWX.
- [Installing the AWX CLI](#installing-the-awx-cli)
* [Building the CLI Documentation](#building-the-cli-documentation)
## Getting started
### Clone the repo
@@ -351,7 +351,7 @@ Once you access the AWX server, you will be prompted with a login dialog. The de
A Kubernetes deployment will require you to have access to a Kubernetes cluster as well as the following tools:
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [helm](https://docs.helm.sh/using_helm/#quickstart-guide)
- [helm](https://helm.sh/docs/intro/quickstart/)
The installation program will reference `kubectl` directly. `helm` is only necessary if you are letting the installer configure PostgreSQL for you.
@@ -382,9 +382,11 @@ Before starting the install process, review the [inventory](./installer/inventor
### Configuring Helm
If you want the AWX installer to manage creating the database pod (rather than installing and configuring postgres on your own). Then you will need to have a working `helm` installation, you can find details here: [https://docs.helm.sh/using_helm/#quickstart-guide](https://docs.helm.sh/using_helm/#quickstart-guide).
If you want the AWX installer to manage creating the database pod (rather than installing and configuring postgres on your own). Then you will need to have a working `helm` installation, you can find details here: [https://helm.sh/docs/intro/quickstart/](https://helm.sh/docs/intro/quickstart/).
Newer Kubernetes clusters with RBAC enabled will need to make sure a service account is created, make sure to follow the instructions here [https://docs.helm.sh/using_helm/#role-based-access-control](https://docs.helm.sh/using_helm/#role-based-access-control)
You do not need to create a [Persistent Volume Claim](https://docs.openshift.org/latest/dev_guide/persistent_volumes.html) as Helm does it for you. However, an existing one may be used by setting the `pg_persistence_existingclaim` variable.
Newer Kubernetes clusters with RBAC enabled will need to make sure a service account is created, make sure to follow the instructions here [https://helm.sh/docs/topics/rbac/](https://helm.sh/docs/topics/rbac/)
### Run the installer
@@ -575,7 +577,7 @@ If you're deploying using Docker Compose, container names will be prefixed by th
Immediately after the containers start, the *awx_task* container will perform required setup tasks, including database migrations. These tasks need to complete before the web interface can be accessed. To monitor the progress, you can follow the container's STDOUT by running the following:
```bash
# Tail the the awx_task log
# Tail the awx_task log
$ docker logs -f awx_task
```
@@ -651,16 +653,14 @@ Potential uses include:
* Checking on the status and output of job runs
* Managing objects like organizations, users, teams, etc...
The preferred way to install the AWX CLI is through pip directly from GitHub:
The preferred way to install the AWX CLI is through pip directly from PyPI:
pip install "https://github.com/ansible/awx/archive/$VERSION.tar.gz#egg=awxkit&subdirectory=awxkit"
pip3 install awxkit
awx --help
...where ``$VERSION`` is the version of AWX you're running. To see a list of all available releases, visit: https://github.com/ansible/awx/releases
## Building the CLI Documentation
To build the docs, spin up a real AWX server, `pip install sphinx sphinxcontrib-autoprogram`, and run:
To build the docs, spin up a real AWX server, `pip3 install sphinx sphinxcontrib-autoprogram`, and run:
~ TOWER_HOST=https://awx.example.org TOWER_USERNAME=example TOWER_PASSWORD=secret make clean html
~ cd build/html/ && python -m http.server

View File

@@ -31,7 +31,7 @@ If your issue isn't considered high priority, then please be patient as it may t
`state:needs_info` The issue needs more information. This could be more debug output, more specifics out the system such as version information. Any detail that is currently preventing this issue from moving forward. This should be considered a blocked state.
`state:needs_review` The the issue/pull request needs to be reviewed by other maintainers and contributors. This is usually used when there is a question out to another maintainer or when a person is less familar with an area of the code base the issue is for.
`state:needs_review` The issue/pull request needs to be reviewed by other maintainers and contributors. This is usually used when there is a question out to another maintainer or when a person is less familar with an area of the code base the issue is for.
`state:needs_revision` More commonly used on pull requests, this state represents that there are changes that are being waited on.

View File

@@ -6,6 +6,8 @@ recursive-include awx/templates *.html
recursive-include awx/api/templates *.md *.html
recursive-include awx/ui/templates *.html
recursive-include awx/ui/static *
recursive-include awx/ui_next/build *.html
recursive-include awx/ui_next/build *
recursive-include awx/playbooks *.yml
recursive-include awx/lib/site-packages *
recursive-include awx/plugins *.ps1

View File

@@ -79,6 +79,7 @@ clean-ui: clean-languages
rm -rf awx/ui/test/e2e/reports/
rm -rf awx/ui/client/languages/
rm -rf awx/ui_next/node_modules/
rm -rf node_modules
rm -rf awx/ui_next/coverage/
rm -rf awx/ui_next/build/locales/_build/
rm -f $(UI_DEPS_FLAG_FILE)
@@ -362,13 +363,13 @@ TEST_DIRS ?= awx/main/tests/unit awx/main/tests/functional awx/conf/tests awx/ss
# Run all API unit tests.
test:
@if [ "$(VENV_BASE)" ]; then \
if [ "$(VENV_BASE)" ]; then \
. $(VENV_BASE)/awx/bin/activate; \
fi; \
PYTHONDONTWRITEBYTECODE=1 py.test -p no:cacheprovider -n auto $(TEST_DIRS)
cmp VERSION awxkit/VERSION || "VERSION and awxkit/VERSION *must* match"
cd awxkit && $(VENV_BASE)/awx/bin/tox -re py2,py3
awx-manage check_migrations --dry-run --check -n 'vNNN_missing_migration_file'
cd awxkit && $(VENV_BASE)/awx/bin/tox -re py3
awx-manage check_migrations --dry-run --check -n 'missing_migration_file'
COLLECTION_TEST_DIRS ?= awx_collection/test/awx
COLLECTION_TEST_TARGET ?=
@@ -377,10 +378,11 @@ COLLECTION_NAMESPACE ?= awx
COLLECTION_INSTALL = ~/.ansible/collections/ansible_collections/$(COLLECTION_NAMESPACE)/$(COLLECTION_PACKAGE)
test_collection:
@if [ "$(VENV_BASE)" ]; then \
rm -f $(shell ls -d $(VENV_BASE)/awx/lib/python* | head -n 1)/no-global-site-packages.txt
if [ "$(VENV_BASE)" ]; then \
. $(VENV_BASE)/awx/bin/activate; \
fi; \
PYTHONPATH=$(PYTHONPATH):$(VENV_BASE)/awx/lib/python3.6/site-packages:/usr/lib/python3.6/site-packages py.test $(COLLECTION_TEST_DIRS)
py.test $(COLLECTION_TEST_DIRS) -v
# The python path needs to be modified so that the tests can find Ansible within the container
# First we will use anything expility set as PYTHONPATH
# Second we will load any libraries out of the virtualenv (if it's unspecified that should be ok because python should not load out of an empty directory)
@@ -400,11 +402,11 @@ symlink_collection:
build_collection:
ansible-playbook -i localhost, awx_collection/tools/template_galaxy.yml -e collection_package=$(COLLECTION_PACKAGE) -e collection_namespace=$(COLLECTION_NAMESPACE) -e collection_version=$(VERSION) -e '{"awx_template_version":false}'
ansible-galaxy collection build awx_collection --force --output-path=awx_collection
ansible-galaxy collection build awx_collection_build --force --output-path=awx_collection_build
install_collection: build_collection
rm -rf $(COLLECTION_INSTALL)
ansible-galaxy collection install awx_collection/$(COLLECTION_NAMESPACE)-$(COLLECTION_PACKAGE)-$(VERSION).tar.gz
ansible-galaxy collection install awx_collection_build/$(COLLECTION_NAMESPACE)-$(COLLECTION_PACKAGE)-$(VERSION).tar.gz
test_collection_sanity: install_collection
cd $(COLLECTION_INSTALL) && ansible-test sanity
@@ -567,14 +569,28 @@ ui-zuul-lint-and-test:
# UI NEXT TASKS
# --------------------------------------
ui-next-lint:
awx/ui_next/node_modules:
$(NPM_BIN) --prefix awx/ui_next install
$(NPM_BIN) run --prefix awx/ui_next lint
$(NPM_BIN) run --prefix awx/ui_next prettier-check
ui-next-test:
$(NPM_BIN) --prefix awx/ui_next install
$(NPM_BIN) run --prefix awx/ui_next test
ui-release-next:
mkdir -p awx/ui_next/build/static
touch awx/ui_next/build/static/.placeholder
ui-devel-next: awx/ui_next/node_modules
$(NPM_BIN) --prefix awx/ui_next run extract-strings
$(NPM_BIN) --prefix awx/ui_next run compile-strings
$(NPM_BIN) --prefix awx/ui_next run build
mkdir -p awx/public/static/css
mkdir -p awx/public/static/js
mkdir -p awx/public/static/media
cp -r awx/ui_next/build/static/css/* awx/public/static/css
cp -r awx/ui_next/build/static/js/* awx/public/static/js
cp -r awx/ui_next/build/static/media/* awx/public/static/media
clean-ui-next:
rm -rf node_modules
rm -rf awx/ui_next/node_modules
rm -rf awx/ui_next/build
ui-next-zuul-lint-and-test:
$(NPM_BIN) --prefix awx/ui_next install
@@ -593,10 +609,10 @@ dev_build:
release_build:
$(PYTHON) setup.py release_build
dist/$(SDIST_TAR_FILE): ui-release VERSION
dist/$(SDIST_TAR_FILE): ui-release ui-release-next VERSION
$(PYTHON) setup.py $(SDIST_COMMAND)
dist/$(WHEEL_FILE): ui-release
dist/$(WHEEL_FILE): ui-release ui-release-next
$(PYTHON) setup.py $(WHEEL_COMMAND)
sdist: dist/$(SDIST_TAR_FILE)

View File

@@ -1 +1 @@
12.0.0
15.0.0

View File

@@ -146,7 +146,7 @@ class FieldLookupBackend(BaseFilterBackend):
# A list of fields that we know can be filtered on without the possiblity
# of introducing duplicates
NO_DUPLICATES_WHITELIST = (CharField, IntegerField, BooleanField)
NO_DUPLICATES_ALLOW_LIST = (CharField, IntegerField, BooleanField)
def get_fields_from_lookup(self, model, lookup):
@@ -205,7 +205,7 @@ class FieldLookupBackend(BaseFilterBackend):
field_list, new_lookup = self.get_fields_from_lookup(model, lookup)
field = field_list[-1]
needs_distinct = (not all(isinstance(f, self.NO_DUPLICATES_WHITELIST) for f in field_list))
needs_distinct = (not all(isinstance(f, self.NO_DUPLICATES_ALLOW_LIST) for f in field_list))
# Type names are stored without underscores internally, but are presented and
# and serialized over the API containing underscores so we remove `_`
@@ -257,6 +257,11 @@ class FieldLookupBackend(BaseFilterBackend):
if key in self.RESERVED_NAMES:
continue
# HACK: make `created` available via API for the Django User ORM model
# so it keep compatiblity with other objects which exposes the `created` attr.
if queryset.model._meta.object_name == 'User' and key.startswith('created'):
key = key.replace('created', 'date_joined')
# HACK: Make job event filtering by host name mostly work even
# when not capturing job event hosts M2M.
if queryset.model._meta.object_name == 'JobEvent' and key.startswith('hosts__name'):

View File

@@ -51,6 +51,7 @@ from awx.main.utils import (
StubLicense
)
from awx.main.utils.db import get_all_field_names
from awx.main.views import ApiErrorView
from awx.api.serializers import ResourceAccessListElementSerializer, CopySerializer, UserSerializer
from awx.api.versioning import URLPathVersioning
from awx.api.metadata import SublistAttachDetatchMetadata, Metadata
@@ -159,11 +160,11 @@ class APIView(views.APIView):
self.queries_before = len(connection.queries)
# If there are any custom headers in REMOTE_HOST_HEADERS, make sure
# they respect the proxy whitelist
# they respect the allowed proxy list
if all([
settings.PROXY_IP_WHITELIST,
request.environ.get('REMOTE_ADDR') not in settings.PROXY_IP_WHITELIST,
request.environ.get('REMOTE_HOST') not in settings.PROXY_IP_WHITELIST
settings.PROXY_IP_ALLOWED_LIST,
request.environ.get('REMOTE_ADDR') not in settings.PROXY_IP_ALLOWED_LIST,
request.environ.get('REMOTE_HOST') not in settings.PROXY_IP_ALLOWED_LIST
]):
for custom_header in settings.REMOTE_HOST_HEADERS:
if custom_header.startswith('HTTP_'):
@@ -188,6 +189,29 @@ class APIView(views.APIView):
'''
Log warning for 400 requests. Add header with elapsed time.
'''
#
# If the URL was rewritten, and we get a 404, we should entirely
# replace the view in the request context with an ApiErrorView()
# Without this change, there will be subtle differences in the BrowseableAPIRenderer
#
# These differences could provide contextual clues which would allow
# anonymous users to determine if usernames were valid or not
# (e.g., if an anonymous user visited `/api/v2/users/valid/`, and got a 404,
# but also saw that the page heading said "User Detail", they might notice
# that's a difference in behavior from a request to `/api/v2/users/not-valid/`, which
# would show a page header of "Not Found"). Changing the view here
# guarantees that the rendered response will look exactly like the response
# when you visit a URL that has no matching URL paths in `awx.api.urls`.
#
if response.status_code == 404 and 'awx.named_url_rewritten' in request.environ:
self.headers.pop('Allow', None)
response = super(APIView, self).finalize_response(request, response, *args, **kwargs)
view = ApiErrorView()
setattr(view, 'request', request)
response.renderer_context['view'] = view
return response
if response.status_code >= 400:
status_msg = "status %s received by user %s attempting to access %s from %s" % \
(response.status_code, request.user, request.path, request.META.get('REMOTE_ADDR', None))
@@ -837,7 +861,7 @@ class CopyAPIView(GenericAPIView):
@staticmethod
def _decrypt_model_field_if_needed(obj, field_name, field_val):
if field_name in getattr(type(obj), 'REENCRYPTION_BLACKLIST_AT_COPY', []):
if field_name in getattr(type(obj), 'REENCRYPTION_BLOCKLIST_AT_COPY', []):
return field_val
if isinstance(obj, Credential) and field_name == 'inputs':
for secret in obj.credential_type.secret_fields:
@@ -883,7 +907,7 @@ class CopyAPIView(GenericAPIView):
field_val = getattr(obj, field.name)
except AttributeError:
continue
# Adjust copy blacklist fields here.
# Adjust copy blocked fields here.
if field.name in fields_to_discard or field.name in [
'id', 'pk', 'polymorphic_ctype', 'unifiedjobtemplate_ptr', 'created_by', 'modified_by'
] or field.name.endswith('_role'):
@@ -980,7 +1004,7 @@ class CopyAPIView(GenericAPIView):
if hasattr(new_obj, 'admin_role') and request.user not in new_obj.admin_role.members.all():
new_obj.admin_role.members.add(request.user)
if sub_objs:
# store the copied object dict into memcached, because it's
# store the copied object dict into cache, because it's
# often too large for postgres' notification bus
# (which has a default maximum message size of 8k)
key = 'deep-copy-{}'.format(str(uuid.uuid4()))

View File

@@ -23,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.models import InventorySource, NotificationTemplate
from awx.main.models import NotificationTemplate
from awx.main.scheduler.kubernetes import PodManager
@@ -115,19 +115,6 @@ class Metadata(metadata.SimpleMetadata):
if getattr(field, 'write_only', False):
field_info['write_only'] = True
# Special handling of inventory source_region choices that vary based on
# selected inventory source.
if field.field_name == 'source_regions':
for cp in ('azure_rm', 'ec2', 'gce'):
get_regions = getattr(InventorySource, 'get_%s_region_choices' % cp)
field_info['%s_region_choices' % cp] = get_regions()
# Special handling of group_by choices for EC2.
if field.field_name == 'group_by':
for cp in ('ec2',):
get_group_by_choices = getattr(InventorySource, 'get_%s_group_by_choices' % cp)
field_info['%s_group_by_choices' % cp] = get_group_by_choices()
# Special handling of notification configuration where the required properties
# are conditional on the type selected.
if field.field_name == 'notification_configuration':

View File

@@ -7,6 +7,24 @@ from prometheus_client.parser import text_string_to_metric_families
# Django REST Framework
from rest_framework import renderers
from rest_framework.request import override_method
from rest_framework.utils import encoders
class SurrogateEncoder(encoders.JSONEncoder):
def encode(self, obj):
ret = super(SurrogateEncoder, self).encode(obj)
try:
ret.encode()
except UnicodeEncodeError as e:
if 'surrogates not allowed' in e.reason:
ret = ret.encode('utf-8', 'replace').decode()
return ret
class DefaultJSONRenderer(renderers.JSONRenderer):
encoder_class = SurrogateEncoder
class BrowsableAPIRenderer(renderers.BrowsableAPIRenderer):

View File

@@ -126,7 +126,7 @@ SUMMARIZABLE_FK_FIELDS = {
'current_job': DEFAULT_SUMMARY_FIELDS + ('status', 'failed', 'license_error'),
'inventory_source': ('source', 'last_updated', 'status'),
'custom_inventory_script': DEFAULT_SUMMARY_FIELDS,
'source_script': ('name', 'description'),
'source_script': DEFAULT_SUMMARY_FIELDS,
'role': ('id', 'role_field'),
'notification_template': DEFAULT_SUMMARY_FIELDS,
'instance_group': ('id', 'name', 'controller_id', 'is_containerized'),
@@ -1269,6 +1269,7 @@ class OrganizationSerializer(BaseSerializer):
object_roles = self.reverse('api:organization_object_roles_list', kwargs={'pk': obj.pk}),
access_list = self.reverse('api:organization_access_list', kwargs={'pk': obj.pk}),
instance_groups = self.reverse('api:organization_instance_groups_list', kwargs={'pk': obj.pk}),
galaxy_credentials = self.reverse('api:organization_galaxy_credentials_list', kwargs={'pk': obj.pk}),
))
return res
@@ -1336,6 +1337,8 @@ class ProjectOptionsSerializer(BaseSerializer):
attrs.pop('local_path', None)
if 'local_path' in attrs and attrs['local_path'] not in valid_local_paths:
errors['local_path'] = _('This path is already being used by another manual project.')
if attrs.get('scm_branch') and scm_type == 'archive':
errors['scm_branch'] = _('SCM branch cannot be used with archive projects.')
if attrs.get('scm_refspec') and scm_type != 'git':
errors['scm_refspec'] = _('SCM refspec can only be used with git projects.')
@@ -1697,9 +1700,13 @@ class HostSerializer(BaseSerializerWithVariables):
d.setdefault('recent_jobs', [{
'id': j.job.id,
'name': j.job.job_template.name if j.job.job_template is not None else "",
'type': j.job.job_type_name,
'status': j.job.status,
'finished': j.job.finished,
} for j in obj.job_host_summaries.select_related('job__job_template').order_by('-created')[:5]])
} for j in obj.job_host_summaries.select_related('job__job_template').order_by('-created').defer(
'job__extra_vars',
'job__artifacts',
)[:5]])
return d
def _get_host_port_from_name(self, name):
@@ -1731,6 +1738,7 @@ class HostSerializer(BaseSerializerWithVariables):
def validate(self, attrs):
name = force_text(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:
@@ -1739,7 +1747,9 @@ class HostSerializer(BaseSerializerWithVariables):
vars_dict = parse_yaml_or_json(variables)
vars_dict['ansible_ssh_port'] = port
attrs['variables'] = json.dumps(vars_dict)
if Group.objects.filter(name=name, inventory=inventory).exists():
raise serializers.ValidationError(_('A Group with that name already exists.'))
return super(HostSerializer, self).validate(attrs)
def to_representation(self, obj):
@@ -1805,6 +1815,13 @@ class GroupSerializer(BaseSerializerWithVariables):
res['inventory'] = self.reverse('api:inventory_detail', kwargs={'pk': obj.inventory.pk})
return res
def validate(self, attrs):
name = force_text(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.'))
return super(GroupSerializer, self).validate(attrs)
def validate_name(self, value):
if value in ('all', '_meta'):
raise serializers.ValidationError(_('Invalid group name.'))
@@ -1921,7 +1938,7 @@ class InventorySourceOptionsSerializer(BaseSerializer):
class Meta:
fields = ('*', 'source', 'source_path', 'source_script', 'source_vars', 'credential',
'source_regions', 'instance_filters', 'group_by', 'overwrite', 'overwrite_vars',
'enabled_var', 'enabled_value', 'host_filter', 'overwrite', 'overwrite_vars',
'custom_virtualenv', 'timeout', 'verbosity')
def get_related(self, obj):
@@ -1936,12 +1953,12 @@ class InventorySourceOptionsSerializer(BaseSerializer):
def validate_source_vars(self, value):
ret = vars_validate_or_raise(value)
for env_k in parse_yaml_or_json(value):
if env_k in settings.INV_ENV_VARIABLE_BLACKLIST:
if env_k in settings.INV_ENV_VARIABLE_BLOCKED:
raise serializers.ValidationError(_("`{}` is a prohibited environment variable".format(env_k)))
return ret
def validate(self, attrs):
# TODO: Validate source, validate source_regions
# TODO: Validate source
errors = {}
source = attrs.get('source', self.instance and self.instance.source or '')
@@ -2520,10 +2537,11 @@ class CredentialTypeSerializer(BaseSerializer):
class CredentialSerializer(BaseSerializer):
show_capabilities = ['edit', 'delete', 'copy', 'use']
capabilities_prefetch = ['admin', 'use']
managed_by_tower = serializers.ReadOnlyField()
class Meta:
model = Credential
fields = ('*', 'organization', 'credential_type', 'inputs', 'kind', 'cloud', 'kubernetes')
fields = ('*', 'organization', 'credential_type', 'managed_by_tower', 'inputs', 'kind', 'cloud', 'kubernetes')
extra_kwargs = {
'credential_type': {
'label': _('Credential Type'),
@@ -2587,6 +2605,13 @@ class CredentialSerializer(BaseSerializer):
return summary_dict
def validate(self, attrs):
if self.instance and self.instance.managed_by_tower:
raise PermissionDenied(
detail=_("Modifications not allowed for managed credentials")
)
return super(CredentialSerializer, self).validate(attrs)
def get_validation_exclusions(self, obj=None):
ret = super(CredentialSerializer, self).get_validation_exclusions(obj)
for field in ('credential_type', 'inputs'):
@@ -2594,6 +2619,17 @@ class CredentialSerializer(BaseSerializer):
ret.remove(field)
return ret
def validate_organization(self, org):
if (
self.instance and
self.instance.credential_type.kind == 'galaxy' and
org is None
):
raise serializers.ValidationError(_(
"Galaxy credentials must be owned by an Organization."
))
return org
def validate_credential_type(self, credential_type):
if self.instance and credential_type.pk != self.instance.credential_type.pk:
for related_objects in (
@@ -2644,12 +2680,29 @@ class CredentialSerializerCreate(CredentialSerializer):
owner_fields.add(field)
else:
attrs.pop(field)
if not owner_fields:
raise serializers.ValidationError({"detail": _("Missing 'user', 'team', or 'organization'.")})
if len(owner_fields) > 1:
received = ", ".join(sorted(owner_fields))
raise serializers.ValidationError({"detail": _(
"Only one of 'user', 'team', or 'organization' should be provided, "
"received {} fields.".format(received)
)})
if attrs.get('team'):
attrs['organization'] = attrs['team'].organization
if (
'credential_type' in attrs and
attrs['credential_type'].kind == 'galaxy' and
list(owner_fields) != ['organization']
):
raise serializers.ValidationError({"organization": _(
"Galaxy credentials must be owned by an Organization."
)})
return super(CredentialSerializerCreate, self).validate(attrs)
def create(self, validated_data):
@@ -2823,7 +2876,7 @@ class JobTemplateMixin(object):
return [{
'id': x.id, 'status': x.status, 'finished': x.finished, 'canceled_on': x.canceled_on,
# Make type consistent with API top-level key, for instance workflow_job
'type': x.get_real_instance_class()._meta.verbose_name.replace(' ', '_')
'type': x.job_type_name
} for x in optimized_qs[:10]]
def get_summary_fields(self, obj):
@@ -4081,7 +4134,8 @@ class JobLaunchSerializer(BaseSerializer):
errors.setdefault('credentials', []).append(_(
'Cannot assign multiple {} credentials.'
).format(cred.unique_hash(display=True)))
if cred.credential_type.kind not in ('ssh', 'vault', 'cloud', 'net'):
if cred.credential_type.kind not in ('ssh', 'vault', 'cloud',
'net', 'kubernetes'):
errors.setdefault('credentials', []).append(_(
'Cannot assign a Credential of kind `{}`'
).format(cred.credential_type.kind))
@@ -4103,7 +4157,10 @@ class JobLaunchSerializer(BaseSerializer):
# verify that credentials (either provided or existing) don't
# require launch-time passwords that have not been provided
if 'credentials' in accepted:
launch_credentials = accepted['credentials']
launch_credentials = Credential.unique_dict(
list(template_credentials.all()) +
list(accepted['credentials'])
).values()
else:
launch_credentials = template_credentials
passwords = attrs.get('credential_passwords', {}) # get from original attrs
@@ -4645,6 +4702,8 @@ class InstanceSerializer(BaseSerializer):
class InstanceGroupSerializer(BaseSerializer):
show_capabilities = ['edit', 'delete']
committed_capacity = serializers.SerializerMethodField()
consumed_capacity = serializers.SerializerMethodField()
percent_capacity_remaining = serializers.SerializerMethodField()

View File

@@ -21,6 +21,7 @@ from awx.api.views import (
OrganizationNotificationTemplatesSuccessList,
OrganizationNotificationTemplatesApprovalList,
OrganizationInstanceGroupsList,
OrganizationGalaxyCredentialsList,
OrganizationObjectRolesList,
OrganizationAccessList,
OrganizationApplicationList,
@@ -49,6 +50,7 @@ urls = [
url(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'),

View File

@@ -14,6 +14,8 @@ import time
from base64 import b64encode
from collections import OrderedDict
from urllib3.exceptions import ConnectTimeoutError
# Django
from django.conf import settings
@@ -122,6 +124,7 @@ from awx.api.views.organization import ( # noqa
OrganizationNotificationTemplatesSuccessList,
OrganizationNotificationTemplatesApprovalList,
OrganizationInstanceGroupsList,
OrganizationGalaxyCredentialsList,
OrganizationAccessList,
OrganizationObjectRolesList,
)
@@ -171,6 +174,15 @@ def api_exception_handler(exc, context):
exc = ParseError(exc.args[0])
if isinstance(context['view'], UnifiedJobStdout):
context['view'].renderer_classes = [renderers.BrowsableAPIRenderer, JSONRenderer]
if isinstance(exc, APIException):
req = context['request']._request
if 'awx.named_url_rewritten' in req.environ and not str(getattr(exc, 'status_code', 0)).startswith('2'):
# if the URL was rewritten, and it's not a 2xx level status code,
# revert the request.path to its original value to avoid leaking
# any context about the existance of resources
req.path = req.environ['awx.named_url_rewritten']
if exc.status_code == 403:
exc = NotFound(detail=_('Not found.'))
return exception_handler(exc, context)
@@ -231,6 +243,8 @@ class DashboardView(APIView):
svn_failed_projects = svn_projects.filter(last_job_failed=True)
hg_projects = user_projects.filter(scm_type='hg')
hg_failed_projects = hg_projects.filter(last_job_failed=True)
archive_projects = user_projects.filter(scm_type='archive')
archive_failed_projects = archive_projects.filter(last_job_failed=True)
data['scm_types'] = {}
data['scm_types']['git'] = {'url': reverse('api:project_list', request=request) + "?scm_type=git",
'label': 'Git',
@@ -247,6 +261,11 @@ class DashboardView(APIView):
'failures_url': reverse('api:project_list', request=request) + "?scm_type=hg&last_job_failed=True",
'total': hg_projects.count(),
'failed': hg_failed_projects.count()}
data['scm_types']['archive'] = {'url': reverse('api:project_list', request=request) + "?scm_type=archive",
'label': 'Remote Archive',
'failures_url': reverse('api:project_list', request=request) + "?scm_type=archive&last_job_failed=True",
'total': archive_projects.count(),
'failed': archive_failed_projects.count()}
user_list = get_user_queryset(request.user, models.User)
team_list = get_user_queryset(request.user, models.Team)
@@ -1337,6 +1356,13 @@ class CredentialDetail(RetrieveUpdateDestroyAPIView):
model = models.Credential
serializer_class = serializers.CredentialSerializer
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.managed_by_tower:
raise PermissionDenied(detail=_("Deletion not allowed for managed credentials"))
return super(CredentialDetail, self).destroy(request, *args, **kwargs)
class CredentialActivityStreamList(SubListAPIView):
@@ -1397,10 +1423,18 @@ class CredentialExternalTest(SubDetailAPIView):
obj.credential_type.plugin.backend(**backend_kwargs)
return Response({}, status=status.HTTP_202_ACCEPTED)
except requests.exceptions.HTTPError as exc:
message = 'HTTP {}\n{}'.format(exc.response.status_code, exc.response.text)
message = 'HTTP {}'.format(exc.response.status_code)
return Response({'inputs': message}, status=status.HTTP_400_BAD_REQUEST)
except Exception as exc:
return Response({'inputs': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
message = exc.__class__.__name__
args = getattr(exc, 'args', [])
for a in args:
if isinstance(
getattr(a, 'reason', None),
ConnectTimeoutError
):
message = str(a.reason)
return Response({'inputs': message}, status=status.HTTP_400_BAD_REQUEST)
class CredentialInputSourceDetail(RetrieveUpdateDestroyAPIView):
@@ -1449,10 +1483,18 @@ class CredentialTypeExternalTest(SubDetailAPIView):
obj.plugin.backend(**backend_kwargs)
return Response({}, status=status.HTTP_202_ACCEPTED)
except requests.exceptions.HTTPError as exc:
message = 'HTTP {}\n{}'.format(exc.response.status_code, exc.response.text)
message = 'HTTP {}'.format(exc.response.status_code)
return Response({'inputs': message}, status=status.HTTP_400_BAD_REQUEST)
except Exception as exc:
return Response({'inputs': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
message = exc.__class__.__name__
args = getattr(exc, 'args', [])
for a in args:
if isinstance(
getattr(a, 'reason', None),
ConnectTimeoutError
):
message = str(a.reason)
return Response({'inputs': message}, status=status.HTTP_400_BAD_REQUEST)
class HostRelatedSearchMixin(object):
@@ -2657,7 +2699,7 @@ class JobTemplateCredentialsList(SubListCreateAttachDetachAPIView):
return {"error": _("Cannot assign multiple {credential_type} credentials.").format(
credential_type=sub.unique_hash(display=True))}
kind = sub.credential_type.kind
if kind not in ('ssh', 'vault', 'cloud', 'net'):
if kind not in ('ssh', 'vault', 'cloud', 'net', 'kubernetes'):
return {'error': _('Cannot assign a Credential of kind `{}`.').format(kind)}
return super(JobTemplateCredentialsList, self).is_valid_relation(parent, sub, created)

View File

@@ -134,7 +134,8 @@ class InventoryDetail(RelatedJobsPreventDeleteMixin, ControlledByScmMixin, Retri
# Do not allow changes to an Inventory kind.
if kind is not None and obj.kind != kind:
return self.http_method_not_allowed(request, *args, **kwargs)
return Response(dict(error=_('You cannot turn a regular inventory into a "smart" inventory.')),
status=status.HTTP_405_METHOD_NOT_ALLOWED)
return super(InventoryDetail, self).update(request, *args, **kwargs)
def destroy(self, request, *args, **kwargs):

View File

@@ -22,7 +22,7 @@ from awx.api.generics import (
)
logger = logging.getLogger('awx.main.analytics')
logger = logging.getLogger('awx.analytics')
class MetricsView(APIView):

View File

@@ -7,6 +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 _
# AWX
from awx.main.models import (
@@ -20,7 +21,8 @@ from awx.main.models import (
Role,
User,
Team,
InstanceGroup
InstanceGroup,
Credential
)
from awx.api.generics import (
ListCreateAPIView,
@@ -42,7 +44,8 @@ from awx.api.serializers import (
RoleSerializer,
NotificationTemplateSerializer,
InstanceGroupSerializer,
ProjectSerializer, JobTemplateSerializer, WorkflowJobTemplateSerializer
ProjectSerializer, JobTemplateSerializer, WorkflowJobTemplateSerializer,
CredentialSerializer
)
from awx.api.views.mixin import (
RelatedJobsPreventDeleteMixin,
@@ -214,6 +217,20 @@ class OrganizationInstanceGroupsList(SubListAttachDetachAPIView):
relationship = 'instance_groups'
class OrganizationGalaxyCredentialsList(SubListAttachDetachAPIView):
model = Credential
serializer_class = CredentialSerializer
parent_model = Organization
relationship = 'galaxy_credentials'
def is_valid_relation(self, parent, sub, created=False):
if sub.kind != 'galaxy_api_token':
return {'msg': _(
f"Credential must be a Galaxy credential, not {sub.credential_type.name}."
)}
class OrganizationAccessList(ResourceAccessList):
model = User # needs to be User for AccessLists's

View File

@@ -21,6 +21,7 @@ import requests
from awx.api.generics import APIView
from awx.conf.registry import settings_registry
from awx.main.analytics import all_collectors
from awx.main.ha import is_ha_environment
from awx.main.utils import (
get_awx_version,
@@ -252,6 +253,7 @@ class ApiV2ConfigView(APIView):
ansible_version=get_ansible_version(),
eula=render_to_string("eula.md") if license_data.get('license_type', 'UNLICENSED') != 'open' else '',
analytics_status=pendo_state,
analytics_collectors=all_collectors(),
become_methods=PRIVILEGE_ESCALATION_METHODS,
)

View File

@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
from awx.conf.migrations import _rename_setting
def copy_allowed_ips(apps, schema_editor):
_rename_setting.rename_setting(apps, schema_editor, old_key='PROXY_IP_WHITELIST', new_key='PROXY_IP_ALLOWED_LIST')
class Migration(migrations.Migration):
dependencies = [
('conf', '0006_v331_ldap_group_type'),
]
operations = [
migrations.RunPython(copy_allowed_ips),
]

View File

@@ -17,6 +17,8 @@ from django.utils.functional import cached_property
# Django REST Framework
from rest_framework.fields import empty, SkipField
import cachetools
# Tower
from awx.main.utils import encrypt_field, decrypt_field
from awx.conf import settings_registry
@@ -28,21 +30,23 @@ from awx.conf.migrations._reencrypt import decrypt_field as old_decrypt_field
logger = logging.getLogger('awx.conf.settings')
SETTING_MEMORY_TTL = 5 if 'callback_receiver' in ' '.join(sys.argv) else 0
# Store a special value to indicate when a setting is not set in the database.
SETTING_CACHE_NOTSET = '___notset___'
# Cannot store None in memcached; use a special value instead to indicate None.
# Cannot store None in cache; use a special value instead to indicate None.
# If the special value for None is the same as the "not set" value, then a value
# of None will be equivalent to the setting not being set (and will raise an
# AttributeError if there is no other default defined).
# SETTING_CACHE_NONE = '___none___'
SETTING_CACHE_NONE = SETTING_CACHE_NOTSET
# Cannot store empty list/tuple in memcached; use a special value instead to
# Cannot store empty list/tuple in cache; use a special value instead to
# indicate an empty list.
SETTING_CACHE_EMPTY_LIST = '___[]___'
# Cannot store empty dict in memcached; use a special value instead to indicate
# Cannot store empty dict in cache; use a special value instead to indicate
# an empty dict.
SETTING_CACHE_EMPTY_DICT = '___{}___'
@@ -406,6 +410,7 @@ class SettingsWrapper(UserSettingsHolder):
def SETTINGS_MODULE(self):
return self._get_default('SETTINGS_MODULE')
@cachetools.cached(cache=cachetools.TTLCache(maxsize=2048, ttl=SETTING_MEMORY_TTL))
def __getattr__(self, name):
value = empty
if name in self.all_supported_settings:

View File

@@ -29,9 +29,10 @@ def reg(request):
# as "defined in a settings file". This is analogous to manually
# specifying a setting on the filesystem (e.g., in a local_settings.py in
# development, or in /etc/tower/conf.d/<something>.py)
defaults = request.node.get_marker('defined_in_file')
if defaults:
settings.configure(**defaults.kwargs)
for marker in request.node.own_markers:
if marker.name == 'defined_in_file':
settings.configure(**marker.kwargs)
settings._wrapped = SettingsWrapper(settings._wrapped,
cache,
registry)

View File

@@ -41,13 +41,16 @@ def settings(request):
cache = LocMemCache(str(uuid4()), {}) # make a new random cache each time
settings = LazySettings()
registry = SettingsRegistry(settings)
defaults = {}
# @pytest.mark.defined_in_file can be used to mark specific setting values
# as "defined in a settings file". This is analogous to manually
# specifying a setting on the filesystem (e.g., in a local_settings.py in
# development, or in /etc/tower/conf.d/<something>.py)
in_file_marker = request.node.get_marker('defined_in_file')
defaults = in_file_marker.kwargs if in_file_marker else {}
for marker in request.node.own_markers:
if marker.name == 'defined_in_file':
defaults = marker.kwargs
defaults['DEFAULTS_SNAPSHOT'] = {}
settings.configure(**defaults)
settings._wrapped = SettingsWrapper(settings._wrapped,
@@ -63,15 +66,6 @@ def test_unregistered_setting(settings):
assert settings.cache.get('DEBUG') is None
def test_cached_settings_unicode_is_auto_decoded(settings):
# https://github.com/linsomniac/python-memcached/issues/79
# https://github.com/linsomniac/python-memcached/blob/288c159720eebcdf667727a859ef341f1e908308/memcache.py#L961
value = 'Iñtërnâtiônàlizætiøn' # this simulates what python-memcached does on cache.set()
settings.cache.set('DEBUG', value)
assert settings.cache.get('DEBUG') == 'Iñtërnâtiônàlizætiøn'
def test_read_only_setting(settings):
settings.registry.register(
'AWX_READ_ONLY',
@@ -251,31 +245,6 @@ def test_setting_from_db(settings, mocker):
assert settings.cache.get('AWX_SOME_SETTING') == 'FROM_DB'
@pytest.mark.parametrize('encrypted', (True, False))
def test_setting_from_db_with_unicode(settings, mocker, encrypted):
settings.registry.register(
'AWX_SOME_SETTING',
field_class=fields.CharField,
category=_('System'),
category_slug='system',
default='DEFAULT',
encrypted=encrypted
)
# this simulates a bug in python-memcached; see https://github.com/linsomniac/python-memcached/issues/79
value = 'Iñtërnâtiônàlizætiøn'
setting_from_db = mocker.Mock(id=1, key='AWX_SOME_SETTING', value=value)
mocks = mocker.Mock(**{
'order_by.return_value': mocker.Mock(**{
'__iter__': lambda self: iter([setting_from_db]),
'first.return_value': setting_from_db
}),
})
with mocker.patch('awx.conf.models.Setting.objects.filter', return_value=mocks):
assert settings.AWX_SOME_SETTING == 'Iñtërnâtiônàlizætiøn'
assert settings.cache.get('AWX_SOME_SETTING') == 'Iñtërnâtiônàlizætiøn'
@pytest.mark.defined_in_file(AWX_SOME_SETTING='DEFAULT')
def test_read_only_setting_assignment(settings):
"read-only settings cannot be overwritten"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1103,11 +1103,6 @@ class CredentialTypeAccess(BaseAccess):
def can_use(self, obj):
return True
def get_method_capability(self, method, obj, parent_obj):
if obj.managed_by_tower:
return False
return super(CredentialTypeAccess, self).get_method_capability(method, obj, parent_obj)
def filtered_queryset(self):
return self.model.objects.all()
@@ -1182,6 +1177,8 @@ class CredentialAccess(BaseAccess):
def get_user_capabilities(self, obj, **kwargs):
user_capabilities = super(CredentialAccess, self).get_user_capabilities(obj, **kwargs)
user_capabilities['use'] = self.can_use(obj)
if getattr(obj, 'managed_by_tower', False) is True:
user_capabilities['edit'] = user_capabilities['delete'] = False
return user_capabilities
@@ -1513,8 +1510,7 @@ class JobTemplateAccess(NotificationAttachMixin, BaseAccess):
thus can be made by a job template administrator which may not have access
to the any inventory, project, or credentials associated with the template.
'''
# We are white listing fields that can
field_whitelist = [
allowed_fields = [
'name', 'description', 'forks', 'limit', 'verbosity', 'extra_vars',
'job_tags', 'force_handlers', 'skip_tags', 'ask_variables_on_launch',
'ask_tags_on_launch', 'ask_job_type_on_launch', 'ask_skip_tags_on_launch',
@@ -1529,7 +1525,7 @@ class JobTemplateAccess(NotificationAttachMixin, BaseAccess):
if k not in [x.name for x in obj._meta.concrete_fields]:
continue
if hasattr(obj, k) and getattr(obj, k) != v:
if k not in field_whitelist and v != getattr(obj, '%s_id' % k, None) \
if k not in allowed_fields and v != getattr(obj, '%s_id' % k, None) \
and not (hasattr(obj, '%s_id' % k) and getattr(obj, '%s_id' % k) is None and v == ''): # Equate '' to None in the case of foreign keys
return False
return True
@@ -2480,13 +2476,16 @@ class NotificationAccess(BaseAccess):
class LabelAccess(BaseAccess):
'''
I can see/use a Label if I have permission to associated organization
I can see/use a Label if I have permission to associated organization, or to a JT that the label is on
'''
model = Label
prefetch_related = ('modified_by', 'created_by', 'organization',)
def filtered_queryset(self):
return self.model.objects.all()
return self.model.objects.filter(
Q(organization__in=Organization.accessible_pk_qs(self.user, 'read_role')) |
Q(unifiedjobtemplate_labels__in=UnifiedJobTemplate.accessible_pk_qs(self.user, 'read_role'))
)
@check_superuser
def can_add(self, data):
@@ -2751,6 +2750,9 @@ class WorkflowApprovalTemplateAccess(BaseAccess):
else:
return (self.check_related('workflow_approval_template', UnifiedJobTemplate, role_field='admin_role'))
def can_change(self, obj, data):
return self.user.can_access(WorkflowJobTemplate, 'change', obj.workflow_job_template, data={})
def can_start(self, obj, validate_license=False):
# for copying WFJTs that contain approval nodes
if self.user.is_superuser:

View File

@@ -1 +1 @@
from .core import register, gather, ship, table_version # noqa
from .core import all_collectors, expensive_collectors, register, gather, ship # noqa

View File

@@ -20,7 +20,7 @@ from django.conf import settings
BROADCAST_WEBSOCKET_REDIS_KEY_NAME = 'broadcast_websocket_stats'
logger = logging.getLogger('awx.main.analytics.broadcast_websocket')
logger = logging.getLogger('awx.analytics.broadcast_websocket')
def dt_to_seconds(dt):

View File

@@ -1,3 +1,4 @@
import io
import os
import os.path
import platform
@@ -6,13 +7,14 @@ from django.db import connection
from django.db.models import Count
from django.conf import settings
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from awx.conf.license import get_license
from awx.main.utils import (get_awx_version, get_ansible_version,
get_custom_venv_choices, camelcase_to_underscore)
from awx.main import models
from django.contrib.sessions.models import Session
from awx.main.analytics import register, table_version
from awx.main.analytics import register
'''
This module is used to define metrics collected by awx.main.analytics.gather()
@@ -31,8 +33,8 @@ data _since_ the last report date - i.e., new data in the last 24 hours)
'''
@register('config', '1.1')
def config(since):
@register('config', '1.1', description=_('General platform configuration.'))
def config(since, **kwargs):
license_info = get_license(show_key=False)
install_type = 'traditional'
if os.environ.get('container') == 'oci':
@@ -63,8 +65,8 @@ def config(since):
}
@register('counts', '1.0')
def counts(since):
@register('counts', '1.0', description=_('Counts of objects such as organizations, inventories, and projects'))
def counts(since, **kwargs):
counts = {}
for cls in (models.Organization, models.Team, models.User,
models.Inventory, models.Credential, models.Project,
@@ -98,8 +100,8 @@ def counts(since):
return counts
@register('org_counts', '1.0')
def org_counts(since):
@register('org_counts', '1.0', description=_('Counts of users and teams by organization'))
def org_counts(since, **kwargs):
counts = {}
for org in models.Organization.objects.annotate(num_users=Count('member_role__members', distinct=True),
num_teams=Count('teams', distinct=True)).values('name', 'id', 'num_users', 'num_teams'):
@@ -110,8 +112,8 @@ def org_counts(since):
return counts
@register('cred_type_counts', '1.0')
def cred_type_counts(since):
@register('cred_type_counts', '1.0', description=_('Counts of credentials by credential type'))
def cred_type_counts(since, **kwargs):
counts = {}
for cred_type in models.CredentialType.objects.annotate(num_credentials=Count(
'credentials', distinct=True)).values('name', 'id', 'managed_by_tower', 'num_credentials'):
@@ -122,8 +124,8 @@ def cred_type_counts(since):
return counts
@register('inventory_counts', '1.2')
def inventory_counts(since):
@register('inventory_counts', '1.2', description=_('Inventories, their inventory sources, and host counts'))
def inventory_counts(since, **kwargs):
counts = {}
for inv in models.Inventory.objects.filter(kind='').annotate(num_sources=Count('inventory_sources', distinct=True),
num_hosts=Count('hosts', distinct=True)).only('id', 'name', 'kind'):
@@ -147,8 +149,8 @@ def inventory_counts(since):
return counts
@register('projects_by_scm_type', '1.0')
def projects_by_scm_type(since):
@register('projects_by_scm_type', '1.0', description=_('Counts of projects by source control type'))
def projects_by_scm_type(since, **kwargs):
counts = dict(
(t[0] or 'manual', 0)
for t in models.Project.SCM_TYPE_CHOICES
@@ -166,8 +168,8 @@ def _get_isolated_datetime(last_check):
return last_check
@register('instance_info', '1.0')
def instance_info(since, include_hostnames=False):
@register('instance_info', '1.0', description=_('Cluster topology and capacity'))
def instance_info(since, include_hostnames=False, **kwargs):
info = {}
instances = models.Instance.objects.values_list('hostname').values(
'uuid', 'version', 'capacity', 'cpu', 'memory', 'managed_by_policy', 'hostname', 'last_isolated_check', 'enabled')
@@ -192,8 +194,8 @@ def instance_info(since, include_hostnames=False):
return info
@register('job_counts', '1.0')
def job_counts(since):
@register('job_counts', '1.0', description=_('Counts of jobs by status'))
def job_counts(since, **kwargs):
counts = {}
counts['total_jobs'] = models.UnifiedJob.objects.exclude(launch_type='sync').count()
counts['status'] = dict(models.UnifiedJob.objects.exclude(launch_type='sync').values_list('status').annotate(Count('status')).order_by())
@@ -202,8 +204,8 @@ def job_counts(since):
return counts
@register('job_instance_counts', '1.0')
def job_instance_counts(since):
@register('job_instance_counts', '1.0', description=_('Counts of jobs by execution node'))
def job_instance_counts(since, **kwargs):
counts = {}
job_types = models.UnifiedJob.objects.exclude(launch_type='sync').values_list(
'execution_node', 'launch_type').annotate(job_launch_type=Count('launch_type')).order_by()
@@ -217,30 +219,71 @@ def job_instance_counts(since):
return counts
@register('query_info', '1.0')
def query_info(since, collection_type):
@register('query_info', '1.0', description=_('Metadata about the analytics collected'))
def query_info(since, collection_type, until, **kwargs):
query_info = {}
query_info['last_run'] = str(since)
query_info['current_time'] = str(now())
query_info['current_time'] = str(until)
query_info['collection_type'] = collection_type
return query_info
# Copies Job Events from db to a .csv to be shipped
@table_version('events_table.csv', '1.1')
@table_version('unified_jobs_table.csv', '1.0')
@table_version('unified_job_template_table.csv', '1.0')
@table_version('workflow_job_node_table.csv', '1.0')
@table_version('workflow_job_template_node_table.csv', '1.0')
def copy_tables(since, full_path, subset=None):
def _copy_table(table, query, path):
file_path = os.path.join(path, table + '_table.csv')
file = open(file_path, 'w', encoding='utf-8')
with connection.cursor() as cursor:
cursor.copy_expert(query, file)
file.close()
return file_path
'''
The event table can be *very* large, and we have a 100MB upload limit.
Split large table dumps at dump time into a series of files.
'''
MAX_TABLE_SIZE = 200 * 1048576
class FileSplitter(io.StringIO):
def __init__(self, filespec=None, *args, **kwargs):
self.filespec = filespec
self.files = []
self.currentfile = None
self.header = None
self.counter = 0
self.cycle_file()
def cycle_file(self):
if self.currentfile:
self.currentfile.close()
self.counter = 0
fname = '{}_split{}'.format(self.filespec, len(self.files))
self.currentfile = open(fname, 'w', encoding='utf-8')
self.files.append(fname)
if self.header:
self.currentfile.write('{}\n'.format(self.header))
def file_list(self):
self.currentfile.close()
# Check for an empty dump
if len(self.header) + 1 == self.counter:
os.remove(self.files[-1])
self.files = self.files[:-1]
# If we only have one file, remove the suffix
if len(self.files) == 1:
os.rename(self.files[0],self.files[0].replace('_split0',''))
return self.files
def write(self, s):
if not self.header:
self.header = s[0:s.index('\n')]
self.counter += self.currentfile.write(s)
if self.counter >= MAX_TABLE_SIZE:
self.cycle_file()
def _copy_table(table, query, path):
file_path = os.path.join(path, table + '_table.csv')
file = FileSplitter(filespec=file_path)
with connection.cursor() as cursor:
cursor.copy_expert(query, file)
return file.file_list()
@register('events_table', '1.1', format='csv', description=_('Automation task records'), expensive=True)
def events_table(since, full_path, until, **kwargs):
events_query = '''COPY (SELECT main_jobevent.id,
main_jobevent.created,
main_jobevent.uuid,
@@ -262,16 +305,21 @@ def copy_tables(since, full_path, subset=None):
main_jobevent.event_data::json->'res'->'warnings' AS warnings,
main_jobevent.event_data::json->'res'->'deprecations' AS deprecations
FROM main_jobevent
WHERE main_jobevent.created > {}
ORDER BY main_jobevent.id ASC) TO STDOUT WITH CSV HEADER'''.format(since.strftime("'%Y-%m-%d %H:%M:%S'"))
if not subset or 'events' in subset:
_copy_table(table='events', query=events_query, path=full_path)
WHERE (main_jobevent.created > '{}' AND main_jobevent.created <= '{}')
ORDER BY main_jobevent.id ASC) TO STDOUT WITH CSV HEADER
'''.format(since.isoformat(),until.isoformat())
return _copy_table(table='events', query=events_query, path=full_path)
@register('unified_jobs_table', '1.1', format='csv', description=_('Data on jobs run'), expensive=True)
def unified_jobs_table(since, full_path, until, **kwargs):
unified_job_query = '''COPY (SELECT main_unifiedjob.id,
main_unifiedjob.polymorphic_ctype_id,
django_content_type.model,
main_unifiedjob.organization_id,
main_organization.name as organization_name,
main_job.inventory_id,
main_inventory.name as inventory_name,
main_unifiedjob.created,
main_unifiedjob.name,
main_unifiedjob.unified_job_template_id,
@@ -289,13 +337,19 @@ def copy_tables(since, full_path, subset=None):
main_unifiedjob.instance_group_id
FROM main_unifiedjob
JOIN django_content_type ON main_unifiedjob.polymorphic_ctype_id = django_content_type.id
LEFT JOIN main_job ON main_unifiedjob.id = main_job.unifiedjob_ptr_id
LEFT JOIN main_inventory ON main_job.inventory_id = main_inventory.id
LEFT JOIN main_organization ON main_organization.id = main_unifiedjob.organization_id
WHERE (main_unifiedjob.created > {0} OR main_unifiedjob.finished > {0})
WHERE ((main_unifiedjob.created > '{0}' AND main_unifiedjob.created <= '{1}')
OR (main_unifiedjob.finished > '{0}' AND main_unifiedjob.finished <= '{1}'))
AND main_unifiedjob.launch_type != 'sync'
ORDER BY main_unifiedjob.id ASC) TO STDOUT WITH CSV HEADER'''.format(since.strftime("'%Y-%m-%d %H:%M:%S'"))
if not subset or 'unified_jobs' in subset:
_copy_table(table='unified_jobs', query=unified_job_query, path=full_path)
ORDER BY main_unifiedjob.id ASC) TO STDOUT WITH CSV HEADER
'''.format(since.isoformat(),until.isoformat())
return _copy_table(table='unified_jobs', query=unified_job_query, path=full_path)
@register('unified_job_template_table', '1.0', format='csv', description=_('Data on job templates'))
def unified_job_template_table(since, full_path, **kwargs):
unified_job_template_query = '''COPY (SELECT main_unifiedjobtemplate.id,
main_unifiedjobtemplate.polymorphic_ctype_id,
django_content_type.model,
@@ -314,9 +368,11 @@ def copy_tables(since, full_path, subset=None):
FROM main_unifiedjobtemplate, django_content_type
WHERE main_unifiedjobtemplate.polymorphic_ctype_id = django_content_type.id
ORDER BY main_unifiedjobtemplate.id ASC) TO STDOUT WITH CSV HEADER'''
if not subset or 'unified_job_template' in subset:
_copy_table(table='unified_job_template', query=unified_job_template_query, path=full_path)
return _copy_table(table='unified_job_template', query=unified_job_template_query, path=full_path)
@register('workflow_job_node_table', '1.0', format='csv', description=_('Data on workflow runs'), expensive=True)
def workflow_job_node_table(since, full_path, until, **kwargs):
workflow_job_node_query = '''COPY (SELECT main_workflowjobnode.id,
main_workflowjobnode.created,
main_workflowjobnode.modified,
@@ -345,11 +401,14 @@ def copy_tables(since, full_path, subset=None):
FROM main_workflowjobnode_always_nodes
GROUP BY from_workflowjobnode_id
) always_nodes ON main_workflowjobnode.id = always_nodes.from_workflowjobnode_id
WHERE main_workflowjobnode.modified > {}
ORDER BY main_workflowjobnode.id ASC) TO STDOUT WITH CSV HEADER'''.format(since.strftime("'%Y-%m-%d %H:%M:%S'"))
if not subset or 'workflow_job_node' in subset:
_copy_table(table='workflow_job_node', query=workflow_job_node_query, path=full_path)
WHERE (main_workflowjobnode.modified > '{}' AND main_workflowjobnode.modified <= '{}')
ORDER BY main_workflowjobnode.id ASC) TO STDOUT WITH CSV HEADER
'''.format(since.isoformat(),until.isoformat())
return _copy_table(table='workflow_job_node', query=workflow_job_node_query, path=full_path)
@register('workflow_job_template_node_table', '1.0', format='csv', description=_('Data on workflows'))
def workflow_job_template_node_table(since, full_path, **kwargs):
workflow_job_template_node_query = '''COPY (SELECT main_workflowjobtemplatenode.id,
main_workflowjobtemplatenode.created,
main_workflowjobtemplatenode.modified,
@@ -377,7 +436,4 @@ def copy_tables(since, full_path, subset=None):
GROUP BY from_workflowjobtemplatenode_id
) always_nodes ON main_workflowjobtemplatenode.id = always_nodes.from_workflowjobtemplatenode_id
ORDER BY main_workflowjobtemplatenode.id ASC) TO STDOUT WITH CSV HEADER'''
if not subset or 'workflow_job_template_node' in subset:
_copy_table(table='workflow_job_template_node', query=workflow_job_template_node_query, path=full_path)
return
return _copy_table(table='workflow_job_template_node', query=workflow_job_template_node_query, path=full_path)

View File

@@ -14,17 +14,13 @@ from rest_framework.exceptions import PermissionDenied
from awx.conf.license import get_license
from awx.main.models import Job
from awx.main.access import access_registry
from awx.main.models.ha import TowerAnalyticsState
from awx.main.utils import get_awx_http_client_headers, set_environ
__all__ = ['register', 'gather', 'ship', 'table_version']
__all__ = ['register', 'gather', 'ship']
logger = logging.getLogger('awx.main.analytics')
manifest = dict()
def _valid_license():
try:
@@ -37,11 +33,38 @@ def _valid_license():
return True
def register(key, version):
def all_collectors():
from awx.main.analytics import collectors
collector_dict = {}
module = collectors
for name, func in inspect.getmembers(module):
if inspect.isfunction(func) and hasattr(func, '__awx_analytics_key__'):
key = func.__awx_analytics_key__
desc = func.__awx_analytics_description__ or ''
version = func.__awx_analytics_version__
collector_dict[key] = { 'name': key, 'version': version, 'description': desc}
return collector_dict
def expensive_collectors():
from awx.main.analytics import collectors
ret = []
module = collectors
for name, func in inspect.getmembers(module):
if inspect.isfunction(func) and hasattr(func, '__awx_analytics_key__') and func.__awx_expensive__:
ret.append(func.__awx_analytics_key__)
return ret
def register(key, version, description=None, format='json', expensive=False):
"""
A decorator used to register a function as a metric collector.
Decorated functions should return JSON-serializable objects.
Decorated functions should do the following based on format:
- json: return JSON-serializable objects.
- csv: write CSV data to a filename named 'key'
@register('projects_by_scm_type', 1)
def projects_by_scm_type():
@@ -51,100 +74,153 @@ def register(key, version):
def decorate(f):
f.__awx_analytics_key__ = key
f.__awx_analytics_version__ = version
f.__awx_analytics_description__ = description
f.__awx_analytics_type__ = format
f.__awx_expensive__ = expensive
return f
return decorate
def table_version(file_name, version):
global manifest
manifest[file_name] = version
def decorate(f):
return f
return decorate
def gather(dest=None, module=None, collection_type='scheduled'):
def gather(dest=None, module=None, subset = None, since = None, until = now(), collection_type='scheduled'):
"""
Gather all defined metrics and write them as JSON files in a .tgz
:param dest: the (optional) absolute path to write a compressed tarball
:pararm module: the module to search for registered analytic collector
:param module: the module to search for registered analytic collector
functions; defaults to awx.main.analytics.collectors
"""
def _write_manifest(destdir, manifest):
path = os.path.join(destdir, 'manifest.json')
with open(path, 'w', encoding='utf-8') as f:
try:
json.dump(manifest, f)
except Exception:
f.close()
os.remove(f.name)
logger.exception("Could not generate manifest.json")
run_now = now()
state = TowerAnalyticsState.get_solo()
last_run = state.last_run
logger.debug("Last analytics run was: {}".format(last_run))
last_run = since or settings.AUTOMATION_ANALYTICS_LAST_GATHER or (now() - timedelta(weeks=4))
logger.debug("Last analytics run was: {}".format(settings.AUTOMATION_ANALYTICS_LAST_GATHER))
max_interval = now() - timedelta(weeks=4)
if last_run < max_interval or not last_run:
last_run = max_interval
if _valid_license() is False:
logger.exception("Invalid License provided, or No License Provided")
return "Error: Invalid License provided, or No License Provided"
return None
if collection_type != 'dry-run' and not settings.INSIGHTS_TRACKING_STATE:
logger.error("Automation Analytics not enabled. Use --dry-run to gather locally without sending.")
return
return None
if module is None:
collector_list = []
if module:
collector_module = module
else:
from awx.main.analytics import collectors
module = collectors
collector_module = collectors
for name, func in inspect.getmembers(collector_module):
if (
inspect.isfunction(func) and
hasattr(func, '__awx_analytics_key__') and
(not subset or name in subset)
):
collector_list.append((name, func))
manifest = dict()
dest = dest or tempfile.mkdtemp(prefix='awx_analytics')
for name, func in inspect.getmembers(module):
if inspect.isfunction(func) and hasattr(func, '__awx_analytics_key__'):
gather_dir = os.path.join(dest, 'stage')
os.mkdir(gather_dir, 0o700)
num_splits = 1
for name, func in collector_list:
if func.__awx_analytics_type__ == 'json':
key = func.__awx_analytics_key__
manifest['{}.json'.format(key)] = func.__awx_analytics_version__
path = '{}.json'.format(os.path.join(dest, key))
path = '{}.json'.format(os.path.join(gather_dir, key))
with open(path, 'w', encoding='utf-8') as f:
try:
if func.__name__ == 'query_info':
json.dump(func(last_run, collection_type=collection_type), f)
else:
json.dump(func(last_run), f)
json.dump(func(last_run, collection_type=collection_type, until=until), f)
manifest['{}.json'.format(key)] = func.__awx_analytics_version__
except Exception:
logger.exception("Could not generate metric {}.json".format(key))
f.close()
os.remove(f.name)
path = os.path.join(dest, 'manifest.json')
with open(path, 'w', encoding='utf-8') as f:
try:
json.dump(manifest, f)
except Exception:
logger.exception("Could not generate manifest.json")
f.close()
os.remove(f.name)
elif func.__awx_analytics_type__ == 'csv':
key = func.__awx_analytics_key__
try:
files = func(last_run, full_path=gather_dir, until=until)
if files:
manifest['{}.csv'.format(key)] = func.__awx_analytics_version__
if len(files) > num_splits:
num_splits = len(files)
except Exception:
logger.exception("Could not generate metric {}.csv".format(key))
try:
collectors.copy_tables(since=last_run, full_path=dest)
except Exception:
logger.exception("Could not copy tables")
# can't use isoformat() since it has colons, which GNU tar doesn't like
tarname = '_'.join([
settings.SYSTEM_UUID,
run_now.strftime('%Y-%m-%d-%H%M%S%z')
])
try:
tgz = shutil.make_archive(
os.path.join(os.path.dirname(dest), tarname),
'gztar',
dest
)
return tgz
except Exception:
logger.exception("Failed to write analytics archive file")
finally:
if not manifest:
# No data was collected
logger.warning("No data from {} to {}".format(last_run, until))
shutil.rmtree(dest)
return None
# Always include config.json if we're using our collectors
if 'config.json' not in manifest.keys() and not module:
from awx.main.analytics import collectors
config = collectors.config
path = '{}.json'.format(os.path.join(gather_dir, config.__awx_analytics_key__))
with open(path, 'w', encoding='utf-8') as f:
try:
json.dump(collectors.config(last_run), f)
manifest['config.json'] = config.__awx_analytics_version__
except Exception:
logger.exception("Could not generate metric {}.json".format(key))
f.close()
os.remove(f.name)
shutil.rmtree(dest)
return None
stage_dirs = [gather_dir]
if num_splits > 1:
for i in range(0, num_splits):
split_path = os.path.join(dest, 'split{}'.format(i))
os.mkdir(split_path, 0o700)
filtered_manifest = {}
shutil.copy(os.path.join(gather_dir, 'config.json'), split_path)
filtered_manifest['config.json'] = manifest['config.json']
suffix = '_split{}'.format(i)
for file in os.listdir(gather_dir):
if file.endswith(suffix):
old_file = os.path.join(gather_dir, file)
new_filename = file.replace(suffix, '')
new_file = os.path.join(split_path, new_filename)
shutil.move(old_file, new_file)
filtered_manifest[new_filename] = manifest[new_filename]
_write_manifest(split_path, filtered_manifest)
stage_dirs.append(split_path)
for item in list(manifest.keys()):
if not os.path.exists(os.path.join(gather_dir, item)):
manifest.pop(item)
_write_manifest(gather_dir, manifest)
tarfiles = []
try:
for i in range(0, len(stage_dirs)):
stage_dir = stage_dirs[i]
# can't use isoformat() since it has colons, which GNU tar doesn't like
tarname = '_'.join([
settings.SYSTEM_UUID,
until.strftime('%Y-%m-%d-%H%M%S%z'),
str(i)
])
tgz = shutil.make_archive(
os.path.join(os.path.dirname(dest), tarname),
'gztar',
stage_dir
)
tarfiles.append(tgz)
except Exception:
shutil.rmtree(stage_dir, ignore_errors = True)
logger.exception("Failed to write analytics archive file")
finally:
shutil.rmtree(dest, ignore_errors = True)
return tarfiles
def ship(path):
@@ -154,6 +230,9 @@ def ship(path):
if not path:
logger.error('Automation Analytics TAR not found')
return
if not os.path.exists(path):
logger.error('Automation Analytics TAR {} not found'.format(path))
return
if "Error:" in str(path):
return
try:
@@ -180,13 +259,11 @@ def ship(path):
auth=(rh_user, rh_password),
headers=s.headers,
timeout=(31, 31))
if response.status_code != 202:
# Accept 2XX status_codes
if response.status_code >= 300:
return logger.exception('Upload failed with status {}, {}'.format(response.status_code,
response.text))
run_now = now()
state = TowerAnalyticsState.get_solo()
state.last_run = run_now
state.save()
finally:
# cleanup tar.gz
os.remove(path)
if os.path.exists(path):
os.remove(path)

View File

@@ -2,7 +2,6 @@
import json
import logging
import os
from distutils.version import LooseVersion as Version
# Django
from django.utils.translation import ugettext_lazy as _
@@ -80,11 +79,11 @@ register(
)
register(
'PROXY_IP_WHITELIST',
'PROXY_IP_ALLOWED_LIST',
field_class=fields.StringListField,
label=_('Proxy IP Whitelist'),
label=_('Proxy IP Allowed List'),
help_text=_("If Tower is behind a reverse proxy/load balancer, use this setting "
"to whitelist the proxy IP addresses from which Tower should trust "
"to configure the proxy IP addresses from which Tower should trust "
"custom REMOTE_HOST_HEADERS header values. "
"If this setting is an empty list (the default), the headers specified by "
"REMOTE_HOST_HEADERS will be trusted unconditionally')"),
@@ -241,7 +240,7 @@ register(
field_class=fields.StringListField,
required=False,
label=_('Paths to expose to isolated jobs'),
help_text=_('Whitelist of paths that would otherwise be hidden to expose to isolated jobs. Enter one path per line.'),
help_text=_('List of paths that would otherwise be hidden to expose to isolated jobs. Enter one path per line.'),
category=_('Jobs'),
category_slug='jobs',
)
@@ -436,91 +435,12 @@ register(
category_slug='jobs',
)
register(
'PRIMARY_GALAXY_URL',
field_class=fields.URLField,
required=False,
allow_blank=True,
label=_('Primary Galaxy Server URL'),
help_text=_(
'For organizations that run their own Galaxy service, this gives the option to specify a '
'host as the primary galaxy server. Requirements will be downloaded from the primary if the '
'specific role or collection is available there. If the content is not avilable in the primary, '
'or if this field is left blank, it will default to galaxy.ansible.com.'
),
category=_('Jobs'),
category_slug='jobs'
)
register(
'PRIMARY_GALAXY_USERNAME',
field_class=fields.CharField,
required=False,
allow_blank=True,
label=_('Primary Galaxy Server Username'),
help_text=_('For using a galaxy server at higher precedence than the public Ansible Galaxy. '
'The username to use for basic authentication against the Galaxy instance, '
'this is mutually exclusive with PRIMARY_GALAXY_TOKEN.'),
category=_('Jobs'),
category_slug='jobs'
)
register(
'PRIMARY_GALAXY_PASSWORD',
field_class=fields.CharField,
encrypted=True,
required=False,
allow_blank=True,
label=_('Primary Galaxy Server Password'),
help_text=_('For using a galaxy server at higher precedence than the public Ansible Galaxy. '
'The password to use for basic authentication against the Galaxy instance, '
'this is mutually exclusive with PRIMARY_GALAXY_TOKEN.'),
category=_('Jobs'),
category_slug='jobs'
)
register(
'PRIMARY_GALAXY_TOKEN',
field_class=fields.CharField,
encrypted=True,
required=False,
allow_blank=True,
label=_('Primary Galaxy Server Token'),
help_text=_('For using a galaxy server at higher precedence than the public Ansible Galaxy. '
'The token to use for connecting with the Galaxy instance, '
'this is mutually exclusive with corresponding username and password settings.'),
category=_('Jobs'),
category_slug='jobs'
)
register(
'PRIMARY_GALAXY_AUTH_URL',
field_class=fields.CharField,
required=False,
allow_blank=True,
label=_('Primary Galaxy Authentication URL'),
help_text=_('For using a galaxy server at higher precedence than the public Ansible Galaxy. '
'The token_endpoint of a Keycloak server.'),
category=_('Jobs'),
category_slug='jobs'
)
register(
'PUBLIC_GALAXY_ENABLED',
field_class=fields.BooleanField,
default=True,
label=_('Allow Access to Public Galaxy'),
help_text=_('Allow or deny access to the public Ansible Galaxy during project updates.'),
category=_('Jobs'),
category_slug='jobs'
)
register(
'GALAXY_IGNORE_CERTS',
field_class=fields.BooleanField,
default=False,
label=_('Ignore Ansible Galaxy SSL Certificate Verification'),
help_text=_('If set to true, certificate validation will not be done when'
help_text=_('If set to true, certificate validation will not be done when '
'installing content from any Galaxy server.'),
category=_('Jobs'),
category_slug='jobs'
@@ -854,84 +774,4 @@ def logging_validate(serializer, attrs):
return attrs
def galaxy_validate(serializer, attrs):
"""Ansible Galaxy config options have mutual exclusivity rules, these rules
are enforced here on serializer validation so that users will not be able
to save settings which obviously break all project updates.
"""
prefix = 'PRIMARY_GALAXY_'
errors = {}
def _new_value(setting_name):
if setting_name in attrs:
return attrs[setting_name]
elif not serializer.instance:
return ''
return getattr(serializer.instance, setting_name, '')
if not _new_value('PRIMARY_GALAXY_URL'):
if _new_value('PUBLIC_GALAXY_ENABLED') is False:
msg = _('A URL for Primary Galaxy must be defined before disabling public Galaxy.')
# put error in both keys because UI has trouble with errors in toggles
for key in ('PRIMARY_GALAXY_URL', 'PUBLIC_GALAXY_ENABLED'):
errors.setdefault(key, [])
errors[key].append(msg)
raise serializers.ValidationError(errors)
from awx.main.constants import GALAXY_SERVER_FIELDS
if not any('{}{}'.format(prefix, subfield.upper()) in attrs for subfield in GALAXY_SERVER_FIELDS):
return attrs
galaxy_data = {}
for subfield in GALAXY_SERVER_FIELDS:
galaxy_data[subfield] = _new_value('{}{}'.format(prefix, subfield.upper()))
if not galaxy_data['url']:
for k, v in galaxy_data.items():
if v:
setting_name = '{}{}'.format(prefix, k.upper())
errors.setdefault(setting_name, [])
errors[setting_name].append(_(
'Cannot provide field if PRIMARY_GALAXY_URL is not set.'
))
for k in GALAXY_SERVER_FIELDS:
if galaxy_data[k]:
setting_name = '{}{}'.format(prefix, k.upper())
if (not serializer.instance) or (not getattr(serializer.instance, setting_name, '')):
# new auth is applied, so check if compatible with version
from awx.main.utils import get_ansible_version
current_version = get_ansible_version()
min_version = '2.9'
if Version(current_version) < Version(min_version):
errors.setdefault(setting_name, [])
errors[setting_name].append(_(
'Galaxy server settings are not available until Ansible {min_version}, '
'you are running {current_version}.'
).format(min_version=min_version, current_version=current_version))
if (galaxy_data['password'] or galaxy_data['username']) and (galaxy_data['token'] or galaxy_data['auth_url']):
for k in ('password', 'username', 'token', 'auth_url'):
setting_name = '{}{}'.format(prefix, k.upper())
if setting_name in attrs:
errors.setdefault(setting_name, [])
errors[setting_name].append(_(
'Setting Galaxy token and authentication URL is mutually exclusive with username and password.'
))
if bool(galaxy_data['username']) != bool(galaxy_data['password']):
msg = _('If authenticating via username and password, both must be provided.')
for k in ('username', 'password'):
setting_name = '{}{}'.format(prefix, k.upper())
errors.setdefault(setting_name, [])
errors[setting_name].append(msg)
if bool(galaxy_data['token']) != bool(galaxy_data['auth_url']):
msg = _('If authenticating via token, both token and authentication URL must be provided.')
for k in ('token', 'auth_url'):
setting_name = '{}{}'.format(prefix, k.upper())
errors.setdefault(setting_name, [])
errors[setting_name].append(msg)
if errors:
raise serializers.ValidationError(errors)
return attrs
register_validate('logging', logging_validate)
register_validate('jobs', galaxy_validate)

View File

@@ -10,8 +10,7 @@ __all__ = [
'ANSI_SGR_PATTERN', 'CAN_CANCEL', 'ACTIVE_STATES', 'STANDARD_INVENTORY_UPDATE_ENV'
]
CLOUD_PROVIDERS = ('azure_rm', 'ec2', 'gce', 'vmware', 'openstack', 'rhv', 'satellite6', 'cloudforms', 'tower')
CLOUD_PROVIDERS = ('azure_rm', 'ec2', 'gce', 'vmware', 'openstack', 'rhv', 'satellite6', 'tower')
SCHEDULEABLE_PROVIDERS = CLOUD_PROVIDERS + ('custom', 'scm',)
PRIVILEGE_ESCALATION_METHODS = [
('sudo', _('Sudo')), ('su', _('Su')), ('pbrun', _('Pbrun')), ('pfexec', _('Pfexec')),
@@ -32,7 +31,7 @@ STANDARD_INVENTORY_UPDATE_ENV = {
CAN_CANCEL = ('new', 'pending', 'waiting', 'running')
ACTIVE_STATES = CAN_CANCEL
CENSOR_VALUE = '************'
ENV_BLACKLIST = frozenset((
ENV_BLOCKLIST = frozenset((
'VIRTUAL_ENV', 'PATH', 'PYTHONPATH', 'PROOT_TMP_DIR', 'JOB_ID',
'INVENTORY_ID', 'INVENTORY_SOURCE_ID', 'INVENTORY_UPDATE_ID',
'AD_HOC_COMMAND_ID', 'REST_API_URL', 'REST_API_TOKEN', 'MAX_EVENT_RES',
@@ -42,7 +41,7 @@ ENV_BLACKLIST = frozenset((
))
# loggers that may be called in process of emitting a log
LOGGER_BLACKLIST = (
LOGGER_BLOCKLIST = (
'awx.main.utils.handlers',
'awx.main.utils.formatters',
'awx.main.utils.filters',
@@ -51,7 +50,3 @@ LOGGER_BLACKLIST = (
# loggers that may be called getting logging settings
'awx.conf'
)
# these correspond to both AWX and Ansible settings to keep naming consistent
# for instance, settings.PRIMARY_GALAXY_AUTH_URL vs env var ANSIBLE_GALAXY_SERVER_FOO_AUTH_URL
GALAXY_SERVER_FIELDS = ('url', 'username', 'password', 'token', 'auth_url')

View File

@@ -1,4 +1,4 @@
from .plugin import CredentialPlugin, CertFiles
from .plugin import CredentialPlugin, CertFiles, raise_for_status
from urllib.parse import quote, urlencode, urljoin
@@ -82,8 +82,9 @@ def aim_backend(**kwargs):
timeout=30,
cert=cert,
verify=verify,
allow_redirects=False,
)
res.raise_for_status()
raise_for_status(res)
return res.json()['Content']

View File

@@ -1,4 +1,4 @@
from .plugin import CredentialPlugin, CertFiles
from .plugin import CredentialPlugin, CertFiles, raise_for_status
import base64
from urllib.parse import urljoin, quote
@@ -58,7 +58,8 @@ def conjur_backend(**kwargs):
auth_kwargs = {
'headers': {'Content-Type': 'text/plain'},
'data': api_key
'data': api_key,
'allow_redirects': False,
}
with CertFiles(cacert) as cert:
@@ -68,11 +69,12 @@ def conjur_backend(**kwargs):
urljoin(url, '/'.join(['authn', account, username, 'authenticate'])),
**auth_kwargs
)
resp.raise_for_status()
raise_for_status(resp)
token = base64.b64encode(resp.content).decode('utf-8')
lookup_kwargs = {
'headers': {'Authorization': 'Token token="{}"'.format(token)},
'allow_redirects': False,
}
# https://www.conjur.org/api.html#secrets-retrieve-a-secret-get
@@ -88,7 +90,7 @@ def conjur_backend(**kwargs):
with CertFiles(cacert) as cert:
lookup_kwargs['verify'] = cert
resp = requests.get(path, timeout=30, **lookup_kwargs)
resp.raise_for_status()
raise_for_status(resp)
return resp.text

View File

@@ -3,7 +3,7 @@ import os
import pathlib
from urllib.parse import urljoin
from .plugin import CredentialPlugin, CertFiles
from .plugin import CredentialPlugin, CertFiles, raise_for_status
import requests
from django.utils.translation import ugettext_lazy as _
@@ -40,6 +40,13 @@ base_inputs = {
'multiline': False,
'secret': True,
'help_text': _('The Secret ID for AppRole Authentication')
}, {
'id': 'default_auth_path',
'label': _('Path to Approle Auth'),
'type': 'string',
'multiline': False,
'default': 'approle',
'help_text': _('The AppRole Authentication path to use if one isn\'t provided in the metadata when linking to an input field. Defaults to \'approle\'')
}
],
'metadata': [{
@@ -47,10 +54,11 @@ base_inputs = {
'label': _('Path to Secret'),
'type': 'string',
'help_text': _('The path to the secret stored in the secret backend e.g, /some/secret/')
},{
}, {
'id': 'auth_path',
'label': _('Path to Auth'),
'type': 'string',
'multiline': False,
'help_text': _('The path where the Authentication method is mounted e.g, approle')
}],
'required': ['url', 'secret_path'],
@@ -118,7 +126,9 @@ def handle_auth(**kwargs):
def approle_auth(**kwargs):
role_id = kwargs['role_id']
secret_id = kwargs['secret_id']
auth_path = kwargs.get('auth_path') or 'approle'
# we first try to use the 'auth_path' from the metadata
# if not found we try to fetch the 'default_auth_path' from inputs
auth_path = kwargs.get('auth_path') or kwargs['default_auth_path']
url = urljoin(kwargs['url'], 'v1')
cacert = kwargs.get('cacert', None)
@@ -145,11 +155,14 @@ def kv_backend(**kwargs):
cacert = kwargs.get('cacert', None)
api_version = kwargs['api_version']
request_kwargs = {'timeout': 30}
request_kwargs = {
'timeout': 30,
'allow_redirects': False,
}
sess = requests.Session()
sess.headers['Authorization'] = 'Bearer {}'.format(token)
# Compatability header for older installs of Hashicorp Vault
# Compatibility header for older installs of Hashicorp Vault
sess.headers['X-Vault-Token'] = token
if api_version == 'v2':
@@ -175,7 +188,7 @@ def kv_backend(**kwargs):
with CertFiles(cacert) as cert:
request_kwargs['verify'] = cert
response = sess.get(request_url, **request_kwargs)
response.raise_for_status()
raise_for_status(response)
json = response.json()
if api_version == 'v2':
@@ -198,7 +211,10 @@ def ssh_backend(**kwargs):
role = kwargs['role']
cacert = kwargs.get('cacert', None)
request_kwargs = {'timeout': 30}
request_kwargs = {
'timeout': 30,
'allow_redirects': False,
}
request_kwargs['json'] = {'public_key': kwargs['public_key']}
if kwargs.get('valid_principals'):
@@ -215,7 +231,7 @@ def ssh_backend(**kwargs):
request_kwargs['verify'] = cert
resp = sess.post(request_url, **request_kwargs)
resp.raise_for_status()
raise_for_status(resp)
return resp.json()['data']['signed_key']

View File

@@ -3,9 +3,19 @@ import tempfile
from collections import namedtuple
from requests.exceptions import HTTPError
CredentialPlugin = namedtuple('CredentialPlugin', ['name', 'inputs', 'backend'])
def raise_for_status(resp):
resp.raise_for_status()
if resp.status_code >= 300:
exc = HTTPError()
setattr(exc, 'response', resp)
raise exc
class CertFiles():
"""
A context manager used for writing a certificate and (optional) key

View File

@@ -24,7 +24,7 @@ class RecordedQueryLog(object):
try:
self.threshold = cache.get('awx-profile-sql-threshold')
except Exception:
# if we can't reach memcached, just assume profiling's off
# if we can't reach the cache, just assume profiling's off
self.threshold = None
def append(self, query):
@@ -110,7 +110,7 @@ class RecordedQueryLog(object):
class DatabaseWrapper(BaseDatabaseWrapper):
"""
This is a special subclass of Django's postgres DB backend which - based on
the value of a special flag in memcached - captures slow queries and
the value of a special flag in cache - captures slow queries and
writes profile and Python stack metadata to the disk.
"""
@@ -133,19 +133,19 @@ class DatabaseWrapper(BaseDatabaseWrapper):
# is the same mechanism used by libraries like the django-debug-toolbar)
#
# in _this_ implementation, we represent it as a property which will
# check memcache for a special flag to be set (when the flag is set, it
# check the cache for a special flag to be set (when the flag is set, it
# means we should start recording queries because somebody called
# `awx-manage profile_sql`)
#
# it's worth noting that this property is wrapped w/ @memoize because
# Django references this attribute _constantly_ (in particular, once
# per executed query); doing a memcached.get() _at most_ once per
# per executed query); doing a cache.get() _at most_ once per
# second is a good enough window to detect when profiling is turned
# on/off by a system administrator
try:
threshold = cache.get('awx-profile-sql-threshold')
except Exception:
# if we can't reach memcached, just assume profiling's off
# if we can't reach the cache, just assume profiling's off
threshold = None
self.queries_log.threshold = threshold
return threshold is not None

View File

@@ -2,6 +2,9 @@ import logging
import uuid
import json
from django.conf import settings
import redis
from awx.main.dispatch import get_local_queuename
from . import pg_bus_conn
@@ -21,7 +24,15 @@ class Control(object):
self.queuename = host or get_local_queuename()
def status(self, *args, **kwargs):
return self.control_with_reply('status', *args, **kwargs)
r = redis.Redis.from_url(settings.BROKER_URL)
if self.service == 'dispatcher':
stats = r.get(f'awx_{self.service}_statistics') or b''
return stats.decode('utf-8')
else:
workers = []
for key in r.keys('awx_callback_receiver_statistics_*'):
workers.append(r.get(key).decode('utf-8'))
return '\n'.join(workers)
def running(self, *args, **kwargs):
return self.control_with_reply('running', *args, **kwargs)
@@ -43,7 +54,7 @@ class Control(object):
for reply in conn.events(select_timeout=timeout, yield_timeouts=True):
if reply is None:
logger.error(f'{self.service} did not reply within {timeout}s')
raise RuntimeError("{self.service} did not reply within {timeout}s")
raise RuntimeError(f"{self.service} did not reply within {timeout}s")
break
return json.loads(reply.payload)

View File

@@ -5,6 +5,7 @@ import signal
import sys
import time
import traceback
from datetime import datetime
from uuid import uuid4
import collections
@@ -27,6 +28,12 @@ else:
logger = logging.getLogger('awx.main.dispatch')
class NoOpResultQueue(object):
def put(self, item):
pass
class PoolWorker(object):
'''
Used to track a worker child process and its pending and finished messages.
@@ -56,11 +63,13 @@ class PoolWorker(object):
It is "idle" when self.managed_tasks is empty.
'''
def __init__(self, queue_size, target, args):
track_managed_tasks = False
def __init__(self, queue_size, target, args, **kwargs):
self.messages_sent = 0
self.messages_finished = 0
self.managed_tasks = collections.OrderedDict()
self.finished = MPQueue(queue_size)
self.finished = MPQueue(queue_size) if self.track_managed_tasks else NoOpResultQueue()
self.queue = MPQueue(queue_size)
self.process = Process(target=target, args=(self.queue, self.finished) + args)
self.process.daemon = True
@@ -74,7 +83,8 @@ class PoolWorker(object):
if not body.get('uuid'):
body['uuid'] = str(uuid4())
uuid = body['uuid']
self.managed_tasks[uuid] = body
if self.track_managed_tasks:
self.managed_tasks[uuid] = body
self.queue.put(body, block=True, timeout=5)
self.messages_sent += 1
self.calculate_managed_tasks()
@@ -111,6 +121,8 @@ class PoolWorker(object):
return str(self.process.exitcode)
def calculate_managed_tasks(self):
if not self.track_managed_tasks:
return
# look to see if any tasks were finished
finished = []
for _ in range(self.finished.qsize()):
@@ -135,6 +147,8 @@ class PoolWorker(object):
@property
def current_task(self):
if not self.track_managed_tasks:
return None
self.calculate_managed_tasks()
# the task at [0] is the one that's running right now (or is about to
# be running)
@@ -145,6 +159,8 @@ class PoolWorker(object):
@property
def orphaned_tasks(self):
if not self.track_managed_tasks:
return []
orphaned = []
if not self.alive:
# if this process had a running task that never finished,
@@ -179,6 +195,11 @@ class PoolWorker(object):
return not self.busy
class StatefulPoolWorker(PoolWorker):
track_managed_tasks = True
class WorkerPool(object):
'''
Creates a pool of forked PoolWorkers.
@@ -200,6 +221,7 @@ class WorkerPool(object):
)
'''
pool_cls = PoolWorker
debug_meta = ''
def __init__(self, min_workers=None, queue_size=None):
@@ -222,10 +244,10 @@ class WorkerPool(object):
idx = len(self.workers)
# It's important to close these because we're _about_ to fork, and we
# don't want the forked processes to inherit the open sockets
# for the DB and memcached connections (that way lies race conditions)
# for the DB and cache connections (that way lies race conditions)
django_connection.close()
django_cache.close()
worker = PoolWorker(self.queue_size, self.target, (idx,) + self.target_args)
worker = self.pool_cls(self.queue_size, self.target, (idx,) + self.target_args)
self.workers.append(worker)
try:
worker.start()
@@ -236,13 +258,13 @@ class WorkerPool(object):
return idx, worker
def debug(self, *args, **kwargs):
self.cleanup()
tmpl = Template(
'Recorded at: {{ dt }} \n'
'{{ pool.name }}[pid:{{ pool.pid }}] workers total={{ workers|length }} {{ meta }} \n'
'{% for w in workers %}'
'. worker[pid:{{ w.pid }}]{% if not w.alive %} GONE exit={{ w.exitcode }}{% endif %}'
' sent={{ w.messages_sent }}'
' finished={{ w.messages_finished }}'
'{% if w.messages_finished %} finished={{ w.messages_finished }}{% endif %}'
' qsize={{ w.managed_tasks|length }}'
' rss={{ w.mb }}MB'
'{% for task in w.managed_tasks.values() %}'
@@ -260,7 +282,11 @@ class WorkerPool(object):
'\n'
'{% endfor %}'
)
return tmpl.render(pool=self, workers=self.workers, meta=self.debug_meta)
now = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC')
return tmpl.render(
pool=self, workers=self.workers, meta=self.debug_meta,
dt=now
)
def write(self, preferred_queue, body):
queue_order = sorted(range(len(self.workers)), key=lambda x: -1 if x==preferred_queue else x)
@@ -293,6 +319,8 @@ class AutoscalePool(WorkerPool):
down based on demand
'''
pool_cls = StatefulPoolWorker
def __init__(self, *args, **kwargs):
self.max_workers = kwargs.pop('max_workers', None)
super(AutoscalePool, self).__init__(*args, **kwargs)
@@ -309,6 +337,10 @@ class AutoscalePool(WorkerPool):
# max workers can't be less than min_workers
self.max_workers = max(self.min_workers, self.max_workers)
def debug(self, *args, **kwargs):
self.cleanup()
return super(AutoscalePool, self).debug(*args, **kwargs)
@property
def should_grow(self):
if len(self.workers) < self.min_workers:

View File

@@ -43,6 +43,9 @@ class WorkerSignalHandler:
class AWXConsumerBase(object):
last_stats = time.time()
def __init__(self, name, worker, queues=[], pool=None):
self.should_stop = False
@@ -54,6 +57,7 @@ class AWXConsumerBase(object):
if pool is None:
self.pool = WorkerPool()
self.pool.init_workers(self.worker.work_loop)
self.redis = redis.Redis.from_url(settings.BROKER_URL)
@property
def listening_on(self):
@@ -99,6 +103,16 @@ class AWXConsumerBase(object):
queue = 0
self.pool.write(queue, body)
self.total_messages += 1
self.record_statistics()
def record_statistics(self):
if time.time() - self.last_stats > 1: # buffer stat recording to once per second
try:
self.redis.set(f'awx_{self.name}_statistics', self.pool.debug())
self.last_stats = time.time()
except Exception:
logger.exception(f"encountered an error communicating with redis to store {self.name} statistics")
self.last_stats = time.time()
def run(self, *args, **kwargs):
signal.signal(signal.SIGINT, self.stop)
@@ -118,23 +132,9 @@ class AWXConsumerRedis(AWXConsumerBase):
super(AWXConsumerRedis, self).run(*args, **kwargs)
self.worker.on_start()
time_to_sleep = 1
while True:
queue = redis.Redis.from_url(settings.BROKER_URL)
while True:
try:
res = queue.blpop(self.queues)
time_to_sleep = 1
res = json.loads(res[1])
self.process_task(res)
except redis.exceptions.RedisError:
time_to_sleep = min(time_to_sleep * 2, 30)
logger.exception(f"encountered an error communicating with redis. Reconnect attempt in {time_to_sleep} seconds")
time.sleep(time_to_sleep)
except (json.JSONDecodeError, KeyError):
logger.exception("failed to decode JSON message from redis")
if self.should_stop:
return
logger.debug(f'{os.getpid()} is alive')
time.sleep(60)
class AWXConsumerPG(AWXConsumerBase):

View File

@@ -1,4 +1,5 @@
import cProfile
import json
import logging
import os
import pstats
@@ -6,12 +7,15 @@ import signal
import tempfile
import time
import traceback
from queue import Empty as QueueEmpty
from django.conf import settings
from django.utils.timezone import now as tz_now
from django.db import DatabaseError, OperationalError, connection as django_connection
from django.db.utils import InterfaceError, InternalError, IntegrityError
from django.db.utils import InterfaceError, InternalError
import psutil
import redis
from awx.main.consumers import emit_channel_notification
from awx.main.models import (JobEvent, AdHocCommandEvent, ProjectUpdateEvent,
@@ -24,10 +28,6 @@ from .base import BaseWorker
logger = logging.getLogger('awx.main.commands.run_callback_receiver')
# the number of seconds to buffer events in memory before flushing
# using JobEvent.objects.bulk_create()
BUFFER_SECONDS = .1
class CallbackBrokerWorker(BaseWorker):
'''
@@ -39,21 +39,57 @@ class CallbackBrokerWorker(BaseWorker):
'''
MAX_RETRIES = 2
last_stats = time.time()
total = 0
last_event = ''
prof = None
def __init__(self):
self.buff = {}
self.pid = os.getpid()
self.redis = redis.Redis.from_url(settings.BROKER_URL)
for key in self.redis.keys('awx_callback_receiver_statistics_*'):
self.redis.delete(key)
def read(self, queue):
try:
return queue.get(block=True, timeout=BUFFER_SECONDS)
except QueueEmpty:
return {'event': 'FLUSH'}
res = self.redis.blpop(settings.CALLBACK_QUEUE, timeout=settings.JOB_EVENT_BUFFER_SECONDS)
if res is None:
return {'event': 'FLUSH'}
self.total += 1
return json.loads(res[1])
except redis.exceptions.RedisError:
logger.exception("encountered an error communicating with redis")
time.sleep(1)
except (json.JSONDecodeError, KeyError):
logger.exception("failed to decode JSON message from redis")
finally:
self.record_statistics()
return {'event': 'FLUSH'}
def record_statistics(self):
# buffer stat recording to once per (by default) 5s
if time.time() - self.last_stats > settings.JOB_EVENT_STATISTICS_INTERVAL:
try:
self.redis.set(f'awx_callback_receiver_statistics_{self.pid}', self.debug())
self.last_stats = time.time()
except Exception:
logger.exception("encountered an error communicating with redis")
self.last_stats = time.time()
def debug(self):
return f'. worker[pid:{self.pid}] sent={self.total} rss={self.mb}MB {self.last_event}'
@property
def mb(self):
return '{:0.3f}'.format(
psutil.Process(self.pid).memory_info().rss / 1024.0 / 1024.0
)
def toggle_profiling(self, *args):
if self.prof:
self.prof.disable()
filename = f'callback-{os.getpid()}.pstats'
filename = f'callback-{self.pid}.pstats'
filepath = os.path.join(tempfile.gettempdir(), filename)
with open(filepath, 'w') as f:
pstats.Stats(self.prof, stream=f).sort_stats('cumulative').print_stats()
@@ -84,20 +120,12 @@ class CallbackBrokerWorker(BaseWorker):
e.modified = now
try:
cls.objects.bulk_create(events)
except Exception as exc:
except Exception:
# if an exception occurs, we should re-attempt to save the
# events one-by-one, because something in the list is
# broken/stale (e.g., an IntegrityError on a specific event)
# broken/stale
for e in events:
try:
if (
isinstance(exc, IntegrityError) and
getattr(e, 'host_id', '')
):
# this is one potential IntegrityError we can
# work around - if the host disappears before
# the event can be processed
e.host_id = None
e.save()
except Exception:
logger.exception('Database Error Saving Job Event')
@@ -108,6 +136,8 @@ class CallbackBrokerWorker(BaseWorker):
def perform_work(self, body):
try:
flush = body.get('event') == 'FLUSH'
if flush:
self.last_event = ''
if not flush:
event_map = {
'job_id': JobEvent,
@@ -123,6 +153,8 @@ class CallbackBrokerWorker(BaseWorker):
job_identifier = body[key]
break
self.last_event = f'\n\t- {cls.__name__} for #{job_identifier} ({body.get("event", "")} {body.get("uuid", "")})' # noqa
if body.get('event') == 'EOF':
try:
final_counter = body.get('final_counter', 0)

View File

@@ -7,8 +7,8 @@ import json
import re
import urllib.parse
from jinja2 import Environment, StrictUndefined
from jinja2.exceptions import UndefinedError, TemplateSyntaxError
from jinja2 import sandbox, StrictUndefined
from jinja2.exceptions import UndefinedError, TemplateSyntaxError, SecurityError
# Django
from django.contrib.postgres.fields import JSONField as upstream_JSONBField
@@ -50,7 +50,7 @@ from awx.main.models.rbac import (
batch_role_ancestor_rebuilding, Role,
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, ROLE_SINGLETON_SYSTEM_AUDITOR
)
from awx.main.constants import ENV_BLACKLIST
from awx.main.constants import ENV_BLOCKLIST
from awx.main import utils
@@ -637,6 +637,14 @@ class CredentialInputField(JSONSchemaField):
else:
decrypted_values[k] = v
# don't allow secrets with $encrypted$ on new object creation
if not model_instance.pk:
for field in model_instance.credential_type.secret_fields:
if value.get(field) == '$encrypted$':
raise serializers.ValidationError({
self.name: [f'$encrypted$ is a reserved keyword, and cannot be used for {field}.']
})
super(JSONSchemaField, self).validate(decrypted_values, model_instance)
errors = {}
for error in Draft4Validator(
@@ -870,9 +878,9 @@ class CredentialTypeInjectorField(JSONSchemaField):
'use is not allowed in credentials.').format(env_var),
code='invalid', params={'value': env_var},
)
if env_var in ENV_BLACKLIST:
if env_var in ENV_BLOCKLIST:
raise django_exceptions.ValidationError(
_('Environment variable {} is blacklisted from use in credentials.').format(env_var),
_('Environment variable {} is not allowed to be used in credentials.').format(env_var),
code='invalid', params={'value': env_var},
)
@@ -932,7 +940,7 @@ class CredentialTypeInjectorField(JSONSchemaField):
self.validate_env_var_allowed(key)
for key, tmpl in injector.items():
try:
Environment(
sandbox.ImmutableSandboxedEnvironment(
undefined=StrictUndefined
).from_string(tmpl).render(valid_namespace)
except UndefinedError as e:
@@ -942,6 +950,10 @@ class CredentialTypeInjectorField(JSONSchemaField):
code='invalid',
params={'value': value},
)
except SecurityError as e:
raise django_exceptions.ValidationError(
_('Encountered unsafe code execution: {}').format(e)
)
except TemplateSyntaxError as e:
raise django_exceptions.ValidationError(
_('Syntax error rendering template for {sub_key} inside of {type} ({error_msg})').format(

View File

@@ -58,7 +58,7 @@ class IsolatedManager(object):
os.chmod(temp.name, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
for host in hosts:
inventory['all']['hosts'][host] = {
"ansible_connection": "community.kubernetes.kubectl",
"ansible_connection": "kubectl",
"ansible_kubectl_config": path,
}
else:

View File

@@ -0,0 +1,96 @@
from django.core.management.base import BaseCommand
from django.db import connection
from awx.main.models import JobTemplate
class Command(BaseCommand):
help = "Find the slowest tasks and hosts for a Job Template's most recent runs."
def add_arguments(self, parser):
parser.add_argument('--template', dest='jt', type=int,
help='ID of the Job Template to profile')
parser.add_argument('--threshold', dest='threshold', type=float, default=30,
help='Only show tasks that took at least this many seconds (defaults to 30)')
parser.add_argument('--history', dest='history', type=float, default=25,
help='The number of historic jobs to look at')
parser.add_argument('--ignore', action='append', help='ignore a specific action (e.g., --ignore git)')
def handle(self, *args, **options):
jt = options['jt']
threshold = options['threshold']
history = options['history']
ignore = options['ignore']
print('## ' + JobTemplate.objects.get(pk=jt).name + f' (last {history} runs)\n')
with connection.cursor() as cursor:
cursor.execute(
f'''
SELECT
b.id, b.job_id, b.host_name, b.created - a.created delta,
b.task task,
b.event_data::json->'task_action' task_action,
b.event_data::json->'task_path' task_path
FROM main_jobevent a JOIN main_jobevent b
ON b.parent_uuid = a.parent_uuid AND a.host_name = b.host_name
WHERE
a.event = 'runner_on_start' AND
b.event != 'runner_on_start' AND
b.event != 'runner_on_skipped' AND
b.failed = false AND
a.job_id IN (
SELECT unifiedjob_ptr_id FROM main_job
WHERE job_template_id={jt}
ORDER BY unifiedjob_ptr_id DESC
LIMIT {history}
)
ORDER BY delta DESC;
'''
)
slowest_events = cursor.fetchall()
def format_td(x):
return str(x).split('.')[0]
fastest = dict()
for event in slowest_events:
_id, job_id, host, duration, task, action, playbook = event
playbook = playbook.rsplit('/')[-1]
if ignore and action in ignore:
continue
if host:
fastest[(action, playbook)] = (_id, host, format_td(duration))
host_counts = dict()
warned = set()
print(f'slowest tasks (--threshold={threshold})\n---')
for event in slowest_events:
_id, job_id, host, duration, task, action, playbook = event
if ignore and action in ignore:
continue
if duration.total_seconds() < threshold:
break
playbook = playbook.rsplit('/')[-1]
human_duration = format_td(duration)
fastest_summary = ''
fastest_match = fastest.get((action, playbook))
if fastest_match[2] != human_duration and (host, action, playbook) not in warned:
warned.add((host, action, playbook))
fastest_summary = ' ' + self.style.WARNING(f'{fastest_match[1]} ran this in {fastest_match[2]}s at /api/v2/job_events/{fastest_match[0]}/')
url = f'/api/v2/jobs/{job_id}/'
print(' -- '.join([url, host, human_duration, action, task, playbook]) + fastest_summary)
host_counts.setdefault(host, [])
host_counts[host].append(duration)
host_counts = sorted(host_counts.items(), key=lambda item: [e.total_seconds() for e in item[1]], reverse=True)
print('\nslowest hosts\n---')
for h, matches in host_counts:
total = len(matches)
total_seconds = sum([e.total_seconds() for e in matches])
print(f'{h} had {total} tasks that ran longer than {threshold} second(s) for a total of {total_seconds}')
print('')

View File

@@ -42,6 +42,16 @@ class Command(BaseCommand):
},
created_by=superuser)
c.admin_role.members.add(superuser)
public_galaxy_credential = Credential(
name='Ansible Galaxy',
managed_by_tower=True,
credential_type=CredentialType.objects.get(kind='galaxy'),
inputs = {
'url': 'https://galaxy.ansible.com/'
}
)
public_galaxy_credential.save()
o.galaxy_credentials.add(public_galaxy_credential)
i = Inventory.objects.create(name='Demo Inventory',
organization=o,
created_by=superuser)

View File

@@ -1,6 +1,9 @@
import logging
from awx.main.analytics import gather, ship
from dateutil import parser
from django.core.management.base import BaseCommand
from django.utils.timezone import now
class Command(BaseCommand):
@@ -15,6 +18,10 @@ class Command(BaseCommand):
help='Gather analytics without shipping. Works even if analytics are disabled in settings.')
parser.add_argument('--ship', dest='ship', action='store_true',
help='Enable to ship metrics to the Red Hat Cloud')
parser.add_argument('--since', dest='since', action='store',
help='Start date for collection')
parser.add_argument('--until', dest='until', action='store',
help='End date for collection')
def init_logging(self):
self.logger = logging.getLogger('awx.main.analytics')
@@ -28,11 +35,28 @@ class Command(BaseCommand):
self.init_logging()
opt_ship = options.get('ship')
opt_dry_run = options.get('dry-run')
opt_since = options.get('since') or None
opt_until = options.get('until') or None
if opt_since:
since = parser.parse(opt_since)
else:
since = None
if opt_until:
until = parser.parse(opt_until)
else:
until = now()
if opt_ship and opt_dry_run:
self.logger.error('Both --ship and --dry-run cannot be processed at the same time.')
return
tgz = gather(collection_type='manual' if not opt_dry_run else 'dry-run')
if tgz:
self.logger.debug(tgz)
tgzfiles = gather(collection_type='manual' if not opt_dry_run else 'dry-run', since = since, until = until)
if tgzfiles:
for tgz in tgzfiles:
self.logger.info(tgz)
else:
self.logger.error('No analytics collected')
if opt_ship:
ship(tgz)
if tgzfiles:
for tgz in tgzfiles:
ship(tgz)

View File

@@ -12,7 +12,6 @@ import sys
import time
import traceback
import shutil
from distutils.version import LooseVersion as Version
# Django
from django.conf import settings
@@ -39,7 +38,6 @@ from awx.main.utils import (
build_proot_temp_dir,
get_licenser
)
from awx.main.utils.common import _get_ansible_version
from awx.main.signals import disable_activity_stream
from awx.main.constants import STANDARD_INVENTORY_UPDATE_ENV
from awx.main.utils.pglock import advisory_lock
@@ -136,15 +134,10 @@ class AnsibleInventoryLoader(object):
# inside of /venv/ansible, so we override the specified interpreter
# https://github.com/ansible/ansible/issues/50714
bargs = ['python', ansible_inventory_path, '-i', self.source]
ansible_version = _get_ansible_version(ansible_inventory_path[:-len('-inventory')])
if ansible_version != 'unknown':
this_version = Version(ansible_version)
if this_version >= Version('2.5'):
bargs.extend(['--playbook-dir', self.source_dir])
if this_version >= Version('2.8'):
if self.verbosity:
# INFO: -vvv, DEBUG: -vvvvv, for inventory, any more than 3 makes little difference
bargs.append('-{}'.format('v' * min(5, self.verbosity * 2 + 1)))
bargs.extend(['--playbook-dir', self.source_dir])
if self.verbosity:
# INFO: -vvv, DEBUG: -vvvvv, for inventory, any more than 3 makes little difference
bargs.append('-{}'.format('v' * min(5, self.verbosity * 2 + 1)))
logger.debug('Using base command: {}'.format(' '.join(bargs)))
return bargs
@@ -271,7 +264,7 @@ class Command(BaseCommand):
logging.DEBUG, 0]))
logger.setLevel(log_levels.get(self.verbosity, 0))
def _get_instance_id(self, from_dict, default=''):
def _get_instance_id(self, variables, default=''):
'''
Retrieve the instance ID from the given dict of host variables.
@@ -279,15 +272,23 @@ class Command(BaseCommand):
the lookup will traverse into nested dicts, equivalent to:
from_dict.get('foo', {}).get('bar', default)
Multiple ID variables may be specified as 'foo.bar,foobar', so that
it will first try to find 'bar' inside of 'foo', and if unable,
will try to find 'foobar' as a fallback
'''
instance_id = default
if getattr(self, 'instance_id_var', None):
for key in self.instance_id_var.split('.'):
if not hasattr(from_dict, 'get'):
instance_id = default
for single_instance_id in self.instance_id_var.split(','):
from_dict = variables
for key in single_instance_id.split('.'):
if not hasattr(from_dict, 'get'):
instance_id = default
break
instance_id = from_dict.get(key, default)
from_dict = instance_id
if instance_id:
break
instance_id = from_dict.get(key, default)
from_dict = instance_id
return smart_text(instance_id)
def _get_enabled(self, from_dict, default=None):
@@ -422,7 +423,7 @@ class Command(BaseCommand):
for mem_host in self.all_group.all_hosts.values():
instance_id = self._get_instance_id(mem_host.variables)
if not instance_id:
logger.warning('Host "%s" has no "%s" variable',
logger.warning('Host "%s" has no "%s" variable(s)',
mem_host.name, self.instance_id_var)
continue
mem_host.instance_id = instance_id

View File

@@ -19,3 +19,7 @@ class Command(BaseCommand):
profile_sql.delay(
threshold=options['threshold'], minutes=options['minutes']
)
print(f"Logging initiated with a threshold of {options['threshold']} second(s) and a duration of"
f" {options['minutes']} minute(s), any queries that meet criteria can"
f" be found in /var/log/tower/profile/."
)

View File

@@ -13,7 +13,7 @@ from django.core.management.base import BaseCommand, CommandError
class Command(BaseCommand):
"""
Internal tower command.
Regsiter this instance with the database for HA tracking.
Register this instance with the database for HA tracking.
"""
help = (

View File

@@ -82,7 +82,7 @@ class Command(BaseCommand):
OAuth2Application.objects.filter(pk=app.pk).update(client_secret=encrypted)
def _settings(self):
# don't update memcached, the *actual* value isn't changing
# don't update the cache, the *actual* value isn't changing
post_save.disconnect(on_post_save_setting, sender=Setting)
for setting in Setting.objects.filter().order_by('pk'):
if settings_registry.is_setting_encrypted(setting.key):

View File

@@ -32,4 +32,7 @@ class Command(BaseCommand):
sys.exit(1)
i = i.first()
ig.instances.remove(i)
if i.hostname in ig.policy_instance_list:
ig.policy_instance_list.remove(i.hostname)
ig.save()
print("Instance removed from instance group")

View File

@@ -4,6 +4,7 @@
from django.conf import settings
from django.core.management.base import BaseCommand
from awx.main.dispatch.control import Control
from awx.main.dispatch.worker import AWXConsumerRedis, CallbackBrokerWorker
@@ -15,7 +16,14 @@ class Command(BaseCommand):
'''
help = 'Launch the job callback receiver'
def add_arguments(self, parser):
parser.add_argument('--status', dest='status', action='store_true',
help='print the internal state of any running dispatchers')
def handle(self, *arg, **options):
if options.get('status'):
print(Control('callback_receiver').status())
return
consumer = None
try:
consumer = AWXConsumerRedis(

View File

@@ -44,7 +44,7 @@ class Command(BaseCommand):
# It's important to close these because we're _about_ to fork, and we
# don't want the forked processes to inherit the open sockets
# for the DB and memcached connections (that way lies race conditions)
# for the DB and cache connections (that way lies race conditions)
django_connection.close()
django_cache.close()

View File

@@ -44,25 +44,17 @@ class HostManager(models.Manager):
inventory_sources__source='tower'
).filter(inventory__organization=org_id).values('name').distinct().count()
def active_counts_by_org(self):
"""Return the counts of active, unique hosts for each organization.
Construction of query involves:
- remove any ordering specified in model's Meta
- Exclude hosts sourced from another Tower
- Consider only hosts where the canonical inventory is owned by each organization
- Restrict the query to only count distinct names
- Return the counts
"""
return self.order_by().exclude(
inventory_sources__source='tower'
).values('inventory__organization').annotate(
inventory__organization__count=models.Count('name', distinct=True))
def get_queryset(self):
"""When the parent instance of the host query set has a `kind=smart` and a `host_filter`
set. Use the `host_filter` to generate the queryset for the hosts.
"""
qs = super(HostManager, self).get_queryset()
qs = super(HostManager, self).get_queryset().defer(
'last_job__extra_vars',
'last_job_host_summary__job__extra_vars',
'last_job__artifacts',
'last_job_host_summary__job__artifacts',
)
if (hasattr(self, 'instance') and
hasattr(self.instance, 'host_filter') and
hasattr(self.instance, 'kind')):

View File

@@ -14,7 +14,7 @@ from django.conf import settings
from django.contrib.auth.models import User
from django.db.migrations.executor import MigrationExecutor
from django.db import connection
from django.shortcuts import get_object_or_404, redirect
from django.shortcuts import redirect
from django.apps import apps
from django.utils.deprecation import MiddlewareMixin
from django.utils.translation import ugettext_lazy as _
@@ -148,7 +148,21 @@ class URLModificationMiddleware(MiddlewareMixin):
def _named_url_to_pk(cls, node, resource, named_url):
kwargs = {}
if node.populate_named_url_query_kwargs(kwargs, named_url):
return str(get_object_or_404(node.model, **kwargs).pk)
match = node.model.objects.filter(**kwargs).first()
if match:
return str(match.pk)
else:
# if the name does *not* resolve to any actual resource,
# we should still attempt to route it through so that 401s are
# respected
# using "zero" here will cause the URL regex to match e.g.,
# /api/v2/users/<integer>/, but it also means that anonymous
# users will go down the path of having their credentials
# verified; in this way, *anonymous* users will that visit
# /api/v2/users/invalid-username/ *won't* see a 404, they'll
# see a 401 as if they'd gone to /api/v2/users/0/
#
return '0'
if resource == 'job_templates' and '++' not in named_url:
# special case for deprecated job template case
# will not raise a 404 on its own
@@ -178,6 +192,7 @@ class URLModificationMiddleware(MiddlewareMixin):
old_path = request.path_info
new_path = self._convert_named_url(old_path)
if request.path_info != new_path:
request.environ['awx.named_url_rewritten'] = request.path
request.path = request.path.replace(request.path_info, new_path)
request.path_info = new_path

View File

@@ -0,0 +1,29 @@
# Generated by Django 2.2.11 on 2020-05-01 13:25
from django.db import migrations, models
from awx.main.migrations._inventory_source import create_scm_script_substitute
def convert_cloudforms_to_scm(apps, schema_editor):
create_scm_script_substitute(apps, 'cloudforms')
class Migration(migrations.Migration):
dependencies = [
('main', '0116_v400_remove_hipchat_notifications'),
]
operations = [
migrations.RunPython(convert_cloudforms_to_scm),
migrations.AlterField(
model_name='inventorysource',
name='source',
field=models.CharField(choices=[('file', 'File, Directory or Script'), ('scm', 'Sourced from a Project'), ('ec2', 'Amazon EC2'), ('gce', 'Google Compute Engine'), ('azure_rm', 'Microsoft Azure Resource Manager'), ('vmware', 'VMware vCenter'), ('satellite6', 'Red Hat Satellite 6'), ('openstack', 'OpenStack'), ('rhv', 'Red Hat Virtualization'), ('tower', 'Ansible Tower'), ('custom', 'Custom Script')], default=None, max_length=32),
),
migrations.AlterField(
model_name='inventoryupdate',
name='source',
field=models.CharField(choices=[('file', 'File, Directory or Script'), ('scm', 'Sourced from a Project'), ('ec2', 'Amazon EC2'), ('gce', 'Google Compute Engine'), ('azure_rm', 'Microsoft Azure Resource Manager'), ('vmware', 'VMware vCenter'), ('satellite6', 'Red Hat Satellite 6'), ('openstack', 'OpenStack'), ('rhv', 'Red Hat Virtualization'), ('tower', 'Ansible Tower'), ('custom', 'Custom Script')], default=None, max_length=32),
),
]

View File

@@ -0,0 +1,23 @@
# Generated by Django 2.2.11 on 2020-08-18 22:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0117_v400_remove_cloudforms_inventory'),
]
operations = [
migrations.AlterField(
model_name='project',
name='scm_type',
field=models.CharField(blank=True, choices=[('', 'Manual'), ('git', 'Git'), ('hg', 'Mercurial'), ('svn', 'Subversion'), ('insights', 'Red Hat Insights'), ('archive', 'Remote Archive')], default='', help_text='Specifies the source control system used to store the project.', max_length=8, verbose_name='SCM Type'),
),
migrations.AlterField(
model_name='projectupdate',
name='scm_type',
field=models.CharField(blank=True, choices=[('', 'Manual'), ('git', 'Git'), ('hg', 'Mercurial'), ('svn', 'Subversion'), ('insights', 'Red Hat Insights'), ('archive', 'Remote Archive')], default='', help_text='Specifies the source control system used to store the project.', max_length=8, verbose_name='SCM Type'),
),
]

View File

@@ -0,0 +1,104 @@
# Generated by Django 2.2.11 on 2020-07-20 19:56
import logging
import yaml
from django.db import migrations, models
from awx.main.models.base import VarsDictProperty
from ._inventory_source_vars import FrozenInjectors
logger = logging.getLogger('awx.main.migrations')
def _get_inventory_sources(InventorySource):
return InventorySource.objects.filter(source__in=['ec2', 'gce', 'azure_rm', 'vmware', 'satellite6', 'openstack', 'rhv', 'tower'])
def inventory_source_vars_forward(apps, schema_editor):
InventorySource = apps.get_model("main", "InventorySource")
'''
The Django app registry does not keep track of model inheritance. The
source_vars_dict property comes from InventorySourceOptions via inheritance.
This adds that property. Luckily, other properteries and functionality from
InventorySourceOptions is not needed by the injector logic.
'''
setattr(InventorySource, 'source_vars_dict', VarsDictProperty('source_vars'))
source_vars_backup = dict()
for inv_source_obj in _get_inventory_sources(InventorySource):
if inv_source_obj.source in FrozenInjectors:
source_vars_backup[inv_source_obj.id] = dict(inv_source_obj.source_vars_dict)
injector = FrozenInjectors[inv_source_obj.source]()
new_inv_source_vars = injector.inventory_as_dict(inv_source_obj, None)
inv_source_obj.source_vars = yaml.dump(new_inv_source_vars)
inv_source_obj.save()
class Migration(migrations.Migration):
dependencies = [
('main', '0118_add_remote_archive_scm_type'),
]
operations = [
migrations.RunPython(inventory_source_vars_forward),
migrations.RemoveField(
model_name='inventorysource',
name='group_by',
),
migrations.RemoveField(
model_name='inventoryupdate',
name='group_by',
),
migrations.RemoveField(
model_name='inventorysource',
name='instance_filters',
),
migrations.RemoveField(
model_name='inventoryupdate',
name='instance_filters',
),
migrations.RemoveField(
model_name='inventorysource',
name='source_regions',
),
migrations.RemoveField(
model_name='inventoryupdate',
name='source_regions',
),
migrations.AddField(
model_name='inventorysource',
name='enabled_value',
field=models.TextField(blank=True, default='', help_text='Only used when enabled_var is set. Value when the host is considered enabled. For example if enabled_var="status.power_state"and enabled_value="powered_on" with host variables:{ "status": { "power_state": "powered_on", "created": "2020-08-04T18:13:04+00:00", "healthy": true }, "name": "foobar", "ip_address": "192.168.2.1"}The host would be marked enabled. If power_state where any value other than powered_on then the host would be disabled when imported into Tower. If the key is not found then the host will be enabled'),
),
migrations.AddField(
model_name='inventorysource',
name='enabled_var',
field=models.TextField(blank=True, default='', help_text='Retrieve the enabled state from the given dict of host variables. The enabled variable may be specified as "foo.bar", in which case the lookup will traverse into nested dicts, equivalent to: from_dict.get("foo", {}).get("bar", default)'),
),
migrations.AddField(
model_name='inventorysource',
name='host_filter',
field=models.TextField(blank=True, default='', help_text='Regex where only matching hosts will be imported into Tower.'),
),
migrations.AddField(
model_name='inventoryupdate',
name='enabled_value',
field=models.TextField(blank=True, default='', help_text='Only used when enabled_var is set. Value when the host is considered enabled. For example if enabled_var="status.power_state"and enabled_value="powered_on" with host variables:{ "status": { "power_state": "powered_on", "created": "2020-08-04T18:13:04+00:00", "healthy": true }, "name": "foobar", "ip_address": "192.168.2.1"}The host would be marked enabled. If power_state where any value other than powered_on then the host would be disabled when imported into Tower. If the key is not found then the host will be enabled'),
),
migrations.AddField(
model_name='inventoryupdate',
name='enabled_var',
field=models.TextField(blank=True, default='', help_text='Retrieve the enabled state from the given dict of host variables. The enabled variable may be specified as "foo.bar", in which case the lookup will traverse into nested dicts, equivalent to: from_dict.get("foo", {}).get("bar", default)'),
),
migrations.AddField(
model_name='inventoryupdate',
name='host_filter',
field=models.TextField(blank=True, default='', help_text='Regex where only matching hosts will be imported into Tower.'),
),
]

View File

@@ -0,0 +1,51 @@
# Generated by Django 2.2.11 on 2020-08-04 15:19
import logging
import awx.main.fields
from awx.main.utils.encryption import encrypt_field, decrypt_field
from django.db import migrations, models
from django.utils.timezone import now
import django.db.models.deletion
from awx.main.migrations import _galaxy as galaxy
from awx.main.models import CredentialType as ModernCredentialType
from awx.main.utils.common import set_current_apps
logger = logging.getLogger('awx.main.migrations')
class Migration(migrations.Migration):
dependencies = [
('main', '0119_inventory_plugins'),
]
operations = [
migrations.AlterField(
model_name='credentialtype',
name='kind',
field=models.CharField(choices=[('ssh', 'Machine'), ('vault', 'Vault'), ('net', 'Network'), ('scm', 'Source Control'), ('cloud', 'Cloud'), ('token', 'Personal Access Token'), ('insights', 'Insights'), ('external', 'External'), ('kubernetes', 'Kubernetes'), ('galaxy', 'Galaxy/Automation Hub')], max_length=32),
),
migrations.CreateModel(
name='OrganizationGalaxyCredentialMembership',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('position', models.PositiveIntegerField(db_index=True, default=None, null=True)),
('credential', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Credential')),
('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Organization')),
],
),
migrations.AddField(
model_name='organization',
name='galaxy_credentials',
field=awx.main.fields.OrderedManyToManyField(blank=True, related_name='organization_galaxy_credentials', through='main.OrganizationGalaxyCredentialMembership', to='main.Credential'),
),
migrations.AddField(
model_name='credential',
name='managed_by_tower',
field=models.BooleanField(default=False, editable=False),
),
migrations.RunPython(galaxy.migrate_galaxy_settings)
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 2.2.11 on 2020-07-24 17:41
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('main', '0120_galaxy_credentials'),
]
operations = [
migrations.DeleteModel(
name='TowerAnalyticsState',
),
]

View File

@@ -0,0 +1,125 @@
# Generated by Django 2.2.11 on 2020-08-04 15:19
import logging
from awx.main.utils.encryption import encrypt_field, decrypt_field
from django.conf import settings
from django.utils.timezone import now
from awx.main.models import CredentialType as ModernCredentialType
from awx.main.utils.common import set_current_apps
logger = logging.getLogger('awx.main.migrations')
def migrate_galaxy_settings(apps, schema_editor):
Organization = apps.get_model('main', 'Organization')
if Organization.objects.count() == 0:
# nothing to migrate
return
set_current_apps(apps)
ModernCredentialType.setup_tower_managed_defaults()
CredentialType = apps.get_model('main', 'CredentialType')
Credential = apps.get_model('main', 'Credential')
Setting = apps.get_model('conf', 'Setting')
galaxy_type = CredentialType.objects.get(kind='galaxy')
private_galaxy_url = Setting.objects.filter(key='PRIMARY_GALAXY_URL').first()
# by default, prior versions of AWX/Tower automatically pulled content
# from galaxy.ansible.com
public_galaxy_enabled = True
public_galaxy_setting = Setting.objects.filter(key='PUBLIC_GALAXY_ENABLED').first()
if public_galaxy_setting and public_galaxy_setting.value is False:
# ...UNLESS this behavior was explicitly disabled via this setting
public_galaxy_enabled = False
public_galaxy_credential = Credential(
created=now(),
modified=now(),
name='Ansible Galaxy',
managed_by_tower=True,
credential_type=galaxy_type,
inputs = {
'url': 'https://galaxy.ansible.com/'
}
)
public_galaxy_credential.save()
for org in Organization.objects.all():
if private_galaxy_url and private_galaxy_url.value:
# If a setting exists for a private Galaxy URL, make a credential for it
username = Setting.objects.filter(key='PRIMARY_GALAXY_USERNAME').first()
password = Setting.objects.filter(key='PRIMARY_GALAXY_PASSWORD').first()
if (username and username.value) or (password and password.value):
logger.error(
f'Specifying HTTP basic auth for the Ansible Galaxy API '
f'({private_galaxy_url.value}) is no longer supported. '
'Please provide an API token instead after your upgrade '
'has completed',
)
inputs = {
'url': private_galaxy_url.value
}
token = Setting.objects.filter(key='PRIMARY_GALAXY_TOKEN').first()
if token and token.value:
inputs['token'] = decrypt_field(token, 'value')
auth_url = Setting.objects.filter(key='PRIMARY_GALAXY_AUTH_URL').first()
if auth_url and auth_url.value:
inputs['auth_url'] = auth_url.value
name = f'Private Galaxy ({private_galaxy_url.value})'
if 'cloud.redhat.com' in inputs['url']:
name = f'Ansible Automation Hub ({private_galaxy_url.value})'
cred = Credential(
created=now(),
modified=now(),
name=name,
organization=org,
credential_type=galaxy_type,
inputs=inputs
)
cred.save()
if token and token.value:
# encrypt based on the primary key from the prior save
cred.inputs['token'] = encrypt_field(cred, 'token')
cred.save()
org.galaxy_credentials.add(cred)
fallback_servers = getattr(settings, 'FALLBACK_GALAXY_SERVERS', [])
for fallback in fallback_servers:
url = fallback.get('url', None)
auth_url = fallback.get('auth_url', None)
username = fallback.get('username', None)
password = fallback.get('password', None)
token = fallback.get('token', None)
if username or password:
logger.error(
f'Specifying HTTP basic auth for the Ansible Galaxy API '
f'({url}) is no longer supported. '
'Please provide an API token instead after your upgrade '
'has completed',
)
inputs = {'url': url}
if token:
inputs['token'] = token
if auth_url:
inputs['auth_url'] = auth_url
cred = Credential(
created=now(),
modified=now(),
name=f'Ansible Galaxy ({url})',
organization=org,
credential_type=galaxy_type,
inputs=inputs
)
cred.save()
if token:
# encrypt based on the primary key from the prior save
cred.inputs['token'] = encrypt_field(cred, 'token')
cred.save()
org.galaxy_credentials.add(cred)
if public_galaxy_enabled:
# If public Galaxy was enabled, associate it to the org
org.galaxy_credentials.add(public_galaxy_credential)

View File

@@ -1,6 +1,9 @@
import logging
from uuid import uuid4
from django.utils.encoding import smart_text
from django.utils.timezone import now
from awx.main.utils.common import parse_yaml_or_json
@@ -87,3 +90,44 @@ def back_out_new_instance_id(apps, source, new_id):
modified_ct, source
))
def create_scm_script_substitute(apps, source):
"""Only applies for cloudforms in practice, but written generally.
Given a source type, this will replace all inventory sources of that type
with SCM inventory sources that source the script from Ansible core
"""
# the revision in the Ansible 2.9 stable branch this project will start out as
# it can still be updated manually later (but staying within 2.9 branch), if desired
ansible_rev = '6f83b9aff42331e15c55a171de0a8b001208c18c'
InventorySource = apps.get_model('main', 'InventorySource')
ContentType = apps.get_model('contenttypes', 'ContentType')
Project = apps.get_model('main', 'Project')
if not InventorySource.objects.filter(source=source).exists():
logger.debug('No sources of type {} to migrate'.format(source))
return
proj_name = 'Replacement project for {} type sources - {}'.format(source, uuid4())
right_now = now()
project = Project.objects.create(
name=proj_name,
created=right_now,
modified=right_now,
description='Created by migration',
polymorphic_ctype=ContentType.objects.get(model='project'),
# project-specific fields
scm_type='git',
scm_url='https://github.com/ansible/ansible.git',
scm_branch='stable-2.9',
scm_revision=ansible_rev
)
ct = 0
for inv_src in InventorySource.objects.filter(source=source).iterator():
inv_src.source = 'scm'
inv_src.source_project = project
inv_src.source_path = 'contrib/inventory/{}.py'.format(source)
inv_src.scm_last_revision = ansible_rev
inv_src.save(update_fields=['source', 'source_project', 'source_path', 'scm_last_revision'])
logger.debug('Changed inventory source {} to scm type'.format(inv_src.pk))
ct += 1
if ct:
logger.info('Changed total of {} inventory sources from {} type to scm'.format(ct, source))

View File

@@ -0,0 +1,751 @@
import json
from django.utils.translation import ugettext_lazy as _
FrozenInjectors = dict()
class PluginFileInjector(object):
plugin_name = None # Ansible core name used to reference plugin
# every source should have collection, these are for the collection name
namespace = None
collection = None
def inventory_as_dict(self, inventory_source, private_data_dir):
"""Default implementation of inventory plugin file contents.
There are some valid cases when all parameters can be obtained from
the environment variables, example "plugin: linode" is valid
ideally, however, some options should be filled from the inventory source data
"""
if self.plugin_name is None:
raise NotImplementedError('At minimum the plugin name is needed for inventory plugin use.')
proper_name = f'{self.namespace}.{self.collection}.{self.plugin_name}'
return {'plugin': proper_name}
class azure_rm(PluginFileInjector):
plugin_name = 'azure_rm'
namespace = 'azure'
collection = 'azcollection'
def inventory_as_dict(self, inventory_source, private_data_dir):
ret = super(azure_rm, self).inventory_as_dict(inventory_source, private_data_dir)
source_vars = inventory_source.source_vars_dict
ret['fail_on_template_errors'] = False
group_by_hostvar = {
'location': {'prefix': '', 'separator': '', 'key': 'location'},
'tag': {'prefix': '', 'separator': '', 'key': 'tags.keys() | list if tags else []'},
# Introduced with https://github.com/ansible/ansible/pull/53046
'security_group': {'prefix': '', 'separator': '', 'key': 'security_group'},
'resource_group': {'prefix': '', 'separator': '', 'key': 'resource_group'},
# Note, os_family was not documented correctly in script, but defaulted to grouping by it
'os_family': {'prefix': '', 'separator': '', 'key': 'os_disk.operating_system_type'}
}
# by default group by everything
# always respect user setting, if they gave it
group_by = [
grouping_name for grouping_name in group_by_hostvar
if source_vars.get('group_by_{}'.format(grouping_name), True)
]
ret['keyed_groups'] = [group_by_hostvar[grouping_name] for grouping_name in group_by]
if 'tag' in group_by:
# Nasty syntax to reproduce "key_value" group names in addition to "key"
ret['keyed_groups'].append({
'prefix': '', 'separator': '',
'key': r'dict(tags.keys() | map("regex_replace", "^(.*)$", "\1_") | list | zip(tags.values() | list)) if tags else []'
})
# Compatibility content
# TODO: add proper support for instance_filters non-specific to compatibility
# TODO: add proper support for group_by non-specific to compatibility
# Dashes were not configurable in azure_rm.py script, we do not want unicode, so always use this
ret['use_contrib_script_compatible_sanitization'] = True
# use same host names as script
ret['plain_host_names'] = True
# By default the script did not filter hosts
ret['default_host_filters'] = []
# User-given host filters
user_filters = []
old_filterables = [
('resource_groups', 'resource_group'),
('tags', 'tags')
# locations / location would be an entry
# but this would conflict with source_regions
]
for key, loc in old_filterables:
value = source_vars.get(key, None)
if value and isinstance(value, str):
# tags can be list of key:value pairs
# e.g. 'Creator:jmarshall, peanutbutter:jelly'
# or tags can be a list of keys
# e.g. 'Creator, peanutbutter'
if key == "tags":
# grab each key value pair
for kvpair in value.split(','):
# split into key and value
kv = kvpair.split(':')
# filter out any host that does not have key
# in their tags.keys() variable
user_filters.append('"{}" not in tags.keys()'.format(kv[0].strip()))
# if a value is provided, check that the key:value pair matches
if len(kv) > 1:
user_filters.append('tags["{}"] != "{}"'.format(kv[0].strip(), kv[1].strip()))
else:
user_filters.append('{} not in {}'.format(
loc, value.split(',')
))
if user_filters:
ret.setdefault('exclude_host_filters', [])
ret['exclude_host_filters'].extend(user_filters)
ret['conditional_groups'] = {'azure': True}
ret['hostvar_expressions'] = {
'provisioning_state': 'provisioning_state | title',
'computer_name': 'name',
'type': 'resource_type',
'private_ip': 'private_ipv4_addresses[0] if private_ipv4_addresses else None',
'public_ip': 'public_ipv4_addresses[0] if public_ipv4_addresses else None',
'public_ip_name': 'public_ip_name if public_ip_name is defined else None',
'public_ip_id': 'public_ip_id if public_ip_id is defined else None',
'tags': 'tags if tags else None'
}
# Special functionality from script
if source_vars.get('use_private_ip', False):
ret['hostvar_expressions']['ansible_host'] = 'private_ipv4_addresses[0]'
# end compatibility content
if inventory_source.source_regions and 'all' not in inventory_source.source_regions:
# initialize a list for this section in inventory file
ret.setdefault('exclude_host_filters', [])
# make a python list of the regions we will use
python_regions = [x.strip() for x in inventory_source.source_regions.split(',')]
# convert that list in memory to python syntax in a string
# now put that in jinja2 syntax operating on hostvar key "location"
# and put that as an entry in the exclusions list
ret['exclude_host_filters'].append("location not in {}".format(repr(python_regions)))
return ret
class ec2(PluginFileInjector):
plugin_name = 'aws_ec2'
namespace = 'amazon'
collection = 'aws'
def _get_ec2_group_by_choices(self):
return [
('ami_id', _('Image ID')),
('availability_zone', _('Availability Zone')),
('aws_account', _('Account')),
('instance_id', _('Instance ID')),
('instance_state', _('Instance State')),
('platform', _('Platform')),
('instance_type', _('Instance Type')),
('key_pair', _('Key Name')),
('region', _('Region')),
('security_group', _('Security Group')),
('tag_keys', _('Tags')),
('tag_none', _('Tag None')),
('vpc_id', _('VPC ID')),
]
def _compat_compose_vars(self):
return {
# vars that change
'ec2_block_devices': (
"dict(block_device_mappings | map(attribute='device_name') | list | zip(block_device_mappings "
"| map(attribute='ebs.volume_id') | list))"
),
'ec2_dns_name': 'public_dns_name',
'ec2_group_name': 'placement.group_name',
'ec2_instance_profile': 'iam_instance_profile | default("")',
'ec2_ip_address': 'public_ip_address',
'ec2_kernel': 'kernel_id | default("")',
'ec2_monitored': "monitoring.state in ['enabled', 'pending']",
'ec2_monitoring_state': 'monitoring.state',
'ec2_placement': 'placement.availability_zone',
'ec2_ramdisk': 'ramdisk_id | default("")',
'ec2_reason': 'state_transition_reason',
'ec2_security_group_ids': "security_groups | map(attribute='group_id') | list | join(',')",
'ec2_security_group_names': "security_groups | map(attribute='group_name') | list | join(',')",
'ec2_tag_Name': 'tags.Name',
'ec2_state': 'state.name',
'ec2_state_code': 'state.code',
'ec2_state_reason': 'state_reason.message if state_reason is defined else ""',
'ec2_sourceDestCheck': 'source_dest_check | default(false) | lower | string', # snake_case syntax intended
'ec2_account_id': 'owner_id',
# vars that just need ec2_ prefix
'ec2_ami_launch_index': 'ami_launch_index | string',
'ec2_architecture': 'architecture',
'ec2_client_token': 'client_token',
'ec2_ebs_optimized': 'ebs_optimized',
'ec2_hypervisor': 'hypervisor',
'ec2_image_id': 'image_id',
'ec2_instance_type': 'instance_type',
'ec2_key_name': 'key_name',
'ec2_launch_time': r'launch_time | regex_replace(" ", "T") | regex_replace("(\+)(\d\d):(\d)(\d)$", ".\g<2>\g<3>Z")',
'ec2_platform': 'platform | default("")',
'ec2_private_dns_name': 'private_dns_name',
'ec2_private_ip_address': 'private_ip_address',
'ec2_public_dns_name': 'public_dns_name',
'ec2_region': 'placement.region',
'ec2_root_device_name': 'root_device_name',
'ec2_root_device_type': 'root_device_type',
# many items need blank defaults because the script tended to keep a common schema
'ec2_spot_instance_request_id': 'spot_instance_request_id | default("")',
'ec2_subnet_id': 'subnet_id | default("")',
'ec2_virtualization_type': 'virtualization_type',
'ec2_vpc_id': 'vpc_id | default("")',
# same as ec2_ip_address, the script provided this
'ansible_host': 'public_ip_address',
# new with https://github.com/ansible/ansible/pull/53645
'ec2_eventsSet': 'events | default("")',
'ec2_persistent': 'persistent | default(false)',
'ec2_requester_id': 'requester_id | default("")'
}
def inventory_as_dict(self, inventory_source, private_data_dir):
ret = super(ec2, self).inventory_as_dict(inventory_source, private_data_dir)
keyed_groups = []
group_by_hostvar = {
'ami_id': {'prefix': '', 'separator': '', 'key': 'image_id', 'parent_group': 'images'},
# 2 entries for zones for same groups to establish 2 parentage trees
'availability_zone': {'prefix': '', 'separator': '', 'key': 'placement.availability_zone', 'parent_group': 'zones'},
'aws_account': {'prefix': '', 'separator': '', 'key': 'ec2_account_id', 'parent_group': 'accounts'}, # composed var
'instance_id': {'prefix': '', 'separator': '', 'key': 'instance_id', 'parent_group': 'instances'}, # normally turned off
'instance_state': {'prefix': 'instance_state', 'key': 'ec2_state', 'parent_group': 'instance_states'}, # composed var
# ec2_platform is a composed var, but group names do not match up to hostvar exactly
'platform': {'prefix': 'platform', 'key': 'platform | default("undefined")', 'parent_group': 'platforms'},
'instance_type': {'prefix': 'type', 'key': 'instance_type', 'parent_group': 'types'},
'key_pair': {'prefix': 'key', 'key': 'key_name', 'parent_group': 'keys'},
'region': {'prefix': '', 'separator': '', 'key': 'placement.region', 'parent_group': 'regions'},
# Security requires some ninja jinja2 syntax, credit to s-hertel
'security_group': {'prefix': 'security_group', 'key': 'security_groups | map(attribute="group_name")', 'parent_group': 'security_groups'},
# tags cannot be parented in exactly the same way as the script due to
# https://github.com/ansible/ansible/pull/53812
'tag_keys': [
{'prefix': 'tag', 'key': 'tags', 'parent_group': 'tags'},
{'prefix': 'tag', 'key': 'tags.keys()', 'parent_group': 'tags'}
],
# 'tag_none': None, # grouping by no tags isn't a different thing with plugin
# naming is redundant, like vpc_id_vpc_8c412cea, but intended
'vpc_id': {'prefix': 'vpc_id', 'key': 'vpc_id', 'parent_group': 'vpcs'},
}
# -- same-ish as script here --
group_by = [x.strip().lower() for x in inventory_source.group_by.split(',') if x.strip()]
for choice in self._get_ec2_group_by_choices():
value = bool((group_by and choice[0] in group_by) or (not group_by and choice[0] != 'instance_id'))
# -- end sameness to script --
if value:
this_keyed_group = group_by_hostvar.get(choice[0], None)
# If a keyed group syntax does not exist, there is nothing we can do to get this group
if this_keyed_group is not None:
if isinstance(this_keyed_group, list):
keyed_groups.extend(this_keyed_group)
else:
keyed_groups.append(this_keyed_group)
# special case, this parentage is only added if both zones and regions are present
if not group_by or ('region' in group_by and 'availability_zone' in group_by):
keyed_groups.append({'prefix': '', 'separator': '', 'key': 'placement.availability_zone', 'parent_group': '{{ placement.region }}'})
source_vars = inventory_source.source_vars_dict
# This is a setting from the script, hopefully no one used it
# if true, it replaces dashes, but not in region / loc names
replace_dash = bool(source_vars.get('replace_dash_in_groups', True))
# Compatibility content
legacy_regex = {
True: r"[^A-Za-z0-9\_]",
False: r"[^A-Za-z0-9\_\-]" # do not replace dash, dash is allowed
}[replace_dash]
list_replacer = 'map("regex_replace", "{rx}", "_") | list'.format(rx=legacy_regex)
# this option, a plugin option, will allow dashes, but not unicode
# when set to False, unicode will be allowed, but it was not allowed by script
# thus, we always have to use this option, and always use our custom regex
ret['use_contrib_script_compatible_sanitization'] = True
for grouping_data in keyed_groups:
if grouping_data['key'] in ('placement.region', 'placement.availability_zone'):
# us-east-2 is always us-east-2 according to ec2.py
# no sanitization in region-ish groups for the script standards, ever ever
continue
if grouping_data['key'] == 'tags':
# dict jinja2 transformation
grouping_data['key'] = 'dict(tags.keys() | {replacer} | zip(tags.values() | {replacer}))'.format(
replacer=list_replacer
)
elif grouping_data['key'] == 'tags.keys()' or grouping_data['prefix'] == 'security_group':
# list jinja2 transformation
grouping_data['key'] += ' | {replacer}'.format(replacer=list_replacer)
else:
# string transformation
grouping_data['key'] += ' | regex_replace("{rx}", "_")'.format(rx=legacy_regex)
# end compatibility content
if source_vars.get('iam_role_arn', None):
ret['iam_role_arn'] = source_vars['iam_role_arn']
# This was an allowed ec2.ini option, also plugin option, so pass through
if source_vars.get('boto_profile', None):
ret['boto_profile'] = source_vars['boto_profile']
elif not replace_dash:
# Using the plugin, but still want dashes allowed
ret['use_contrib_script_compatible_sanitization'] = True
if source_vars.get('nested_groups') is False:
for this_keyed_group in keyed_groups:
this_keyed_group.pop('parent_group', None)
if keyed_groups:
ret['keyed_groups'] = keyed_groups
# Instance ID not part of compat vars, because of settings.EC2_INSTANCE_ID_VAR
compose_dict = {'ec2_id': 'instance_id'}
inst_filters = {}
# Compatibility content
compose_dict.update(self._compat_compose_vars())
# plugin provides "aws_ec2", but not this which the script gave
ret['groups'] = {'ec2': True}
if source_vars.get('hostname_variable') is not None:
hnames = []
for expr in source_vars.get('hostname_variable').split(','):
if expr == 'public_dns_name':
hnames.append('dns-name')
elif not expr.startswith('tag:') and '_' in expr:
hnames.append(expr.replace('_', '-'))
else:
hnames.append(expr)
ret['hostnames'] = hnames
else:
# public_ip as hostname is non-default plugin behavior, script behavior
ret['hostnames'] = [
'network-interface.addresses.association.public-ip',
'dns-name',
'private-dns-name'
]
# The script returned only running state by default, the plugin does not
# https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html#options
# options: pending | running | shutting-down | terminated | stopping | stopped
inst_filters['instance-state-name'] = ['running']
# end compatibility content
if source_vars.get('destination_variable') or source_vars.get('vpc_destination_variable'):
for fd in ('destination_variable', 'vpc_destination_variable'):
if source_vars.get(fd):
compose_dict['ansible_host'] = source_vars.get(fd)
break
if compose_dict:
ret['compose'] = compose_dict
if inventory_source.instance_filters:
# logic used to live in ec2.py, now it belongs to us. Yay more code?
filter_sets = [f for f in inventory_source.instance_filters.split(',') if f]
for instance_filter in filter_sets:
# AND logic not supported, unclear how to...
instance_filter = instance_filter.strip()
if not instance_filter or '=' not in instance_filter:
continue
filter_key, filter_value = [x.strip() for x in instance_filter.split('=', 1)]
if not filter_key:
continue
inst_filters[filter_key] = filter_value
if inst_filters:
ret['filters'] = inst_filters
if inventory_source.source_regions and 'all' not in inventory_source.source_regions:
ret['regions'] = inventory_source.source_regions.split(',')
return ret
class gce(PluginFileInjector):
plugin_name = 'gcp_compute'
namespace = 'google'
collection = 'cloud'
def _compat_compose_vars(self):
# missing: gce_image, gce_uuid
# https://github.com/ansible/ansible/issues/51884
return {
'gce_description': 'description if description else None',
'gce_machine_type': 'machineType',
'gce_name': 'name',
'gce_network': 'networkInterfaces[0].network.name',
'gce_private_ip': 'networkInterfaces[0].networkIP',
'gce_public_ip': 'networkInterfaces[0].accessConfigs[0].natIP | default(None)',
'gce_status': 'status',
'gce_subnetwork': 'networkInterfaces[0].subnetwork.name',
'gce_tags': 'tags.get("items", [])',
'gce_zone': 'zone',
'gce_metadata': 'metadata.get("items", []) | items2dict(key_name="key", value_name="value")',
# NOTE: image hostvar is enabled via retrieve_image_info option
'gce_image': 'image',
# We need this as long as hostnames is non-default, otherwise hosts
# will not be addressed correctly, was returned in script
'ansible_ssh_host': 'networkInterfaces[0].accessConfigs[0].natIP | default(networkInterfaces[0].networkIP)'
}
def inventory_as_dict(self, inventory_source, private_data_dir):
ret = super(gce, self).inventory_as_dict(inventory_source, private_data_dir)
# auth related items
ret['auth_kind'] = "serviceaccount"
filters = []
# TODO: implement gce group_by options
# gce never processed the group_by field, if it had, we would selectively
# apply those options here, but it did not, so all groups are added here
keyed_groups = [
# the jinja2 syntax is duplicated with compose
# https://github.com/ansible/ansible/issues/51883
{'prefix': 'network', 'key': 'gce_subnetwork'}, # composed var
{'prefix': '', 'separator': '', 'key': 'gce_private_ip'}, # composed var
{'prefix': '', 'separator': '', 'key': 'gce_public_ip'}, # composed var
{'prefix': '', 'separator': '', 'key': 'machineType'},
{'prefix': '', 'separator': '', 'key': 'zone'},
{'prefix': 'tag', 'key': 'gce_tags'}, # composed var
{'prefix': 'status', 'key': 'status | lower'},
# NOTE: image hostvar is enabled via retrieve_image_info option
{'prefix': '', 'separator': '', 'key': 'image'},
]
# This will be used as the gce instance_id, must be universal, non-compat
compose_dict = {'gce_id': 'id'}
# Compatibility content
# TODO: proper group_by and instance_filters support, irrelevant of compat mode
# The gce.py script never sanitized any names in any way
ret['use_contrib_script_compatible_sanitization'] = True
# Perform extra API query to get the image hostvar
ret['retrieve_image_info'] = True
# Add in old hostvars aliases
compose_dict.update(self._compat_compose_vars())
# Non-default names to match script
ret['hostnames'] = ['name', 'public_ip', 'private_ip']
# end compatibility content
if keyed_groups:
ret['keyed_groups'] = keyed_groups
if filters:
ret['filters'] = filters
if compose_dict:
ret['compose'] = compose_dict
if inventory_source.source_regions and 'all' not in inventory_source.source_regions:
ret['zones'] = inventory_source.source_regions.split(',')
return ret
class vmware(PluginFileInjector):
plugin_name = 'vmware_vm_inventory'
namespace = 'community'
collection = 'vmware'
def inventory_as_dict(self, inventory_source, private_data_dir):
ret = super(vmware, self).inventory_as_dict(inventory_source, private_data_dir)
ret['strict'] = False
# Documentation of props, see
# https://github.com/ansible/ansible/blob/devel/docs/docsite/rst/scenario_guides/vmware_scenarios/vmware_inventory_vm_attributes.rst
UPPERCASE_PROPS = [
"availableField",
"configIssue",
"configStatus",
"customValue", # optional
"datastore",
"effectiveRole",
"guestHeartbeatStatus", # optional
"layout", # optional
"layoutEx", # optional
"name",
"network",
"overallStatus",
"parentVApp", # optional
"permission",
"recentTask",
"resourcePool",
"rootSnapshot",
"snapshot", # optional
"triggeredAlarmState",
"value"
]
NESTED_PROPS = [
"capability",
"config",
"guest",
"runtime",
"storage",
"summary", # repeat of other properties
]
ret['properties'] = UPPERCASE_PROPS + NESTED_PROPS
ret['compose'] = {'ansible_host': 'guest.ipAddress'} # default value
ret['compose']['ansible_ssh_host'] = ret['compose']['ansible_host']
# the ansible_uuid was unique every host, every import, from the script
ret['compose']['ansible_uuid'] = '99999999 | random | to_uuid'
for prop in UPPERCASE_PROPS:
if prop == prop.lower():
continue
ret['compose'][prop.lower()] = prop
ret['with_nested_properties'] = True
# ret['property_name_format'] = 'lower_case' # only dacrystal/topic/vmware-inventory-plugin-property-format
# process custom options
vmware_opts = dict(inventory_source.source_vars_dict.items())
if inventory_source.instance_filters:
vmware_opts.setdefault('host_filters', inventory_source.instance_filters)
if inventory_source.group_by:
vmware_opts.setdefault('groupby_patterns', inventory_source.group_by)
alias_pattern = vmware_opts.get('alias_pattern')
if alias_pattern:
ret.setdefault('hostnames', [])
for alias in alias_pattern.split(','): # make best effort
striped_alias = alias.replace('{', '').replace('}', '').strip() # make best effort
if not striped_alias:
continue
ret['hostnames'].append(striped_alias)
host_pattern = vmware_opts.get('host_pattern') # not working in script
if host_pattern:
stripped_hp = host_pattern.replace('{', '').replace('}', '').strip() # make best effort
ret['compose']['ansible_host'] = stripped_hp
ret['compose']['ansible_ssh_host'] = stripped_hp
host_filters = vmware_opts.get('host_filters')
if host_filters:
ret.setdefault('filters', [])
for hf in host_filters.split(','):
striped_hf = hf.replace('{', '').replace('}', '').strip() # make best effort
if not striped_hf:
continue
ret['filters'].append(striped_hf)
else:
# default behavior filters by power state
ret['filters'] = ['runtime.powerState == "poweredOn"']
groupby_patterns = vmware_opts.get('groupby_patterns')
ret.setdefault('keyed_groups', [])
if groupby_patterns:
for pattern in groupby_patterns.split(','):
stripped_pattern = pattern.replace('{', '').replace('}', '').strip() # make best effort
ret['keyed_groups'].append({
'prefix': '', 'separator': '',
'key': stripped_pattern
})
else:
# default groups from script
for entry in ('config.guestId', '"templates" if config.template else "guests"'):
ret['keyed_groups'].append({
'prefix': '', 'separator': '',
'key': entry
})
return ret
class openstack(PluginFileInjector):
plugin_name = 'openstack'
namespace = 'openstack'
collection = 'cloud'
def inventory_as_dict(self, inventory_source, private_data_dir):
def use_host_name_for_name(a_bool_maybe):
if not isinstance(a_bool_maybe, bool):
# Could be specified by user via "host" or "uuid"
return a_bool_maybe
elif a_bool_maybe:
return 'name' # plugin default
else:
return 'uuid'
ret = super(openstack, self).inventory_as_dict(inventory_source, private_data_dir)
ret['fail_on_errors'] = True
ret['expand_hostvars'] = True
ret['inventory_hostname'] = use_host_name_for_name(False)
# Note: mucking with defaults will break import integrity
# For the plugin, we need to use the same defaults as the old script
# or else imports will conflict. To find script defaults you have
# to read source code of the script.
#
# Script Defaults Plugin Defaults
# 'use_hostnames': False, 'name' (True)
# 'expand_hostvars': True, 'no' (False)
# 'fail_on_errors': True, 'no' (False)
#
# These are, yet again, different from ansible_variables in script logic
# but those are applied inconsistently
source_vars = inventory_source.source_vars_dict
for var_name in ['expand_hostvars', 'fail_on_errors']:
if var_name in source_vars:
ret[var_name] = source_vars[var_name]
if 'use_hostnames' in source_vars:
ret['inventory_hostname'] = use_host_name_for_name(source_vars['use_hostnames'])
return ret
class rhv(PluginFileInjector):
"""ovirt uses the custom credential templating, and that is all
"""
plugin_name = 'ovirt'
initial_version = '2.9'
namespace = 'ovirt'
collection = 'ovirt'
def inventory_as_dict(self, inventory_source, private_data_dir):
ret = super(rhv, self).inventory_as_dict(inventory_source, private_data_dir)
ret['ovirt_insecure'] = False # Default changed from script
# TODO: process strict option upstream
ret['compose'] = {
'ansible_host': '(devices.values() | list)[0][0] if devices else None'
}
ret['keyed_groups'] = []
for key in ('cluster', 'status'):
ret['keyed_groups'].append({'prefix': key, 'separator': '_', 'key': key})
ret['keyed_groups'].append({'prefix': 'tag', 'separator': '_', 'key': 'tags'})
ret['ovirt_hostname_preference'] = ['name', 'fqdn']
source_vars = inventory_source.source_vars_dict
for key, value in source_vars.items():
if key == 'plugin':
continue
ret[key] = value
return ret
class satellite6(PluginFileInjector):
plugin_name = 'foreman'
namespace = 'theforeman'
collection = 'foreman'
def inventory_as_dict(self, inventory_source, private_data_dir):
ret = super(satellite6, self).inventory_as_dict(inventory_source, private_data_dir)
ret['validate_certs'] = False
group_patterns = '[]'
group_prefix = 'foreman_'
want_hostcollections = False
want_ansible_ssh_host = False
want_facts = True
foreman_opts = inventory_source.source_vars_dict.copy()
for k, v in foreman_opts.items():
if k == 'satellite6_group_patterns' and isinstance(v, str):
group_patterns = v
elif k == 'satellite6_group_prefix' and isinstance(v, str):
group_prefix = v
elif k == 'satellite6_want_hostcollections' and isinstance(v, bool):
want_hostcollections = v
elif k == 'satellite6_want_ansible_ssh_host' and isinstance(v, bool):
want_ansible_ssh_host = v
elif k == 'satellite6_want_facts' and isinstance(v, bool):
want_facts = v
# add backwards support for ssl_verify
# plugin uses new option, validate_certs, instead
elif k == 'ssl_verify' and isinstance(v, bool):
ret['validate_certs'] = v
else:
ret[k] = str(v)
# Compatibility content
group_by_hostvar = {
"environment": {"prefix": "{}environment_".format(group_prefix),
"separator": "",
"key": "foreman['environment_name'] | lower | regex_replace(' ', '') | "
"regex_replace('[^A-Za-z0-9_]', '_') | regex_replace('none', '')"},
"location": {"prefix": "{}location_".format(group_prefix),
"separator": "",
"key": "foreman['location_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')"},
"organization": {"prefix": "{}organization_".format(group_prefix),
"separator": "",
"key": "foreman['organization_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')"},
"lifecycle_environment": {"prefix": "{}lifecycle_environment_".format(group_prefix),
"separator": "",
"key": "foreman['content_facet_attributes']['lifecycle_environment_name'] | "
"lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')"},
"content_view": {"prefix": "{}content_view_".format(group_prefix),
"separator": "",
"key": "foreman['content_facet_attributes']['content_view_name'] | "
"lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')"}
}
ret['legacy_hostvars'] = True # convert hostvar structure to the form used by the script
ret['want_params'] = True
ret['group_prefix'] = group_prefix
ret['want_hostcollections'] = want_hostcollections
ret['want_facts'] = want_facts
if want_ansible_ssh_host:
ret['compose'] = {'ansible_ssh_host': "foreman['ip6'] | default(foreman['ip'], true)"}
ret['keyed_groups'] = [group_by_hostvar[grouping_name] for grouping_name in group_by_hostvar]
def form_keyed_group(group_pattern):
"""
Converts foreman group_pattern to
inventory plugin keyed_group
e.g. {app_param}-{tier_param}-{dc_param}
becomes
"%s-%s-%s" | format(app_param, tier_param, dc_param)
"""
if type(group_pattern) is not str:
return None
params = re.findall('{[^}]*}', group_pattern)
if len(params) == 0:
return None
param_names = []
for p in params:
param_names.append(p[1:-1].strip()) # strip braces and space
# form keyed_group key by
# replacing curly braces with '%s'
# (for use with jinja's format filter)
key = group_pattern
for p in params:
key = key.replace(p, '%s', 1)
# apply jinja filter to key
key = '"{}" | format({})'.format(key, ', '.join(param_names))
keyed_group = {'key': key,
'separator': ''}
return keyed_group
try:
group_patterns = json.loads(group_patterns)
if type(group_patterns) is list:
for group_pattern in group_patterns:
keyed_group = form_keyed_group(group_pattern)
if keyed_group:
ret['keyed_groups'].append(keyed_group)
except json.JSONDecodeError:
logger.warning('Could not parse group_patterns. Expected JSON-formatted string, found: {}'
.format(group_patterns))
return ret
class tower(PluginFileInjector):
plugin_name = 'tower'
namespace = 'awx'
collection = 'awx'
def inventory_as_dict(self, inventory_source, private_data_dir):
ret = super(tower, self).inventory_as_dict(inventory_source, private_data_dir)
# Credentials injected as env vars, same as script
try:
# plugin can take an actual int type
identifier = int(inventory_source.instance_filters)
except ValueError:
# inventory_id could be a named URL
identifier = iri_to_uri(inventory_source.instance_filters)
ret['inventory_id'] = identifier
ret['include_metadata'] = True # used for license check
return ret
for cls in PluginFileInjector.__subclasses__():
FrozenInjectors[cls.__name__] = cls

View File

@@ -127,9 +127,15 @@ def user_get_auditor_of_organizations(user):
return Organization.objects.filter(auditor_role__members=user)
@property
def created(user):
return user.date_joined
User.add_to_class('organizations', user_get_organizations)
User.add_to_class('admin_of_organizations', user_get_admin_of_organizations)
User.add_to_class('auditor_of_organizations', user_get_auditor_of_organizations)
User.add_to_class('created', created)
@property

View File

@@ -15,6 +15,7 @@ from crum import get_current_user
# AWX
from awx.main.utils import encrypt_field, parse_yaml_or_json
from awx.main.constants import CLOUD_PROVIDERS
__all__ = ['prevent_search', 'VarsDictProperty', 'BaseModel', 'CreatedModifiedModel',
'PasswordFieldsModel', 'PrimordialModel', 'CommonModel',
@@ -50,7 +51,7 @@ PROJECT_UPDATE_JOB_TYPE_CHOICES = [
(PERM_INVENTORY_CHECK, _('Check')),
]
CLOUD_INVENTORY_SOURCES = ['ec2', 'vmware', 'gce', 'azure_rm', 'openstack', 'rhv', 'custom', 'satellite6', 'cloudforms', 'scm', 'tower',]
CLOUD_INVENTORY_SOURCES = list(CLOUD_PROVIDERS) + ['scm', 'custom']
VERBOSITY_CHOICES = [
(0, '0 (Normal)'),
@@ -406,7 +407,7 @@ def prevent_search(relation):
sensitive_data = prevent_search(models.CharField(...))
The flag set by this function is used by
`awx.api.filters.FieldLookupBackend` to blacklist fields and relations that
`awx.api.filters.FieldLookupBackend` to block fields and relations that
should not be searchable/filterable via search query params
"""
setattr(relation, '__prevent_search__', True)

View File

@@ -11,7 +11,7 @@ import tempfile
from types import SimpleNamespace
# Jinja2
from jinja2 import Template
from jinja2 import sandbox
# Django
from django.db import models
@@ -96,6 +96,10 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin):
help_text=_('Specify the type of credential you want to create. Refer '
'to the Ansible Tower documentation for details on each type.')
)
managed_by_tower = models.BooleanField(
default=False,
editable=False
)
organization = models.ForeignKey(
'Organization',
null=True,
@@ -331,6 +335,7 @@ class CredentialType(CommonModelNameNotUnique):
('insights', _('Insights')),
('external', _('External')),
('kubernetes', _('Kubernetes')),
('galaxy', _('Galaxy/Automation Hub')),
)
kind = models.CharField(
@@ -514,8 +519,11 @@ class CredentialType(CommonModelNameNotUnique):
# If any file templates are provided, render the files and update the
# special `tower` template namespace so the filename can be
# referenced in other injectors
sandbox_env = sandbox.ImmutableSandboxedEnvironment()
for file_label, file_tmpl in file_tmpls.items():
data = Template(file_tmpl).render(**namespace)
data = sandbox_env.from_string(file_tmpl).render(**namespace)
_, path = tempfile.mkstemp(dir=private_data_dir)
with open(path, 'w') as f:
f.write(data)
@@ -537,14 +545,14 @@ class CredentialType(CommonModelNameNotUnique):
except ValidationError as e:
logger.error('Ignoring prohibited env var {}, reason: {}'.format(env_var, e))
continue
env[env_var] = Template(tmpl).render(**namespace)
safe_env[env_var] = Template(tmpl).render(**safe_namespace)
env[env_var] = sandbox_env.from_string(tmpl).render(**namespace)
safe_env[env_var] = sandbox_env.from_string(tmpl).render(**safe_namespace)
if 'INVENTORY_UPDATE_ID' not in env:
# awx-manage inventory_update does not support extra_vars via -e
extra_vars = {}
for var_name, tmpl in self.injectors.get('extra_vars', {}).items():
extra_vars[var_name] = Template(tmpl).render(**namespace)
extra_vars[var_name] = sandbox_env.from_string(tmpl).render(**namespace)
def build_extra_vars_file(vars, private_dir):
handle, path = tempfile.mkstemp(dir = private_dir)
@@ -1103,26 +1111,36 @@ ManagedCredentialType(
}, {
'id': 'username',
'label': ugettext_noop('Username'),
'type': 'string'
'type': 'string',
'help_text': ugettext_noop('The Ansible Tower user to authenticate as.'
'This should not be set if an OAuth token is being used.')
}, {
'id': 'password',
'label': ugettext_noop('Password'),
'type': 'string',
'secret': True,
}, {
'id': 'oauth_token',
'label': ugettext_noop('OAuth Token'),
'type': 'string',
'secret': True,
'help_text': ugettext_noop('An OAuth token to use to authenticate to Tower with.'
'This should not be set if username/password are being used.')
}, {
'id': 'verify_ssl',
'label': ugettext_noop('Verify SSL'),
'type': 'boolean',
'secret': False
}],
'required': ['host', 'username', 'password'],
'required': ['host'],
},
injectors={
'env': {
'TOWER_HOST': '{{host}}',
'TOWER_USERNAME': '{{username}}',
'TOWER_PASSWORD': '{{password}}',
'TOWER_VERIFY_SSL': '{{verify_ssl}}'
'TOWER_VERIFY_SSL': '{{verify_ssl}}',
'TOWER_OAUTH_TOKEN': '{{oauth_token}}'
}
},
)
@@ -1160,6 +1178,38 @@ ManagedCredentialType(
)
ManagedCredentialType(
namespace='galaxy_api_token',
kind='galaxy',
name=ugettext_noop('Ansible Galaxy/Automation Hub API Token'),
inputs={
'fields': [{
'id': 'url',
'label': ugettext_noop('Galaxy Server URL'),
'type': 'string',
'help_text': ugettext_noop('The URL of the Galaxy instance to connect to.')
},{
'id': 'auth_url',
'label': ugettext_noop('Auth Server URL'),
'type': 'string',
'help_text': ugettext_noop(
'The URL of a Keycloak server token_endpoint, if using '
'SSO auth.'
)
},{
'id': 'token',
'label': ugettext_noop('API Token'),
'type': 'string',
'secret': True,
'help_text': ugettext_noop(
'A token to use for authentication against the Galaxy instance.'
)
}],
'required': ['url'],
}
)
class CredentialInputSource(PrimordialModel):
class Meta:

View File

@@ -101,3 +101,17 @@ def openstack(cred, env, private_data_dir):
f.close()
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
env['OS_CLIENT_CONFIG_FILE'] = path
def kubernetes_bearer_token(cred, env, private_data_dir):
env['K8S_AUTH_HOST'] = cred.get_input('host', default='')
env['K8S_AUTH_API_KEY'] = cred.get_input('bearer_token', default='')
if cred.get_input('verify_ssl') and 'ssl_ca_cert' in cred.inputs:
env['K8S_AUTH_VERIFY_SSL'] = 'True'
handle, path = tempfile.mkstemp(dir=private_data_dir)
with os.fdopen(handle, 'w') as f:
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
f.write(cred.get_input('ssl_ca_cert'))
env['K8S_AUTH_SSL_CA_CERT'] = path
else:
env['K8S_AUTH_VERIFY_SSL'] = 'False'

View File

@@ -4,6 +4,8 @@ import datetime
import logging
from collections import defaultdict
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.db import models, DatabaseError, connection
from django.utils.dateparse import parse_datetime
from django.utils.text import Truncator
@@ -57,7 +59,18 @@ def create_host_status_counts(event_data):
return dict(host_status_counts)
MINIMAL_EVENTS = set([
'playbook_on_play_start', 'playbook_on_task_start',
'playbook_on_stats', 'EOF'
])
def emit_event_detail(event):
if (
settings.UI_LIVE_UPDATES_ENABLED is False and
event.event not in MINIMAL_EVENTS
):
return
cls = event.__class__
relation = {
JobEvent: 'job_id',
@@ -337,41 +350,47 @@ class BasePlaybookEvent(CreatedModifiedModel):
pass
if isinstance(self, JobEvent):
hostnames = self._hostnames()
self._update_host_summary_from_stats(hostnames)
if self.job.inventory:
try:
self.job.inventory.update_computed_fields()
except DatabaseError:
logger.exception('Computed fields database error saving event {}'.format(self.pk))
try:
job = self.job
except ObjectDoesNotExist:
job = None
if job:
hostnames = self._hostnames()
self._update_host_summary_from_stats(set(hostnames))
if job.inventory:
try:
job.inventory.update_computed_fields()
except DatabaseError:
logger.exception('Computed fields database error saving event {}'.format(self.pk))
# find parent links and progagate changed=T and failed=T
changed = self.job.job_events.filter(changed=True).exclude(parent_uuid=None).only('parent_uuid').values_list('parent_uuid', flat=True).distinct() # noqa
failed = self.job.job_events.filter(failed=True).exclude(parent_uuid=None).only('parent_uuid').values_list('parent_uuid', flat=True).distinct() # noqa
# find parent links and progagate changed=T and failed=T
changed = job.job_events.filter(changed=True).exclude(parent_uuid=None).only('parent_uuid').values_list('parent_uuid', flat=True).distinct() # noqa
failed = job.job_events.filter(failed=True).exclude(parent_uuid=None).only('parent_uuid').values_list('parent_uuid', flat=True).distinct() # noqa
JobEvent.objects.filter(
job_id=self.job_id, uuid__in=changed
).update(changed=True)
JobEvent.objects.filter(
job_id=self.job_id, uuid__in=failed
).update(failed=True)
JobEvent.objects.filter(
job_id=self.job_id, uuid__in=changed
).update(changed=True)
JobEvent.objects.filter(
job_id=self.job_id, uuid__in=failed
).update(failed=True)
# send success/failure notifications when we've finished handling the playbook_on_stats event
from awx.main.tasks import handle_success_and_failure_notifications # circular import
# send success/failure notifications when we've finished handling the playbook_on_stats event
from awx.main.tasks import handle_success_and_failure_notifications # circular import
def _send_notifications():
handle_success_and_failure_notifications.apply_async([self.job.id])
connection.on_commit(_send_notifications)
def _send_notifications():
handle_success_and_failure_notifications.apply_async([job.id])
connection.on_commit(_send_notifications)
for field in ('playbook', 'play', 'task', 'role'):
value = force_text(event_data.get(field, '')).strip()
if value != getattr(self, field):
setattr(self, field, value)
analytics_logger.info(
'Event data saved.',
extra=dict(python_objects=dict(job_event=self))
)
if settings.LOG_AGGREGATOR_ENABLED:
analytics_logger.info(
'Event data saved.',
extra=dict(python_objects=dict(job_event=self))
)
@classmethod
def create_from_data(cls, **kwargs):
@@ -484,7 +503,11 @@ class JobEvent(BasePlaybookEvent):
def _update_host_summary_from_stats(self, hostnames):
with ignore_inventory_computed_fields():
if not self.job or not self.job.inventory:
try:
if not self.job or not self.job.inventory:
logger.info('Event {} missing job or inventory, host summaries not updated'.format(self.pk))
return
except ObjectDoesNotExist:
logger.info('Event {} missing job or inventory, host summaries not updated'.format(self.pk))
return
job = self.job
@@ -520,11 +543,21 @@ class JobEvent(BasePlaybookEvent):
(summary['host_id'], summary['id'])
for summary in JobHostSummary.objects.filter(job_id=job.id).values('id', 'host_id')
)
updated_hosts = set()
for h in all_hosts:
h.last_job_id = job.id
# if the hostname *shows up* in the playbook_on_stats event
if h.name in hostnames:
h.last_job_id = job.id
updated_hosts.add(h)
if h.id in host_mapping:
h.last_job_host_summary_id = host_mapping[h.id]
Host.objects.bulk_update(all_hosts, ['last_job_id', 'last_job_host_summary_id'])
updated_hosts.add(h)
Host.objects.bulk_update(
list(updated_hosts),
['last_job_id', 'last_job_host_summary_id'],
batch_size=100
)
@property

View File

@@ -12,6 +12,7 @@ from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.utils.timezone import now, timedelta
import redis
from solo.models import SingletonModel
from awx import __version__ as awx_application_version
@@ -23,7 +24,7 @@ from awx.main.models.unified_jobs import UnifiedJob
from awx.main.utils import get_cpu_capacity, get_mem_capacity, get_system_task_capacity
from awx.main.models.mixins import RelatedJobsMixin
__all__ = ('Instance', 'InstanceGroup', 'TowerScheduleState', 'TowerAnalyticsState')
__all__ = ('Instance', 'InstanceGroup', 'TowerScheduleState')
class HasPolicyEditsMixin(HasEditsMixin):
@@ -152,6 +153,14 @@ class Instance(HasPolicyEditsMixin, BaseModel):
self.capacity = get_system_task_capacity(self.capacity_adjustment)
else:
self.capacity = 0
try:
# if redis is down for some reason, that means we can't persist
# playbook event data; we should consider this a zero capacity event
redis.Redis.from_url(settings.BROKER_URL).ping()
except redis.ConnectionError:
self.capacity = 0
self.cpu = cpu[0]
self.memory = mem[0]
self.cpu_capacity = cpu[1]
@@ -287,10 +296,6 @@ class TowerScheduleState(SingletonModel):
schedule_last_run = models.DateTimeField(auto_now_add=True)
class TowerAnalyticsState(SingletonModel):
last_run = models.DateTimeField(auto_now_add=True)
def schedule_policy_task():
from awx.main.tasks import apply_cluster_membership_policies
connection.on_commit(lambda: apply_cluster_membership_policies.apply_async())

File diff suppressed because it is too large Load Diff

View File

@@ -566,7 +566,6 @@ class WebhookMixin(models.Model):
def update_webhook_status(self, status):
if not self.webhook_credential:
logger.debug("No credential configured to post back webhook status, skipping.")
return
status_api = self.extra_vars_dict.get('tower_webhook_status_api')

View File

@@ -262,25 +262,25 @@ class JobNotificationMixin(object):
'running': 'started',
'failed': 'error'}
# Tree of fields that can be safely referenced in a notification message
JOB_FIELDS_WHITELIST = ['id', 'type', 'url', 'created', 'modified', 'name', 'description', 'job_type', 'playbook',
'forks', 'limit', 'verbosity', 'job_tags', 'force_handlers', 'skip_tags', 'start_at_task',
'timeout', 'use_fact_cache', 'launch_type', 'status', 'failed', 'started', 'finished',
'elapsed', 'job_explanation', 'execution_node', 'controller_node', 'allow_simultaneous',
'scm_revision', 'diff_mode', 'job_slice_number', 'job_slice_count', 'custom_virtualenv',
'approval_status', 'approval_node_name', 'workflow_url', 'scm_branch',
{'host_status_counts': ['skipped', 'ok', 'changed', 'failed', 'failures', 'dark'
'processed', 'rescued', 'ignored']},
{'summary_fields': [{'inventory': ['id', 'name', 'description', 'has_active_failures',
'total_hosts', 'hosts_with_active_failures', 'total_groups',
'has_inventory_sources',
'total_inventory_sources', 'inventory_sources_with_failures',
'organization_id', 'kind']},
{'project': ['id', 'name', 'description', 'status', 'scm_type']},
{'job_template': ['id', 'name', 'description']},
{'unified_job_template': ['id', 'name', 'description', 'unified_job_type']},
{'instance_group': ['name', 'id']},
{'created_by': ['id', 'username', 'first_name', 'last_name']},
{'labels': ['count', 'results']}]}]
JOB_FIELDS_ALLOWED_LIST = ['id', 'type', 'url', 'created', 'modified', 'name', 'description', 'job_type', 'playbook',
'forks', 'limit', 'verbosity', 'job_tags', 'force_handlers', 'skip_tags', 'start_at_task',
'timeout', 'use_fact_cache', 'launch_type', 'status', 'failed', 'started', 'finished',
'elapsed', 'job_explanation', 'execution_node', 'controller_node', 'allow_simultaneous',
'scm_revision', 'diff_mode', 'job_slice_number', 'job_slice_count', 'custom_virtualenv',
'approval_status', 'approval_node_name', 'workflow_url', 'scm_branch', 'artifacts',
{'host_status_counts': ['skipped', 'ok', 'changed', 'failed', 'failures', 'dark'
'processed', 'rescued', 'ignored']},
{'summary_fields': [{'inventory': ['id', 'name', 'description', 'has_active_failures',
'total_hosts', 'hosts_with_active_failures', 'total_groups',
'has_inventory_sources',
'total_inventory_sources', 'inventory_sources_with_failures',
'organization_id', 'kind']},
{'project': ['id', 'name', 'description', 'status', 'scm_type']},
{'job_template': ['id', 'name', 'description']},
{'unified_job_template': ['id', 'name', 'description', 'unified_job_type']},
{'instance_group': ['name', 'id']},
{'created_by': ['id', 'username', 'first_name', 'last_name']},
{'labels': ['count', 'results']}]}]
@classmethod
def context_stub(cls):
@@ -288,6 +288,7 @@ class JobNotificationMixin(object):
Context has the same structure as the context that will actually be used to render
a notification message."""
context = {'job': {'allow_simultaneous': False,
'artifacts': {},
'controller_node': 'foo_controller',
'created': datetime.datetime(2018, 11, 13, 6, 4, 0, 0, tzinfo=datetime.timezone.utc),
'custom_virtualenv': 'my_venv',
@@ -377,8 +378,8 @@ class JobNotificationMixin(object):
def context(self, serialized_job):
"""Returns a dictionary that can be used for rendering notification messages.
The context will contain whitelisted content retrieved from a serialized job object
(see JobNotificationMixin.JOB_FIELDS_WHITELIST), the job's friendly name,
The context will contain allowed content retrieved from a serialized job object
(see JobNotificationMixin.JOB_FIELDS_ALLOWED_LIST the job's friendly name,
and a url to the job run."""
job_context = {'host_status_counts': {}}
summary = None
@@ -395,22 +396,22 @@ class JobNotificationMixin(object):
'job_metadata': json.dumps(self.notification_data(), indent=4)
}
def build_context(node, fields, whitelisted_fields):
for safe_field in whitelisted_fields:
def build_context(node, fields, allowed_fields):
for safe_field in allowed_fields:
if type(safe_field) is dict:
field, whitelist_subnode = safe_field.copy().popitem()
field, allowed_subnode = safe_field.copy().popitem()
# ensure content present in job serialization
if field not in fields:
continue
subnode = fields[field]
node[field] = {}
build_context(node[field], subnode, whitelist_subnode)
build_context(node[field], subnode, allowed_subnode)
else:
# ensure content present in job serialization
if safe_field not in fields:
continue
node[safe_field] = fields[safe_field]
build_context(context['job'], serialized_job, self.JOB_FIELDS_WHITELIST)
build_context(context['job'], serialized_job, self.JOB_FIELDS_ALLOWED_LIST)
return context

View File

@@ -45,6 +45,12 @@ class Organization(CommonModel, NotificationFieldsModel, ResourceMixin, CustomVi
blank=True,
through='OrganizationInstanceGroupMembership'
)
galaxy_credentials = OrderedManyToManyField(
'Credential',
blank=True,
through='OrganizationGalaxyCredentialMembership',
related_name='%(class)s_galaxy_credentials'
)
max_hosts = models.PositiveIntegerField(
blank=True,
default=0,
@@ -108,6 +114,23 @@ class Organization(CommonModel, NotificationFieldsModel, ResourceMixin, CustomVi
return UnifiedJob.objects.non_polymorphic().filter(organization=self)
class OrganizationGalaxyCredentialMembership(models.Model):
organization = models.ForeignKey(
'Organization',
on_delete=models.CASCADE
)
credential = models.ForeignKey(
'Credential',
on_delete=models.CASCADE
)
position = models.PositiveIntegerField(
null=True,
default=None,
db_index=True,
)
class Team(CommonModelNameNotUnique, ResourceMixin):
'''
A team is a group of users that work on common projects.

View File

@@ -55,6 +55,7 @@ class ProjectOptions(models.Model):
('hg', _('Mercurial')),
('svn', _('Subversion')),
('insights', _('Red Hat Insights')),
('archive', _('Remote Archive')),
]
class Meta:
@@ -194,6 +195,11 @@ class ProjectOptions(models.Model):
if not check_if_exists or os.path.exists(smart_str(proj_path)):
return proj_path
def get_cache_path(self):
local_path = os.path.basename(self.local_path)
if local_path:
return os.path.join(settings.PROJECTS_ROOT, '.__awx_cache', local_path)
@property
def playbooks(self):
results = []
@@ -418,6 +424,10 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn
return True
return False
@property
def cache_id(self):
return str(self.last_job_id)
@property
def notification_templates(self):
base_notification_templates = NotificationTemplate.objects
@@ -455,11 +465,12 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn
)
def delete(self, *args, **kwargs):
path_to_delete = self.get_project_path(check_if_exists=False)
paths_to_delete = (self.get_project_path(check_if_exists=False), self.get_cache_path())
r = super(Project, self).delete(*args, **kwargs)
if self.scm_type and path_to_delete: # non-manual, concrete path
from awx.main.tasks import delete_project_files
delete_project_files.delay(path_to_delete)
for path_to_delete in paths_to_delete:
if self.scm_type and path_to_delete: # non-manual, concrete path
from awx.main.tasks import delete_project_files
delete_project_files.delay(path_to_delete)
return r
@@ -554,6 +565,19 @@ class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManage
def result_stdout_raw(self):
return self._result_stdout_raw(redact_sensitive=True)
@property
def branch_override(self):
"""Whether a branch other than the project default is used."""
if not self.project:
return True
return bool(self.scm_branch and self.scm_branch != self.project.scm_branch)
@property
def cache_id(self):
if self.branch_override or self.job_type == 'check' or (not self.project):
return str(self.id)
return self.project.cache_id
def result_stdout_raw_limited(self, start_line=0, end_line=None, redact_sensitive=True):
return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive=redact_sensitive)
@@ -597,10 +621,7 @@ class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManage
def save(self, *args, **kwargs):
added_update_fields = []
if not self.job_tags:
job_tags = ['update_{}'.format(self.scm_type)]
if self.job_type == 'run':
job_tags.append('install_roles')
job_tags.append('install_collections')
job_tags = ['update_{}'.format(self.scm_type), 'install_roles', 'install_collections']
self.job_tags = ','.join(job_tags)
added_update_fields.append('job_tags')
if self.scm_delete_on_update and 'delete' not in self.job_tags and self.job_type == 'check':

View File

@@ -205,10 +205,15 @@ class Schedule(PrimordialModel, LaunchTimeConfig):
'A valid TZID must be provided (e.g., America/New_York)'
)
if fast_forward and ('MINUTELY' in rrule or 'HOURLY' in rrule):
if (
fast_forward and
('MINUTELY' in rrule or 'HOURLY' in rrule) and
'COUNT=' not in rrule
):
try:
first_event = x[0]
if first_event < now():
# If the first event was over a week ago...
if (now() - first_event).days > 7:
# hourly/minutely rrules with far-past DTSTART values
# are *really* slow to precompute
# start *from* one week ago to speed things up drastically

View File

@@ -962,6 +962,10 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
def event_class(self):
raise NotImplementedError()
@property
def job_type_name(self):
return self.get_real_instance_class()._meta.verbose_name.replace(' ', '_')
@property
def result_stdout_text(self):
related = UnifiedJobDeprecatedStdout.objects.get(pk=self.pk)
@@ -1221,7 +1225,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
def websocket_emit_data(self):
''' Return extra data that should be included when submitting data to the browser over the websocket connection '''
websocket_data = dict(type=self.get_real_instance_class()._meta.verbose_name.replace(' ', '_'))
websocket_data = dict(type=self.job_type_name)
if self.spawned_by_workflow:
websocket_data.update(dict(workflow_job_id=self.workflow_job_id,
workflow_node_id=self.workflow_node_id))
@@ -1362,7 +1366,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
running = self.celery_task_id in ControlDispatcher(
'dispatcher', self.controller_node or self.execution_node
).running(timeout=timeout)
except socket.timeout:
except (socket.timeout, RuntimeError):
logger.error('could not reach dispatcher on {} within {}s'.format(
self.execution_node, timeout
))

View File

@@ -139,7 +139,7 @@ class WorkflowJobTemplateNode(WorkflowNodeBase):
'always_nodes', 'credentials', 'inventory', 'extra_data', 'survey_passwords',
'char_prompts', 'all_parents_must_converge', 'identifier'
]
REENCRYPTION_BLACKLIST_AT_COPY = ['extra_data', 'survey_passwords']
REENCRYPTION_BLOCKLIST_AT_COPY = ['extra_data', 'survey_passwords']
workflow_job_template = models.ForeignKey(
'WorkflowJobTemplate',

View File

@@ -94,8 +94,8 @@ class GrafanaBackend(AWXBaseEmailBackend, CustomNotificationBase):
headers=grafana_headers,
verify=(not self.grafana_no_verify_ssl))
if r.status_code >= 400:
logger.error(smart_text(_("Error sending notification grafana: {}").format(r.text)))
logger.error(smart_text(_("Error sending notification grafana: {}").format(r.status_code)))
if not self.fail_silently:
raise Exception(smart_text(_("Error sending notification grafana: {}").format(r.text)))
raise Exception(smart_text(_("Error sending notification grafana: {}").format(r.status_code)))
sent_messages += 1
return sent_messages

View File

@@ -46,8 +46,8 @@ class MattermostBackend(AWXBaseEmailBackend, CustomNotificationBase):
r = requests.post("{}".format(m.recipients()[0]),
json=payload, verify=(not self.mattermost_no_verify_ssl))
if r.status_code >= 400:
logger.error(smart_text(_("Error sending notification mattermost: {}").format(r.text)))
logger.error(smart_text(_("Error sending notification mattermost: {}").format(r.status_code)))
if not self.fail_silently:
raise Exception(smart_text(_("Error sending notification mattermost: {}").format(r.text)))
raise Exception(smart_text(_("Error sending notification mattermost: {}").format(r.status_code)))
sent_messages += 1
return sent_messages

View File

@@ -46,9 +46,9 @@ class RocketChatBackend(AWXBaseEmailBackend, CustomNotificationBase):
if r.status_code >= 400:
logger.error(smart_text(
_("Error sending notification rocket.chat: {}").format(r.text)))
_("Error sending notification rocket.chat: {}").format(r.status_code)))
if not self.fail_silently:
raise Exception(smart_text(
_("Error sending notification rocket.chat: {}").format(r.text)))
_("Error sending notification rocket.chat: {}").format(r.status_code)))
sent_messages += 1
return sent_messages

View File

@@ -72,8 +72,8 @@ class WebhookBackend(AWXBaseEmailBackend, CustomNotificationBase):
headers=self.headers,
verify=(not self.disable_ssl_verification))
if r.status_code >= 400:
logger.error(smart_text(_("Error sending notification webhook: {}").format(r.text)))
logger.error(smart_text(_("Error sending notification webhook: {}").format(r.status_code)))
if not self.fail_silently:
raise Exception(smart_text(_("Error sending notification webhook: {}").format(r.text)))
raise Exception(smart_text(_("Error sending notification webhook: {}").format(r.status_code)))
sent_messages += 1
return sent_messages

View File

@@ -1,8 +1,6 @@
import re
import urllib.parse as urlparse
from django.conf import settings
REPLACE_STR = '$encrypted$'
@@ -12,12 +10,6 @@ class UriCleaner(object):
@staticmethod
def remove_sensitive(cleartext):
# exclude_list contains the items that will _not_ be redacted
exclude_list = [settings.PUBLIC_GALAXY_SERVER['url']]
if settings.PRIMARY_GALAXY_URL:
exclude_list += [settings.PRIMARY_GALAXY_URL]
if settings.FALLBACK_GALAXY_SERVERS:
exclude_list += [server['url'] for server in settings.FALLBACK_GALAXY_SERVERS]
redactedtext = cleartext
text_index = 0
while True:
@@ -25,10 +17,6 @@ class UriCleaner(object):
if not match:
break
uri_str = match.group(1)
# Do not redact items from the exclude list
if any(uri_str.startswith(exclude_uri) for exclude_uri in exclude_list):
text_index = match.start() + len(uri_str)
continue
try:
# May raise a ValueError if invalid URI for one reason or another
o = urlparse.urlsplit(uri_str)

View File

@@ -12,10 +12,13 @@ import random
from django.db import transaction, connection
from django.utils.translation import ugettext_lazy as _, gettext_noop
from django.utils.timezone import now as tz_now
from django.conf import settings
# AWX
from awx.main.dispatch.reaper import reap_job
from awx.main.models import (
AdHocCommand,
Instance,
InstanceGroup,
InventorySource,
InventoryUpdate,
@@ -43,6 +46,12 @@ class TaskManager():
def __init__(self):
self.graph = dict()
# start task limit indicates how many pending jobs can be started on this
# .schedule() run. Starting jobs is expensive, and there is code in place to reap
# the task manager after 5 minutes. At scale, the task manager can easily take more than
# 5 minutes to start pending jobs. If this limit is reached, pending jobs
# will no longer be started and will be started on the next task manager cycle.
self.start_task_limit = settings.START_TASK_LIMIT
for rampart_group in InstanceGroup.objects.prefetch_related('instances'):
self.graph[rampart_group.name] = dict(graph=DependencyGraph(rampart_group.name),
capacity_total=rampart_group.capacity,
@@ -187,6 +196,10 @@ class TaskManager():
return result
def start_task(self, task, rampart_group, dependent_tasks=None, instance=None):
self.start_task_limit -= 1
if self.start_task_limit == 0:
# schedule another run immediately after this task manager
schedule_task_manager()
from awx.main.tasks import handle_work_error, handle_work_success
dependent_tasks = dependent_tasks or []
@@ -446,6 +459,8 @@ class TaskManager():
def process_pending_tasks(self, pending_tasks):
running_workflow_templates = set([wf.unified_job_template_id for wf in self.get_running_workflow_jobs()])
for task in pending_tasks:
if self.start_task_limit <= 0:
break
if self.is_job_blocked(task):
logger.debug("{} is blocked from running".format(task.log_format))
continue
@@ -515,6 +530,20 @@ class TaskManager():
task.job_explanation = timeout_message
task.save(update_fields=['status', 'job_explanation', 'timed_out'])
def reap_jobs_from_orphaned_instances(self):
# discover jobs that are in running state but aren't on an execution node
# that we know about; this is a fairly rare event, but it can occur if you,
# for example, SQL backup an awx install with running jobs and restore it
# elsewhere
for j in UnifiedJob.objects.filter(
status__in=['pending', 'waiting', 'running'],
).exclude(
execution_node__in=Instance.objects.values_list('hostname', flat=True)
):
if j.execution_node and not j.is_containerized:
logger.error(f'{j.execution_node} is not a registered instance; reaping {j.log_format}')
reap_job(j, 'failed')
def calculate_capacity_consumed(self, tasks):
self.graph = InstanceGroup.objects.capacity_values(tasks=tasks, graph=self.graph)
@@ -567,6 +596,7 @@ class TaskManager():
self.spawn_workflow_graph_jobs(running_workflow_tasks)
self.timeout_approval_node()
self.reap_jobs_from_orphaned_instances()
self.process_tasks(all_sorted_tasks)
return finished_wfjs

View File

@@ -23,6 +23,7 @@ import fcntl
from pathlib import Path
from uuid import uuid4
import urllib.parse as urlparse
import shlex
# Django
from django.conf import settings
@@ -50,8 +51,9 @@ import ansible_runner
# AWX
from awx import __version__ as awx_application_version
from awx.main.constants import CLOUD_PROVIDERS, PRIVILEGE_ESCALATION_METHODS, STANDARD_INVENTORY_UPDATE_ENV, GALAXY_SERVER_FIELDS
from awx.main.constants import PRIVILEGE_ESCALATION_METHODS, STANDARD_INVENTORY_UPDATE_ENV
from awx.main.access import access_registry
from awx.main.analytics import all_collectors, expensive_collectors
from awx.main.redact import UriCleaner
from awx.main.models import (
Schedule, TowerScheduleState, Instance, InstanceGroup,
@@ -72,7 +74,7 @@ from awx.main.utils import (update_scm_url,
ignore_inventory_group_removal, extract_ansible_vars, schedule_task_manager,
get_awx_version)
from awx.main.utils.ansible import read_ansible_config
from awx.main.utils.common import _get_ansible_version, get_custom_venv_choices
from awx.main.utils.common import get_custom_venv_choices
from awx.main.utils.external_logging import reconfigure_rsyslog
from awx.main.utils.safe_yaml import safe_dump, sanitize_jinja
from awx.main.utils.reload import stop_local_services
@@ -354,6 +356,26 @@ def send_notifications(notification_list, job_id=None):
@task(queue=get_local_queuename)
def gather_analytics():
def _gather_and_ship(subset, since, until):
tgzfiles = []
try:
tgzfiles = analytics.gather(subset=subset, since=since, until=until)
# empty analytics without raising an exception is not an error
if not tgzfiles:
return True
logger.info('Gathered analytics from {} to {}: {}'.format(since, until, tgzfiles))
for tgz in tgzfiles:
analytics.ship(tgz)
except Exception:
logger.exception('Error gathering and sending analytics for {} to {}.'.format(since,until))
return False
finally:
if tgzfiles:
for tgz in tgzfiles:
if os.path.exists(tgz):
os.remove(tgz)
return True
from awx.conf.models import Setting
from rest_framework.fields import DateTimeField
if not settings.INSIGHTS_TRACKING_STATE:
@@ -372,16 +394,29 @@ def gather_analytics():
if acquired is False:
logger.debug('Not gathering analytics, another task holds lock')
return
try:
tgz = analytics.gather()
if not tgz:
return
logger.info('gathered analytics: {}'.format(tgz))
analytics.ship(tgz)
settings.AUTOMATION_ANALYTICS_LAST_GATHER = gather_time
finally:
if os.path.exists(tgz):
os.remove(tgz)
subset = list(all_collectors().keys())
incremental_collectors = []
for collector in expensive_collectors():
if collector in subset:
subset.remove(collector)
incremental_collectors.append(collector)
# Cap gathering at 4 weeks of data if there has been no data gathering
since = last_time or (gather_time - timedelta(weeks=4))
if incremental_collectors:
start = since
until = None
while start < gather_time:
until = start + timedelta(hours = 4)
if (until > gather_time):
until = gather_time
if not _gather_and_ship(incremental_collectors, since=start, until=until):
break
start = until
settings.AUTOMATION_ANALYTICS_LAST_GATHER = until
if subset:
_gather_and_ship(subset, since=since, until=gather_time)
@task(queue=get_local_queuename)
@@ -840,25 +875,12 @@ class BaseTask(object):
logger.error('Failed to update %s after %d retries.',
self.model._meta.object_name, _attempt)
def get_ansible_version(self, instance):
if not hasattr(self, '_ansible_version'):
self._ansible_version = _get_ansible_version(
ansible_path=self.get_path_to_ansible(instance, executable='ansible'))
return self._ansible_version
def get_path_to(self, *args):
'''
Return absolute path relative to this file.
'''
return os.path.abspath(os.path.join(os.path.dirname(__file__), *args))
def get_path_to_ansible(self, instance, executable='ansible-playbook', **kwargs):
venv_path = getattr(instance, 'ansible_virtualenv_path', settings.ANSIBLE_VENV_PATH)
venv_exe = os.path.join(venv_path, 'bin', executable)
if os.path.exists(venv_exe):
return venv_exe
return shutil.which(executable)
def build_private_data(self, instance, private_data_dir):
'''
Return SSH private key data (only if stored in DB as ssh_key_data).
@@ -1013,8 +1035,6 @@ class BaseTask(object):
'resource_profiling_memory_poll_interval': mem_poll_interval,
'resource_profiling_pid_poll_interval': pid_poll_interval,
'resource_profiling_results_dir': results_dir})
else:
logger.debug('Resource profiling not enabled for task')
return resource_profiling_params
@@ -1486,6 +1506,8 @@ class BaseTask(object):
self.instance.job_explanation = "Job terminated due to timeout"
status = 'failed'
extra_update_fields['job_explanation'] = self.instance.job_explanation
# ensure failure notification sends even if playbook_on_stats event is not triggered
handle_success_and_failure_notifications.apply_async([self.instance.job.id])
except InvalidVirtualenvError as e:
extra_update_fields['job_explanation'] = e.message
@@ -1632,21 +1654,10 @@ class RunJob(BaseTask):
return passwords
def add_ansible_venv(self, venv_path, env, isolated=False):
super(RunJob, self).add_ansible_venv(venv_path, env, isolated=isolated)
# Add awx/lib to PYTHONPATH.
env['PYTHONPATH'] = env.get('PYTHONPATH', '') + self.get_path_to('..', 'lib') + ':'
def build_env(self, job, private_data_dir, isolated=False, private_data_files=None):
'''
Build environment dictionary for ansible-playbook.
'''
plugin_dir = self.get_path_to('..', 'plugins', 'callback')
plugin_dirs = [plugin_dir]
if hasattr(settings, 'AWX_ANSIBLE_CALLBACK_PLUGINS') and \
settings.AWX_ANSIBLE_CALLBACK_PLUGINS:
plugin_dirs.extend(settings.AWX_ANSIBLE_CALLBACK_PLUGINS)
plugin_path = ':'.join(plugin_dirs)
env = super(RunJob, self).build_env(job, private_data_dir,
isolated=isolated,
private_data_files=private_data_files)
@@ -1657,20 +1668,13 @@ class RunJob(BaseTask):
# callbacks to work.
env['JOB_ID'] = str(job.pk)
env['INVENTORY_ID'] = str(job.inventory.pk)
if job.use_fact_cache:
library_path = env.get('ANSIBLE_LIBRARY')
env['ANSIBLE_LIBRARY'] = ':'.join(
filter(None, [
library_path,
self.get_path_to('..', 'plugins', 'library')
])
)
if job.project:
env['PROJECT_REVISION'] = job.project.scm_revision
env['ANSIBLE_RETRY_FILES_ENABLED'] = "False"
env['MAX_EVENT_RES'] = str(settings.MAX_EVENT_RES_DATA)
if not isolated:
env['ANSIBLE_CALLBACK_PLUGINS'] = plugin_path
if hasattr(settings, 'AWX_ANSIBLE_CALLBACK_PLUGINS') and settings.AWX_ANSIBLE_CALLBACK_PLUGINS:
env['ANSIBLE_CALLBACK_PLUGINS'] = ':'.join(settings.AWX_ANSIBLE_CALLBACK_PLUGINS)
env['AWX_HOST'] = settings.TOWER_URL_BASE
# Create a directory for ControlPath sockets that is unique to each
@@ -1804,7 +1808,7 @@ class RunJob(BaseTask):
# By default, all extra vars disallow Jinja2 template usage for
# security reasons; top level key-values defined in JT.extra_vars, however,
# are whitelisted as "safe" (because they can only be set by users with
# are allowed as "safe" (because they can only be set by users with
# higher levels of privilege - those that have the ability create and
# edit Job Templates)
safe_dict = {}
@@ -1867,44 +1871,31 @@ class RunJob(BaseTask):
project_path = job.project.get_project_path(check_if_exists=False)
job_revision = job.project.scm_revision
sync_needs = []
all_sync_needs = ['update_{}'.format(job.project.scm_type), 'install_roles', 'install_collections']
source_update_tag = 'update_{}'.format(job.project.scm_type)
branch_override = bool(job.scm_branch and job.scm_branch != job.project.scm_branch)
if not job.project.scm_type:
pass # manual projects are not synced, user has responsibility for that
elif not os.path.exists(project_path):
logger.debug('Performing fresh clone of {} on this instance.'.format(job.project))
sync_needs = all_sync_needs
elif not job.project.scm_revision:
logger.debug('Revision not known for {}, will sync with remote'.format(job.project))
sync_needs = all_sync_needs
elif job.project.scm_type == 'git':
sync_needs.append(source_update_tag)
elif job.project.scm_type == 'git' and job.project.scm_revision and (not branch_override):
git_repo = git.Repo(project_path)
try:
desired_revision = job.project.scm_revision
if job.scm_branch and job.scm_branch != job.project.scm_branch:
desired_revision = job.scm_branch # could be commit or not, but will try as commit
current_revision = git_repo.head.commit.hexsha
if desired_revision == current_revision:
job_revision = desired_revision
if job_revision == git_repo.head.commit.hexsha:
logger.debug('Skipping project sync for {} because commit is locally available'.format(job.log_format))
else:
sync_needs = all_sync_needs
sync_needs.append(source_update_tag)
except (ValueError, BadGitName):
logger.debug('Needed commit for {} not in local source tree, will sync with remote'.format(job.log_format))
sync_needs = all_sync_needs
sync_needs.append(source_update_tag)
else:
sync_needs = all_sync_needs
# Galaxy requirements are not supported for manual projects
if not sync_needs and job.project.scm_type:
# see if we need a sync because of presence of roles
galaxy_req_path = os.path.join(project_path, 'roles', 'requirements.yml')
if os.path.exists(galaxy_req_path):
logger.debug('Running project sync for {} because of galaxy role requirements.'.format(job.log_format))
sync_needs.append('install_roles')
logger.debug('Project not available locally, {} will sync with remote'.format(job.log_format))
sync_needs.append(source_update_tag)
galaxy_collections_req_path = os.path.join(project_path, 'collections', 'requirements.yml')
if os.path.exists(galaxy_collections_req_path):
logger.debug('Running project sync for {} because of galaxy collections requirements.'.format(job.log_format))
sync_needs.append('install_collections')
has_cache = os.path.exists(os.path.join(job.project.get_cache_path(), job.project.cache_id))
# Galaxy requirements are not supported for manual projects
if job.project.scm_type and ((not has_cache) or branch_override):
sync_needs.extend(['install_roles', 'install_collections'])
if sync_needs:
pu_ig = job.instance_group
@@ -1922,7 +1913,7 @@ class RunJob(BaseTask):
execution_node=pu_en,
celery_task_id=job.celery_task_id
)
if job.scm_branch and job.scm_branch != job.project.scm_branch:
if branch_override:
sync_metafields['scm_branch'] = job.scm_branch
if 'update_' not in sync_metafields['job_tags']:
sync_metafields['scm_revision'] = job_revision
@@ -1954,10 +1945,7 @@ class RunJob(BaseTask):
if job_revision:
job = self.update_model(job.pk, scm_revision=job_revision)
# Project update does not copy the folder, so copy here
RunProjectUpdate.make_local_copy(
project_path, os.path.join(private_data_dir, 'project'),
job.project.scm_type, job_revision
)
RunProjectUpdate.make_local_copy(job.project, private_data_dir, scm_revision=job_revision)
if job.inventory.kind == 'smart':
# cache smart inventory memberships so that the host_filter query is not
@@ -1997,10 +1985,7 @@ class RunProjectUpdate(BaseTask):
@property
def proot_show_paths(self):
show_paths = [settings.PROJECTS_ROOT]
if self.job_private_data_dir:
show_paths.append(self.job_private_data_dir)
return show_paths
return [settings.PROJECTS_ROOT]
def __init__(self, *args, job_private_data_dir=None, **kwargs):
super(RunProjectUpdate, self).__init__(*args, **kwargs)
@@ -2034,12 +2019,6 @@ class RunProjectUpdate(BaseTask):
credential = project_update.credential
if credential.has_input('ssh_key_data'):
private_data['credentials'][credential] = credential.get_input('ssh_key_data', default='')
# Create dir where collections will live for the job run
if project_update.job_type != 'check' and getattr(self, 'job_private_data_dir'):
for folder_name in ('requirements_collections', 'requirements_roles'):
folder_path = os.path.join(self.job_private_data_dir, folder_name)
os.mkdir(folder_path, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
return private_data
def build_passwords(self, project_update, runtime_passwords):
@@ -2070,38 +2049,27 @@ class RunProjectUpdate(BaseTask):
# like https://github.com/ansible/ansible/issues/30064
env['TMP'] = settings.AWX_PROOT_BASE_PATH
env['PROJECT_UPDATE_ID'] = str(project_update.pk)
env['ANSIBLE_CALLBACK_PLUGINS'] = self.get_path_to('..', 'plugins', 'callback')
if settings.GALAXY_IGNORE_CERTS:
env['ANSIBLE_GALAXY_IGNORE'] = True
# Set up the public Galaxy server, if enabled
galaxy_configured = False
if settings.PUBLIC_GALAXY_ENABLED:
galaxy_servers = [settings.PUBLIC_GALAXY_SERVER] # static setting
else:
galaxy_configured = True
galaxy_servers = []
# Set up fallback Galaxy servers, if configured
if settings.FALLBACK_GALAXY_SERVERS:
galaxy_configured = True
galaxy_servers = settings.FALLBACK_GALAXY_SERVERS + galaxy_servers
# Set up the primary Galaxy server, if configured
if settings.PRIMARY_GALAXY_URL:
galaxy_configured = True
galaxy_servers = [{'id': 'primary_galaxy'}] + galaxy_servers
for key in GALAXY_SERVER_FIELDS:
value = getattr(settings, 'PRIMARY_GALAXY_{}'.format(key.upper()))
if value:
galaxy_servers[0][key] = value
if galaxy_configured:
for server in galaxy_servers:
for key in GALAXY_SERVER_FIELDS:
if not server.get(key):
continue
env_key = ('ANSIBLE_GALAXY_SERVER_{}_{}'.format(server.get('id', 'unnamed'), key)).upper()
env[env_key] = server[key]
if galaxy_servers:
# now set the precedence of galaxy servers
env['ANSIBLE_GALAXY_SERVER_LIST'] = ','.join([server.get('id', 'unnamed') for server in galaxy_servers])
# build out env vars for Galaxy credentials (in order)
galaxy_server_list = []
if project_update.project.organization:
for i, cred in enumerate(
project_update.project.organization.galaxy_credentials.all()
):
env[f'ANSIBLE_GALAXY_SERVER_SERVER{i}_URL'] = cred.get_input('url')
auth_url = cred.get_input('auth_url', default=None)
token = cred.get_input('token', default=None)
if token:
env[f'ANSIBLE_GALAXY_SERVER_SERVER{i}_TOKEN'] = token
if auth_url:
env[f'ANSIBLE_GALAXY_SERVER_SERVER{i}_AUTH_URL'] = auth_url
galaxy_server_list.append(f'server{i}')
if galaxy_server_list:
env['ANSIBLE_GALAXY_SERVER_LIST'] = ','.join(galaxy_server_list)
return env
def _build_scm_url_extra_vars(self, project_update):
@@ -2132,7 +2100,7 @@ class RunProjectUpdate(BaseTask):
scm_username = False
elif scm_url_parts.scheme.endswith('ssh'):
scm_password = False
elif scm_type == 'insights':
elif scm_type in ('insights', 'archive'):
extra_vars['scm_username'] = scm_username
extra_vars['scm_password'] = scm_password
scm_url = update_scm_url(scm_type, scm_url, scm_username,
@@ -2167,25 +2135,39 @@ class RunProjectUpdate(BaseTask):
extra_vars.update(extra_vars_new)
scm_branch = project_update.scm_branch
branch_override = bool(scm_branch and project_update.scm_branch != project_update.project.scm_branch)
if project_update.job_type == 'run' and (not branch_override):
scm_branch = project_update.project.scm_revision
if project_update.job_type == 'run' and (not project_update.branch_override):
if project_update.project.scm_revision:
scm_branch = project_update.project.scm_revision
elif not scm_branch:
raise RuntimeError('Could not determine a revision to run from project.')
elif not scm_branch:
scm_branch = {'hg': 'tip'}.get(project_update.scm_type, 'HEAD')
galaxy_creds_are_defined = (
project_update.project.organization and
project_update.project.organization.galaxy_credentials.exists()
)
if not galaxy_creds_are_defined and (
settings.AWX_ROLES_ENABLED or settings.AWX_COLLECTIONS_ENABLED
):
logger.debug(
'Galaxy role/collection syncing is enabled, but no '
f'credentials are configured for {project_update.project.organization}.'
)
extra_vars.update({
'project_path': project_update.get_project_path(check_if_exists=False),
'projects_root': settings.PROJECTS_ROOT.rstrip('/'),
'local_path': os.path.basename(project_update.project.local_path),
'project_path': project_update.get_project_path(check_if_exists=False), # deprecated
'insights_url': settings.INSIGHTS_URL_BASE,
'awx_license_type': get_license(show_key=False).get('license_type', 'UNLICENSED'),
'awx_version': get_awx_version(),
'scm_url': scm_url,
'scm_branch': scm_branch,
'scm_clean': project_update.scm_clean,
'roles_enabled': settings.AWX_ROLES_ENABLED,
'collections_enabled': settings.AWX_COLLECTIONS_ENABLED,
'roles_enabled': galaxy_creds_are_defined and settings.AWX_ROLES_ENABLED,
'collections_enabled': galaxy_creds_are_defined and settings.AWX_COLLECTIONS_ENABLED,
})
if project_update.job_type != 'check' and self.job_private_data_dir:
extra_vars['collections_destination'] = os.path.join(self.job_private_data_dir, 'requirements_collections')
extra_vars['roles_destination'] = os.path.join(self.job_private_data_dir, 'requirements_roles')
# apply custom refspec from user for PR refs and the like
if project_update.scm_refspec:
extra_vars['scm_refspec'] = project_update.scm_refspec
@@ -2195,7 +2177,7 @@ class RunProjectUpdate(BaseTask):
self._write_extra_vars_file(private_data_dir, extra_vars)
def build_cwd(self, project_update, private_data_dir):
return self.get_path_to('..', 'playbooks')
return os.path.join(private_data_dir, 'project')
def build_playbook_path_relative_to_cwd(self, project_update, private_data_dir):
return os.path.join('project_update.yml')
@@ -2280,7 +2262,11 @@ class RunProjectUpdate(BaseTask):
def acquire_lock(self, instance, blocking=True):
lock_path = instance.get_lock_file()
if lock_path is None:
raise RuntimeError(u'Invalid lock file path')
# If from migration or someone blanked local_path for any other reason, recoverable by save
instance.save()
lock_path = instance.get_lock_file()
if lock_path is None:
raise RuntimeError(u'Invalid lock file path')
try:
self.lock_fd = os.open(lock_path, os.O_RDWR | os.O_CREAT)
@@ -2317,8 +2303,7 @@ class RunProjectUpdate(BaseTask):
os.mkdir(settings.PROJECTS_ROOT)
self.acquire_lock(instance)
self.original_branch = None
if (instance.scm_type == 'git' and instance.job_type == 'run' and instance.project and
instance.scm_branch != instance.project.scm_branch):
if instance.scm_type == 'git' and instance.branch_override:
project_path = instance.project.get_project_path(check_if_exists=False)
if os.path.exists(project_path):
git_repo = git.Repo(project_path)
@@ -2327,17 +2312,54 @@ class RunProjectUpdate(BaseTask):
else:
self.original_branch = git_repo.active_branch
stage_path = os.path.join(instance.get_cache_path(), 'stage')
if os.path.exists(stage_path):
logger.warning('{0} unexpectedly existed before update'.format(stage_path))
shutil.rmtree(stage_path)
os.makedirs(stage_path) # presence of empty cache indicates lack of roles or collections
# the project update playbook is not in a git repo, but uses a vendoring directory
# to be consistent with the ansible-runner model,
# that is moved into the runner projecct folder here
awx_playbooks = self.get_path_to('..', 'playbooks')
copy_tree(awx_playbooks, os.path.join(private_data_dir, 'project'))
@staticmethod
def make_local_copy(project_path, destination_folder, scm_type, scm_revision):
if scm_type == 'git':
def clear_project_cache(cache_dir, keep_value):
if os.path.isdir(cache_dir):
for entry in os.listdir(cache_dir):
old_path = os.path.join(cache_dir, entry)
if entry not in (keep_value, 'stage'):
# invalidate, then delete
new_path = os.path.join(cache_dir,'.~~delete~~' + entry)
try:
os.rename(old_path, new_path)
shutil.rmtree(new_path)
except OSError:
logger.warning(f"Could not remove cache directory {old_path}")
@staticmethod
def make_local_copy(p, job_private_data_dir, scm_revision=None):
"""Copy project content (roles and collections) to a job private_data_dir
:param object p: Either a project or a project update
:param str job_private_data_dir: The root of the target ansible-runner folder
:param str scm_revision: For branch_override cases, the git revision to copy
"""
project_path = p.get_project_path(check_if_exists=False)
destination_folder = os.path.join(job_private_data_dir, 'project')
if not scm_revision:
scm_revision = p.scm_revision
if p.scm_type == 'git':
git_repo = git.Repo(project_path)
if not os.path.exists(destination_folder):
os.mkdir(destination_folder, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
tmp_branch_name = 'awx_internal/{}'.format(uuid4())
# always clone based on specific job revision
if not scm_revision:
if not p.scm_revision:
raise RuntimeError('Unexpectedly could not determine a revision to run from project.')
source_branch = git_repo.create_head(tmp_branch_name, scm_revision)
source_branch = git_repo.create_head(tmp_branch_name, p.scm_revision)
# git clone must take file:// syntax for source repo or else options like depth will be ignored
source_as_uri = Path(project_path).as_uri()
git.Repo.clone_from(
@@ -2356,19 +2378,48 @@ class RunProjectUpdate(BaseTask):
else:
copy_tree(project_path, destination_folder, preserve_symlinks=1)
# copy over the roles and collection cache to job folder
cache_path = os.path.join(p.get_cache_path(), p.cache_id)
subfolders = []
if settings.AWX_COLLECTIONS_ENABLED:
subfolders.append('requirements_collections')
if settings.AWX_ROLES_ENABLED:
subfolders.append('requirements_roles')
for subfolder in subfolders:
cache_subpath = os.path.join(cache_path, subfolder)
if os.path.exists(cache_subpath):
dest_subpath = os.path.join(job_private_data_dir, subfolder)
copy_tree(cache_subpath, dest_subpath, preserve_symlinks=1)
logger.debug('{0} {1} prepared {2} from cache'.format(type(p).__name__, p.pk, dest_subpath))
def post_run_hook(self, instance, status):
# To avoid hangs, very important to release lock even if errors happen here
try:
if self.playbook_new_revision:
instance.scm_revision = self.playbook_new_revision
instance.save(update_fields=['scm_revision'])
# Roles and collection folders copy to durable cache
base_path = instance.get_cache_path()
stage_path = os.path.join(base_path, 'stage')
if status == 'successful' and 'install_' in instance.job_tags:
# Clear other caches before saving this one, and if branch is overridden
# do not clear cache for main branch, but do clear it for other branches
self.clear_project_cache(base_path, keep_value=instance.project.cache_id)
cache_path = os.path.join(base_path, instance.cache_id)
if os.path.exists(stage_path):
if os.path.exists(cache_path):
logger.warning('Rewriting cache at {0}, performance may suffer'.format(cache_path))
shutil.rmtree(cache_path)
os.rename(stage_path, cache_path)
logger.debug('{0} wrote to cache at {1}'.format(instance.log_format, cache_path))
elif os.path.exists(stage_path):
shutil.rmtree(stage_path) # cannot trust content update produced
if self.job_private_data_dir:
# copy project folder before resetting to default branch
# because some git-tree-specific resources (like submodules) might matter
self.make_local_copy(
instance.get_project_path(check_if_exists=False), os.path.join(self.job_private_data_dir, 'project'),
instance.scm_type, instance.scm_revision
)
self.make_local_copy(instance, self.job_private_data_dir)
if self.original_branch:
# for git project syncs, non-default branches can be problems
# restore to branch the repo was on before this run
@@ -2412,7 +2463,7 @@ class RunInventoryUpdate(BaseTask):
@property
def proot_show_paths(self):
return [self.get_path_to('..', 'plugins', 'inventory'), settings.AWX_ANSIBLE_COLLECTIONS_PATHS]
return [settings.AWX_ANSIBLE_COLLECTIONS_PATHS]
def build_private_data(self, inventory_update, private_data_dir):
"""
@@ -2430,7 +2481,7 @@ class RunInventoryUpdate(BaseTask):
If no private data is needed, return None.
"""
if inventory_update.source in InventorySource.injectors:
injector = InventorySource.injectors[inventory_update.source](self.get_ansible_version(inventory_update))
injector = InventorySource.injectors[inventory_update.source]()
return injector.build_private_data(inventory_update, private_data_dir)
def build_env(self, inventory_update, private_data_dir, isolated, private_data_files=None):
@@ -2458,19 +2509,16 @@ class RunInventoryUpdate(BaseTask):
injector = None
if inventory_update.source in InventorySource.injectors:
injector = InventorySource.injectors[inventory_update.source](self.get_ansible_version(inventory_update))
injector = InventorySource.injectors[inventory_update.source]()
if injector is not None:
env = injector.build_env(inventory_update, env, private_data_dir, private_data_files)
# All CLOUD_PROVIDERS sources implement as either script or auto plugin
if injector.should_use_plugin():
env['ANSIBLE_INVENTORY_ENABLED'] = 'auto'
else:
env['ANSIBLE_INVENTORY_ENABLED'] = 'script'
# All CLOUD_PROVIDERS sources implement as inventory plugin from collection
env['ANSIBLE_INVENTORY_ENABLED'] = 'auto'
if inventory_update.source in ['scm', 'custom']:
for env_k in inventory_update.source_vars_dict:
if str(env_k) not in env and str(env_k) not in settings.INV_ENV_VARIABLE_BLACKLIST:
if str(env_k) not in env and str(env_k) not in settings.INV_ENV_VARIABLE_BLOCKED:
env[str(env_k)] = str(inventory_update.source_vars_dict[env_k])
elif inventory_update.source == 'file':
raise NotImplementedError('Cannot update file sources through the task system.')
@@ -2533,28 +2581,23 @@ class RunInventoryUpdate(BaseTask):
args.extend(['--venv', inventory_update.ansible_virtualenv_path])
src = inventory_update.source
# Add several options to the shell arguments based on the
# inventory-source-specific setting in the AWX configuration.
# These settings are "per-source"; it's entirely possible that
# they will be different between cloud providers if an AWX user
# actively uses more than one.
if getattr(settings, '%s_ENABLED_VAR' % src.upper(), False):
args.extend(['--enabled-var',
getattr(settings, '%s_ENABLED_VAR' % src.upper())])
if getattr(settings, '%s_ENABLED_VALUE' % src.upper(), False):
args.extend(['--enabled-value',
getattr(settings, '%s_ENABLED_VALUE' % src.upper())])
if getattr(settings, '%s_GROUP_FILTER' % src.upper(), False):
args.extend(['--group-filter',
getattr(settings, '%s_GROUP_FILTER' % src.upper())])
if getattr(settings, '%s_HOST_FILTER' % src.upper(), False):
args.extend(['--host-filter',
getattr(settings, '%s_HOST_FILTER' % src.upper())])
if inventory_update.enabled_var:
args.extend(['--enabled-var', shlex.quote(inventory_update.enabled_var)])
args.extend(['--enabled-value', shlex.quote(inventory_update.enabled_value)])
else:
if getattr(settings, '%s_ENABLED_VAR' % src.upper(), False):
args.extend(['--enabled-var',
getattr(settings, '%s_ENABLED_VAR' % src.upper())])
if getattr(settings, '%s_ENABLED_VALUE' % src.upper(), False):
args.extend(['--enabled-value',
getattr(settings, '%s_ENABLED_VALUE' % src.upper())])
if inventory_update.host_filter:
args.extend(['--host-filter', shlex.quote(inventory_update.host_filter)])
if getattr(settings, '%s_EXCLUDE_EMPTY_GROUPS' % src.upper()):
args.append('--exclude-empty-groups')
if getattr(settings, '%s_INSTANCE_ID_VAR' % src.upper(), False):
args.extend(['--instance-id-var',
getattr(settings, '%s_INSTANCE_ID_VAR' % src.upper()),])
"'{}'".format(getattr(settings, '%s_INSTANCE_ID_VAR' % src.upper())),])
# Add arguments for the source inventory script
args.append('--source')
args.append(self.pseudo_build_inventory(inventory_update, private_data_dir))
@@ -2579,19 +2622,15 @@ class RunInventoryUpdate(BaseTask):
injector = None
if inventory_update.source in InventorySource.injectors:
injector = InventorySource.injectors[src](self.get_ansible_version(inventory_update))
injector = InventorySource.injectors[src]()
if injector is not None:
if injector.should_use_plugin():
content = injector.inventory_contents(inventory_update, private_data_dir)
# must be a statically named file
inventory_path = os.path.join(private_data_dir, injector.filename)
with open(inventory_path, 'w') as f:
f.write(content)
os.chmod(inventory_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
else:
# Use the vendored script path
inventory_path = self.get_path_to('..', 'plugins', 'inventory', injector.script_name)
content = injector.inventory_contents(inventory_update, private_data_dir)
# must be a statically named file
inventory_path = os.path.join(private_data_dir, injector.filename)
with open(inventory_path, 'w') as f:
f.write(content)
os.chmod(inventory_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
elif src == 'scm':
inventory_path = os.path.join(private_data_dir, 'project', inventory_update.source_path)
elif src == 'custom':
@@ -2615,12 +2654,6 @@ class RunInventoryUpdate(BaseTask):
src = inventory_update.source
if src == 'scm' and inventory_update.source_project_update:
return os.path.join(private_data_dir, 'project')
if src in CLOUD_PROVIDERS:
injector = None
if src in InventorySource.injectors:
injector = InventorySource.injectors[src](self.get_ansible_version(inventory_update))
if (not injector) or (not injector.should_use_plugin()):
return self.get_path_to('..', 'plugins', 'inventory')
return private_data_dir
def build_playbook_path_relative_to_cwd(self, inventory_update, private_data_dir):
@@ -2634,13 +2667,21 @@ class RunInventoryUpdate(BaseTask):
source_project = None
if inventory_update.inventory_source:
source_project = inventory_update.inventory_source.source_project
if (inventory_update.source=='scm' and inventory_update.launch_type!='scm' and source_project):
# In project sync, pulling galaxy roles is not needed
if (inventory_update.source=='scm' and inventory_update.launch_type!='scm' and
source_project and source_project.scm_type): # never ever update manual projects
# Check if the content cache exists, so that we do not unnecessarily re-download roles
sync_needs = ['update_{}'.format(source_project.scm_type)]
has_cache = os.path.exists(os.path.join(source_project.get_cache_path(), source_project.cache_id))
# Galaxy requirements are not supported for manual projects
if not has_cache:
sync_needs.extend(['install_roles', 'install_collections'])
local_project_sync = source_project.create_project_update(
_eager_fields=dict(
launch_type="sync",
job_type='run',
job_tags='update_{},install_collections'.format(source_project.scm_type), # roles are never valid for inventory
job_tags=','.join(sync_needs),
status='running',
execution_node=inventory_update.execution_node,
instance_group = inventory_update.instance_group,
@@ -2664,11 +2705,7 @@ class RunInventoryUpdate(BaseTask):
raise
elif inventory_update.source == 'scm' and inventory_update.launch_type == 'scm' and source_project:
# This follows update, not sync, so make copy here
project_path = source_project.get_project_path(check_if_exists=False)
RunProjectUpdate.make_local_copy(
project_path, os.path.join(private_data_dir, 'project'),
source_project.scm_type, source_project.scm_revision
)
RunProjectUpdate.make_local_copy(source_project, private_data_dir)
@task(queue=get_local_queuename)
@@ -2728,7 +2765,6 @@ class RunAdHocCommand(BaseTask):
'''
Build environment dictionary for ansible.
'''
plugin_dir = self.get_path_to('..', 'plugins', 'callback')
env = super(RunAdHocCommand, self).build_env(ad_hoc_command, private_data_dir,
isolated=isolated,
private_data_files=private_data_files)
@@ -2738,7 +2774,6 @@ class RunAdHocCommand(BaseTask):
env['AD_HOC_COMMAND_ID'] = str(ad_hoc_command.pk)
env['INVENTORY_ID'] = str(ad_hoc_command.inventory.pk)
env['INVENTORY_HOSTVARS'] = str(True)
env['ANSIBLE_CALLBACK_PLUGINS'] = plugin_dir
env['ANSIBLE_LOAD_CALLBACK_PLUGINS'] = '1'
env['ANSIBLE_SFTP_BATCH_MODE'] = 'False'

View File

@@ -131,8 +131,8 @@ def mock_cache():
def pytest_runtest_teardown(item, nextitem):
# clear Django cache at the end of every test ran
# NOTE: this should not be memcache, see test_cache in test_env.py
# this is a local test cache, so we want every test to start with empty cache
# NOTE: this should not be memcache (as it is deprecated), nor should it be redis.
# This is a local test cache, so we want every test to start with an empty cache
cache.clear()

View File

@@ -1,43 +0,0 @@
conditional_groups:
azure: true
default_host_filters: []
exclude_host_filters:
- resource_group not in ['foo_resources', 'bar_resources']
- '"Creator" not in tags.keys()'
- tags["Creator"] != "jmarshall"
- '"peanutbutter" not in tags.keys()'
- tags["peanutbutter"] != "jelly"
- location not in ['southcentralus', 'westus']
fail_on_template_errors: false
hostvar_expressions:
ansible_host: private_ipv4_addresses[0]
computer_name: name
private_ip: private_ipv4_addresses[0] if private_ipv4_addresses else None
provisioning_state: provisioning_state | title
public_ip: public_ipv4_addresses[0] if public_ipv4_addresses else None
public_ip_id: public_ip_id if public_ip_id is defined else None
public_ip_name: public_ip_name if public_ip_name is defined else None
tags: tags if tags else None
type: resource_type
keyed_groups:
- key: location
prefix: ''
separator: ''
- key: tags.keys() | list if tags else []
prefix: ''
separator: ''
- key: security_group
prefix: ''
separator: ''
- key: resource_group
prefix: ''
separator: ''
- key: os_disk.operating_system_type
prefix: ''
separator: ''
- key: dict(tags.keys() | map("regex_replace", "^(.*)$", "\1_") | list | zip(tags.values() | list)) if tags else []
prefix: ''
separator: ''
plain_host_names: true
plugin: azure.azcollection.azure_rm
use_contrib_script_compatible_sanitization: true

View File

@@ -1,81 +0,0 @@
boto_profile: /tmp/my_boto_stuff
compose:
ansible_host: public_dns_name
ec2_account_id: owner_id
ec2_ami_launch_index: ami_launch_index | string
ec2_architecture: architecture
ec2_block_devices: dict(block_device_mappings | map(attribute='device_name') | list | zip(block_device_mappings | map(attribute='ebs.volume_id') | list))
ec2_client_token: client_token
ec2_dns_name: public_dns_name
ec2_ebs_optimized: ebs_optimized
ec2_eventsSet: events | default("")
ec2_group_name: placement.group_name
ec2_hypervisor: hypervisor
ec2_id: instance_id
ec2_image_id: image_id
ec2_instance_profile: iam_instance_profile | default("")
ec2_instance_type: instance_type
ec2_ip_address: public_ip_address
ec2_kernel: kernel_id | default("")
ec2_key_name: key_name
ec2_launch_time: launch_time | regex_replace(" ", "T") | regex_replace("(\+)(\d\d):(\d)(\d)$", ".\g<2>\g<3>Z")
ec2_monitored: monitoring.state in ['enabled', 'pending']
ec2_monitoring_state: monitoring.state
ec2_persistent: persistent | default(false)
ec2_placement: placement.availability_zone
ec2_platform: platform | default("")
ec2_private_dns_name: private_dns_name
ec2_private_ip_address: private_ip_address
ec2_public_dns_name: public_dns_name
ec2_ramdisk: ramdisk_id | default("")
ec2_reason: state_transition_reason
ec2_region: placement.region
ec2_requester_id: requester_id | default("")
ec2_root_device_name: root_device_name
ec2_root_device_type: root_device_type
ec2_security_group_ids: security_groups | map(attribute='group_id') | list | join(',')
ec2_security_group_names: security_groups | map(attribute='group_name') | list | join(',')
ec2_sourceDestCheck: source_dest_check | default(false) | lower | string
ec2_spot_instance_request_id: spot_instance_request_id | default("")
ec2_state: state.name
ec2_state_code: state.code
ec2_state_reason: state_reason.message if state_reason is defined else ""
ec2_subnet_id: subnet_id | default("")
ec2_tag_Name: tags.Name
ec2_virtualization_type: virtualization_type
ec2_vpc_id: vpc_id | default("")
filters:
instance-state-name:
- running
groups:
ec2: true
hostnames:
- dns-name
iam_role_arn: arn:aws:iam::123456789012:role/test-role
keyed_groups:
- key: placement.availability_zone
parent_group: zones
prefix: ''
separator: ''
- key: instance_type | regex_replace("[^A-Za-z0-9\_]", "_")
parent_group: types
prefix: type
- key: placement.region
parent_group: regions
prefix: ''
separator: ''
- key: dict(tags.keys() | map("regex_replace", "[^A-Za-z0-9\_]", "_") | list | zip(tags.values() | map("regex_replace", "[^A-Za-z0-9\_]", "_") | list))
parent_group: tags
prefix: tag
- key: tags.keys() | map("regex_replace", "[^A-Za-z0-9\_]", "_") | list
parent_group: tags
prefix: tag
- key: placement.availability_zone
parent_group: '{{ placement.region }}'
prefix: ''
separator: ''
plugin: amazon.aws.aws_ec2
regions:
- us-east-2
- ap-south-1
use_contrib_script_compatible_sanitization: true

View File

@@ -1,50 +0,0 @@
auth_kind: serviceaccount
compose:
ansible_ssh_host: networkInterfaces[0].accessConfigs[0].natIP | default(networkInterfaces[0].networkIP)
gce_description: description if description else None
gce_id: id
gce_image: image
gce_machine_type: machineType
gce_metadata: metadata.get("items", []) | items2dict(key_name="key", value_name="value")
gce_name: name
gce_network: networkInterfaces[0].network.name
gce_private_ip: networkInterfaces[0].networkIP
gce_public_ip: networkInterfaces[0].accessConfigs[0].natIP | default(None)
gce_status: status
gce_subnetwork: networkInterfaces[0].subnetwork.name
gce_tags: tags.get("items", [])
gce_zone: zone
hostnames:
- name
- public_ip
- private_ip
keyed_groups:
- key: gce_subnetwork
prefix: network
- key: gce_private_ip
prefix: ''
separator: ''
- key: gce_public_ip
prefix: ''
separator: ''
- key: machineType
prefix: ''
separator: ''
- key: zone
prefix: ''
separator: ''
- key: gce_tags
prefix: tag
- key: status | lower
prefix: status
- key: image
prefix: ''
separator: ''
plugin: google.cloud.gcp_compute
projects:
- fooo
retrieve_image_info: true
use_contrib_script_compatible_sanitization: true
zones:
- us-east4-a
- us-west1-b

View File

@@ -1,7 +1,3 @@
ansible:
expand_hostvars: true
fail_on_errors: true
use_hostnames: false
clouds:
devstack:
auth:
@@ -11,5 +7,5 @@ clouds:
project_domain_name: fooo
project_name: fooo
username: fooo
private: false
private: true
verify: false

View File

@@ -1,4 +0,0 @@
expand_hostvars: true
fail_on_errors: true
inventory_hostname: uuid
plugin: openstack.cloud.openstack

View File

@@ -1,20 +0,0 @@
base_source_var: value_of_var
compose:
ansible_host: (devices.values() | list)[0][0] if devices else None
groups:
dev: '"dev" in tags'
keyed_groups:
- key: cluster
prefix: cluster
separator: _
- key: status
prefix: status
separator: _
- key: tags
prefix: tag
separator: _
ovirt_hostname_preference:
- name
- fqdn
ovirt_insecure: false
plugin: ovirt.ovirt.ovirt

View File

@@ -1,29 +0,0 @@
base_source_var: value_of_var
compose:
ansible_ssh_host: foreman['ip6'] | default(foreman['ip'], true)
group_prefix: foo_group_prefix
keyed_groups:
- key: foreman['environment_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_') | regex_replace('none', '')
prefix: foo_group_prefixenvironment_
separator: ''
- key: foreman['location_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')
prefix: foo_group_prefixlocation_
separator: ''
- key: foreman['organization_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')
prefix: foo_group_prefixorganization_
separator: ''
- key: foreman['content_facet_attributes']['lifecycle_environment_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')
prefix: foo_group_prefixlifecycle_environment_
separator: ''
- key: foreman['content_facet_attributes']['content_view_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')
prefix: foo_group_prefixcontent_view_
separator: ''
- key: '"%s-%s-%s" | format(app, tier, color)'
separator: ''
- key: '"%s-%s" | format(app, color)'
separator: ''
legacy_hostvars: true
plugin: theforeman.foreman.foreman
want_facts: true
want_hostcollections: true
want_params: true

View File

@@ -3,5 +3,6 @@
"TOWER_HOST": "https://foo.invalid",
"TOWER_PASSWORD": "fooo",
"TOWER_USERNAME": "fooo",
"TOWER_OAUTH_TOKEN": "",
"TOWER_VERIFY_SSL": "False"
}

View File

@@ -1,3 +0,0 @@
include_metadata: true
inventory_id: 42
plugin: awx.awx.tower

View File

@@ -1,55 +0,0 @@
compose:
ansible_host: guest.ipAddress
ansible_ssh_host: guest.ipAddress
ansible_uuid: 99999999 | random | to_uuid
availablefield: availableField
configissue: configIssue
configstatus: configStatus
customvalue: customValue
effectiverole: effectiveRole
guestheartbeatstatus: guestHeartbeatStatus
layoutex: layoutEx
overallstatus: overallStatus
parentvapp: parentVApp
recenttask: recentTask
resourcepool: resourcePool
rootsnapshot: rootSnapshot
triggeredalarmstate: triggeredAlarmState
filters:
- config.zoo == "DC0_H0_VM0"
hostnames:
- config.foo
keyed_groups:
- key: config.asdf
prefix: ''
separator: ''
plugin: community.vmware.vmware_vm_inventory
properties:
- availableField
- configIssue
- configStatus
- customValue
- datastore
- effectiveRole
- guestHeartbeatStatus
- layout
- layoutEx
- name
- network
- overallStatus
- parentVApp
- permission
- recentTask
- resourcePool
- rootSnapshot
- snapshot
- triggeredAlarmState
- value
- capability
- config
- guest
- runtime
- storage
- summary
strict: false
with_nested_properties: true

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