Compare commits

..

1052 Commits

Author SHA1 Message Date
softwarefactory-project-zuul[bot]
c09cad3e6d Merge pull request #10522 from AlanCoding/close_file
Close file before returning

Resolves
/home/alancoding/repos/tower-qa/tests/lib/plugins/pytest_restqa/plugin.py:122: ResourceWarning: unclosed file <_io.TextIOWrapper name='/home/alancoding/repos/tower-qa/scripts/resource_loading/data_latest_loading.yml' mode='r' encoding='UTF-8'>
  qe_config.resources = PseudoNamespace(yaml_file.load_file(config.option.resource_file))

We have this same pattern earlier in the file.

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-28 17:52:37 +00:00
softwarefactory-project-zuul[bot]
ce20c8e77b Merge pull request #10536 from shanemcd/bump-19.2.2
Bump versions for AWX 19.2.2

Reviewed-by: Seth Foster <None>
Reviewed-by: Elijah DeLee <kdelee@redhat.com>
Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
2021-06-28 17:15:41 +00:00
Shane McDonald
73bb475503 Bump version + changelog 2021-06-28 12:25:44 -04:00
Shane McDonald
6df5c0331a Use Ansible Runner 2.0.0 release 2021-06-28 12:25:19 -04:00
softwarefactory-project-zuul[bot]
dc7bd73431 Merge pull request #10532 from shanemcd/downstream-fixes
Downstream fixes

Reviewed-by: Elijah DeLee <kdelee@redhat.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-06-28 15:31:31 +00:00
softwarefactory-project-zuul[bot]
017bb63023 Merge pull request #10528 from fosterseth/fix_collection_copy_from_error
Fix awx collections copy_item warning keyword error

SUMMARY


warn() does not take keyword 'msg'
add testing around the copy_from parameter for project creation


ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.2.1

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-06-28 15:16:51 +00:00
softwarefactory-project-zuul[bot]
5d4fc9613d Merge pull request #10524 from beeankha/ee_test_playbook
Add Integration Test Playbook for execution_environment Collections Module

SUMMARY

Adressing Issue #10454

Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-06-28 15:06:20 +00:00
Alan Rominger
f126a6343b Fix bug setting execution_node to null (not blank) (#5169) 2021-06-28 10:51:06 -04:00
Jeff Bradberry
40f5ff362c Bump ansible-runner to 2.0.0.0rc3 2021-06-28 10:51:06 -04:00
Shane McDonald
1ed170fff0 Dont overwrite result_traceback if it was already set. 2021-06-28 10:51:06 -04:00
Jeff Bradberry
d5deedc822 Make sure that validation of managed EEs makes sense
- missing fields in a patch request should be ignored
- compare the organization pks, if present
2021-06-28 10:51:05 -04:00
Alex Corey
9992bf03b0 resolves crashing details view 2021-06-28 10:51:05 -04:00
Alex Corey
04839a037a prevent delete of instance groups list item controlplan and default 2021-06-28 10:51:05 -04:00
Marliana Lara
f541fe9904 Add comment to explain why we resolve the promises sequentially 2021-06-28 10:51:05 -04:00
Marliana Lara
162ea776fd Add order selected list to instance group lookups 2021-06-28 10:51:05 -04:00
Alan Rominger
f1273d5810 Show tracebacks from dependency failures (#5154) 2021-06-28 10:51:05 -04:00
Alan Rominger
390e1f9a0a Fix obvious logical bug with project folder pre-creation (#5155) 2021-06-28 10:51:04 -04:00
Keith J. Grant
8dc788dbcb clean up responsive behavior of advanced search 2021-06-28 10:51:04 -04:00
Shane McDonald
397908543d Disable activity stream for updates in status handler 2021-06-28 10:51:04 -04:00
Jeff Bradberry
3be29d54ad Bump ansible-runner to 2.0.0.0rc2 and receptorctl to 1.0.0.0rc1 2021-06-28 10:51:04 -04:00
Shane McDonald
03fb12d4c2 Force system jobs to always run on control plane 2021-06-28 10:51:04 -04:00
Tiago
69388edaf9 fix lint 2021-06-28 10:51:04 -04:00
Marliana Lara
1e750cfed9 Add datalist test selectors 2021-06-28 10:51:04 -04:00
Shane McDonald
1ba51c0357 Fix unit tests
Signed-off-by: Shane McDonald <me@shanemcd.com>
2021-06-28 10:51:03 -04:00
Shane McDonald
2fa27000ab Prevent inventory updates started via projects from running on controlplane 2021-06-28 10:51:03 -04:00
nixocio
057bd6e625 Remove plus button job output
Remove plus button job output since this feature was not implemented yet.
And it will be evaluated for a future release.

See: https://github.com/ansible/awx/issues/6613
2021-06-28 10:51:03 -04:00
Alan Rominger
d0b7d970c4 Create partition for 2 job types that bypass TM (#5138)
* Create partition for 2 job types that bypass TM

* Mock create_partition in unit tests
2021-06-28 10:51:03 -04:00
Christian M. Adams
5ffffebe34 Attempt to check/wait for migrations 30x (~12 min)
- the task container needs to wait longer for migrations to complete for fresh installs before starting services
  - otherwise, services start prematurely and clutter the logs with errors because migrations are mid-flight
2021-06-28 10:51:03 -04:00
Marliana Lara
b98544264b Rename draggable prop and fix typos 2021-06-28 10:51:03 -04:00
Shane McDonald
0d7ef709bf Prevent jobs from trying to run on controlplane in k8s 2021-06-28 10:51:02 -04:00
Jake McDermott
1211faf8df Only derive row count from max counter when job is running. 2021-06-28 10:51:02 -04:00
Jake McDermott
dc327ceaeb Autofix problematic dependencies 2021-06-28 10:51:02 -04:00
Shane McDonald
0f25720634 Update minikube docs 2021-06-28 10:51:02 -04:00
Alex Corey
28a62ea774 properly validates credential password fields 2021-06-28 10:51:02 -04:00
Kia Lam
d3c5397721 Add link to project update job details on job details page. 2021-06-28 10:51:02 -04:00
nixocio
f06490a5f8 Fix disparity of dev server and prod build
Fix disparity of dev server and prod build

See: https://github.com/ansible/awx/issues/9997
2021-06-28 10:51:02 -04:00
Marliana Lara
9fddf7c5cf Add draggable selected list to galaxy credential lookup 2021-06-28 10:51:01 -04:00
nixocio
673f722b71 Update inventory list filters
Update inventory list filters

See: https://github.com/ansible/awx/issues/7675
2021-06-28 10:51:01 -04:00
Jake McDermott
4de477686e Update help text for hashivault credential plugin 2021-06-28 10:51:01 -04:00
Jake McDermott
4cc734ce6e Enable instance group creation for non-k8s deployments only 2021-06-28 10:51:01 -04:00
Jake McDermott
f08bf4766d Add read-only settings for IS_K8S 2021-06-28 10:51:01 -04:00
nixocio
77b0b9a4e3 Disable edit fields for managed EE, except pull
Disable edit fields for managed EE, except pull options.

See: https://github.com/ansible/tower/issues/5016
2021-06-28 10:51:01 -04:00
Keith J. Grant
487d78cc72 Don't reload template when navigating to edit form 2021-06-28 10:51:00 -04:00
mabashian
f0a6567cd8 Hide host_filter search key when hiding smart inventories 2021-06-28 10:51:00 -04:00
mabashian
8246d4a298 Remove smart inventories from host form inv lookup 2021-06-28 10:51:00 -04:00
Bill Nottingham
cd83030668 Rename sosreport plugin 2021-06-28 10:51:00 -04:00
mabashian
88d492371b Link users to workflow approval details from workflow node 2021-06-28 10:51:00 -04:00
Keith J. Grant
9316ace3f6 delete commented line 2021-06-28 10:51:00 -04:00
Keith J. Grant
55b5060944 remove duplicate JT credential fetch 2021-06-28 10:51:00 -04:00
Keith J. Grant
0be68fe84f reduce duplicate network request in JT form 2021-06-28 10:50:59 -04:00
Seth Foster
5da02690c1 Fix copy_from warning message
- warn() does not take keyword 'msg'
- add testing around the copy_from parameter for project creation
2021-06-26 01:28:02 -04:00
beeankha
c417c5e219 Add test playbook for EE collections module 2021-06-25 18:01:26 -04:00
Alan Rominger
02cccbe608 Close file before returning 2021-06-25 14:47:44 -04:00
softwarefactory-project-zuul[bot]
2afa406b7f Merge pull request #10490 from shanemcd/downstream-fixes
Downstream fixes

Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-06-22 17:24:12 +00:00
Alan Rominger
1831b2591a Null iso IG jobs before deleting (#5122)
This is a workaround for polymorphic SET_NULL bug
2021-06-22 10:57:16 -04:00
Alex Corey
3cdd35f2cf default credentials are selected on POL load 2021-06-22 10:49:41 -04:00
Alan Rominger
1422bb2043 Fix tower upgrade (#5114)
* Hack to avoid creating both tower and controller CredentialType

* Remove line used for testing
2021-06-22 10:49:41 -04:00
mabashian
695787be4e Fix broken test 2021-06-22 10:49:40 -04:00
mabashian
e1b8f30d8f Extract strings 2021-06-22 10:49:40 -04:00
mabashian
293924168f Make expanded view ee detail warning match unexpanded 2021-06-22 10:49:40 -04:00
mabashian
7c72be7025 Adds a link to the ee migration docs in a popover when ee is missing 2021-06-22 10:49:40 -04:00
Alan Rominger
4a85983eb7 Symlink modules for 2.9 compat (#5103)
* Symlink modules for 2.9 compat

* Avoid symlinks in completeness tests
2021-06-22 10:49:40 -04:00
Seth Foster
82c510e51e remove tower_token alias (#5110) 2021-06-22 10:49:39 -04:00
Alan Rominger
0508a9267c Minor patch to right wording for 400 error (#5109) 2021-06-22 10:49:39 -04:00
Elijah DeLee
11e416995a accept old env vars
this broke our build of the cli docs
2021-06-22 10:49:39 -04:00
Seth Foster
bb3fc3caa8 controller_token, alias tower_token 2021-06-22 10:49:39 -04:00
nixocio
ab40006535 Link to instance group from org details when present
Link to instance group from org details when present

See: https://github.com/ansible/awx/issues/4953
2021-06-22 10:49:39 -04:00
Alan Rominger
53fe08af61 Update collection inventory_source options 2021-06-22 10:49:38 -04:00
Alan Rominger
a8083296e6 Make safe variable duplications for rename (#5093)
* Make safe variable duplications to controller

* Back out some changes to be smarter

* Update test to new vars
2021-06-22 10:49:38 -04:00
nixocio
95e796a88a Remove URL params when closing wizard
Remove URL params when closing wizard

See: https://github.com/ansible/awx/issues/10240
2021-06-22 10:49:38 -04:00
Bill Nottingham
0c0028541d Update inventory/cred names in UI 2021-06-22 10:49:38 -04:00
Amol Gautam
32cc7e976a Refactored awx/settings/defaults.py 2021-06-22 10:49:38 -04:00
Alex Corey
3495f75fa0 adds verbosity to payload 2021-06-22 10:49:37 -04:00
Jeff Bradberry
493e6cc527 Make the isolated removal migration non-atomic
We are apparently running into problems with pending triggers under
some circumstances.
2021-06-22 10:49:37 -04:00
Amol Gautam
7510b243bb Fixed UI linting 2021-06-22 10:49:37 -04:00
Christian M. Adams
e06ebb1f11 Fix credential test for default cred test 2021-06-22 10:49:37 -04:00
Alan Rominger
cc616206b3 Pass current apps to CredentialType setup method 2021-06-22 10:49:37 -04:00
Christian M. Adams
06b04007a0 Rename managed_by_tower to managed 2021-06-22 10:49:36 -04:00
Alan Rominger
6db4732bf3 Rename the TOWER_ settings 2021-06-22 10:49:36 -04:00
Alan Rominger
ead7907173 Update another test for tower to controller rename 2021-06-22 10:49:36 -04:00
Amol Gautam
68f0ae612e Fixed Migration 2021-06-22 10:49:36 -04:00
Alan Rominger
8c1bc97c2f Fix up unit tests after tower to controller rename 2021-06-22 10:49:36 -04:00
Amol Gautam
b64c2d6861 Removed references to tower in InventorySource and Credentials
--- Removed reference to tower in  InventorySource and InventoryUpdate model
--- Added a migration for above change
--- Added new CONTROLLER* variables in awx/main/models/credentials/__init__.py
--- Migrated awxkit to new CONTROLLER* variables
--- Updated the tests to use new CONTROLLER* variables
--- Fix some issues with upgrade path, rename more cases
2021-06-22 10:49:35 -04:00
Yanis Guenane
645f7f6dac Expand sos report plugin compatibility
sos 4 now uses sos.report.plugin when sos 3 was using sos.plugins. This
change allows compatibility with both.
2021-06-22 10:49:35 -04:00
Chris Meyers
0a5e9da287 replace default oci runtime runc with crun
* Our tests could consistently get awx jobs into a deadlocked state
whenever the parallelism was high. Even podman ps would hang when the
system was in this state. We don't know exactly where in runc the bug is
but the deadlocks stopped happening when we changed the OCI runtime
environment to crun.
2021-06-22 10:49:35 -04:00
nixocio
a60abe38a8 Allow space on host filter for smart inventory
Allow space on host filter for smart inventory

Fix: https://github.com/ansible/tower/issues/4874
2021-06-22 10:49:35 -04:00
mabashian
51abbb9464 Fixes bug where UI wasn't handling an array of survey answer choices 2021-06-22 10:49:34 -04:00
Alex Corey
560b4ebf71 offers an empty values as a choice on single select survey questions that are not required.
Also changes the single select component to a <Select variant='single'> component
following patternfly design guidelines
2021-06-22 10:49:34 -04:00
Alan Rominger
5a7a1b8f20 Remove inventory_as_dict which would mess with downstream templating (#5085) 2021-06-22 10:49:34 -04:00
nixocio
f1ca272394 Remove test button from logging settings screen
Remove test button from logging settings screen

Closes: https://github.com/ansible/awx/issues/9409
2021-06-22 10:49:34 -04:00
mabashian
8697387d13 Fix failing test 2021-06-22 10:49:34 -04:00
Bill Nottingham
1e68519c99 Remove insights_credential from inventory 2021-06-22 10:49:33 -04:00
mabashian
0947d30682 Fixes visual bug where revert button showed up above input 2021-06-22 10:49:33 -04:00
mabashian
c993c8b3b9 Fixes bug where email notification ssl and tls were a dropdown instead of checkboxes 2021-06-22 10:49:33 -04:00
Alex Corey
2ce09d0dcc adds job id to job name in job list delete modal 2021-06-22 10:49:33 -04:00
Keith J. Grant
25bca532c2 delete commented code 2021-06-22 10:49:33 -04:00
Keith J. Grant
fb897891c9 delete PaginatedDataList, move toolbar buttons to PaginatedTable dir 2021-06-22 10:49:32 -04:00
Keith J. Grant
421d8f215c Convert lists to tables
- ProjectJobTemplatesList
- UserTokenList
2021-06-22 10:49:32 -04:00
Keith J. Grant
3db92ca668 Convert more lists to tables
- Smart Inventory Hosts List
- Organization EE List
- Organization Teams list
2021-06-22 10:49:32 -04:00
Keith J. Grant
c6fa85036e convert ee template list, host group list to tables 2021-06-22 10:49:32 -04:00
Keith J. Grant
0b4a296181 convert ApplicationTokenList, HostFilterLookup to tables 2021-06-22 10:49:32 -04:00
nixocio
1665acd58a Allow edit fields to custom credential types
The logic to disable certain fields is just valid for `encrypted`
fields. Since the multiline field - no secret, does not have a button to `replace`
the content to null  - it was always set to disabled.

Fix: https://github.com/ansible/awx/issues/10079
2021-06-22 10:49:31 -04:00
Seth Foster
75a27c38c2 Add a periodic task to reap unreleased receptor work units
- Add work_unit_id field to UnifiedJob
2021-06-22 10:49:31 -04:00
nixocio
7b9bcd0481 Remove EE from WorkflowJobTemplate screens
Remove EE from WorkflowJobTemplate screens

Related ansible/awx#10443
Related ansible/awx#10399
2021-06-22 10:49:31 -04:00
Alan Rominger
15444bef70 Show inventory source POST in OPTIONS for inventory admins (#5076) 2021-06-22 10:49:31 -04:00
mabashian
f4bc69d5f7 Fixes bug where cred password fiield was displaying ASK 2021-06-22 10:49:31 -04:00
mabashian
29d57ea403 Fixes bug where toolbar was hidden on user token list 2021-06-22 10:49:30 -04:00
Elijah DeLee
ea5bd45d03 log perf of requests at debug level 2021-06-22 10:31:15 -04:00
softwarefactory-project-zuul[bot]
165a529ae0 Merge pull request #10480 from mscherer/fix_freenode
Remove more freenode from docs

SUMMARY
Removing more mention of Freenode, since we moved to Libera.
ISSUE TYPE

Docs Pull Request

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-21 17:24:55 +00:00
Michael Scherer
1c31a56395 Remove more freenode from docs 2021-06-19 11:32:02 +02:00
softwarefactory-project-zuul[bot]
0c120782d4 Merge pull request #10463 from mayasd/patch-1
Update Dockerfile.j2

SUMMARY
Jobs unable to start because podman trying to use systemd cgroup manager. See error below :
WARN[0000] Failed to add conmon to systemd sandbox cgroup: dial unix /run/systemd/private: connect: no such file or directory
Error: OCI runtime error: systemd cgroup flag passed, but systemd support for managing cgroups is not available

related #10099


ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

AWX VERSION
awx: 19.0.0

ADDITIONAL INFORMATION

According to this PR containers/podman#7009, podman switch references from libpod.conf to containers.conf.
According to containers.conf man (https://github.com/containers/common/blob/main/docs/containers.conf.5.md), configuration file is a TOML file but engine section declaration is missing.

thanks to @Siorde too 👍

Reviewed-by: Chris Meyers <None>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-17 21:19:30 +00:00
Shane McDonald
6ba053d4ee Update release date in changelog for 19.2.1 2021-06-17 14:39:39 -04:00
softwarefactory-project-zuul[bot]
3ecd26b5d8 Merge pull request #10468 from wenottingham/platforms
List platforms that developers regularly run the dev env on

SUMMARY
Other platforms are generally untested.
ISSUE TYPE

Docs Pull Request

Reviewed-by: Julen Landa Alustiza <None>
Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-06-17 17:24:42 +00:00
Bill Nottingham
bdf753ce23 Update tools/docker-compose/README.md
Co-authored-by: Shane McDonald <me@shanemcd.com>
2021-06-17 11:56:29 -04:00
Bill Nottingham
0f54516b38 List platforms that developers regularly run the dev env 2021-06-17 11:50:36 -04:00
softwarefactory-project-zuul[bot]
a56e32b59b Merge pull request #10464 from AlanCoding/ee_docs
Update and expand docs/ folder for EEs

This has some new content about EE precedence, which I don't think we've documented anywhere else, thinking of @tvo318 here, content was developed by @jbradberry
(I think the numbers 2 and 3 in the global job default EE may still be subject to revision, just a warning)
@shanemcd #10324 is incorporated into this
This mentions @rebeccahhh's venv migration stuff, but I'm trying to write the absolute minimum possible while still mentioning migration.

Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Jeff Bradberry <None>
2021-06-17 13:07:07 +00:00
softwarefactory-project-zuul[bot]
026d5e6bdb Merge pull request #10465 from shanemcd/downstream-fixes
Downstream fixes

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-06-16 21:44:52 +00:00
Shane McDonald
03e73156ea Allow inventory updates to run in container groups 2021-06-16 17:11:43 -04:00
Alan Rominger
0b6208047c Correct the function of the -q option for migration helper commands 2021-06-16 16:26:38 -04:00
Alan Rominger
f14129de9b Further copy editing of EE docs 2021-06-16 16:18:21 -04:00
Jeff Bradberry
6c1ba03235 Remove EE from the workflow job template collection module 2021-06-16 15:41:09 -04:00
Jeff Bradberry
85bb4e976f Execution environments are meaningless for workflows
so, remove them from the API endpoints for workflows.  Also, tear out
the WFJT.execution_environment step in the resolver.  If we want that
to be a thing, it ought to be a .default_environment instead.
2021-06-16 15:41:09 -04:00
Shane McDonald
d1d3711fee Add yamllint to dev dependencies 2021-06-16 15:41:09 -04:00
Shane McDonald
d671366cad Add flake8 back to requirements_dev.txt 2021-06-16 15:41:08 -04:00
Shane McDonald
f9043864ce Create make target for api linter tasks 2021-06-16 15:41:08 -04:00
nixocio
a1ded8db3f Linkify credentials on JobTemplate and Organization Details
Linkify credentials on JobTemplate and Organization Details.

See: https://github.com/ansible/awx/issues/385
2021-06-16 15:41:08 -04:00
Alex Corey
cf6b6d831f adds visualizer button to output toolbar 2021-06-16 15:41:08 -04:00
Alex Corey
736cd4df36 refetches smart inventory after edit save 2021-06-16 15:41:08 -04:00
nixocio
8d99f79de4 Hide Edit button for non system admin
Hide Edit button for non system admin

See: https://github.com/ansible/tower/issues/5032
2021-06-16 15:41:08 -04:00
Alex Corey
1c70773cc2 shows user type fields only for sys admins 2021-06-16 15:41:07 -04:00
mabashian
c76a7d638f Removes tooltip from user in page toolbar 2021-06-16 15:41:07 -04:00
mabashian
7a455d08d7 Change Options to Enabled Options in various details views 2021-06-16 15:41:07 -04:00
nixocio
2c5bcf268d Update UI to reflect new API EE changes
* Show resolved EE for job template details.
* Do not show EE if a certain job status still running, since EE on the
API is not set yet. It was causing the bug to temporarily show `missing
resource`.
* Fix discrepancy about job types for list and details.

See: https://github.com/ansible/awx/issues/10327
Also: https://github.com/ansible/awx/issues/10399
2021-06-16 15:41:07 -04:00
mabashian
32cee852f0 Swap underscore for hyphen 2021-06-16 15:41:07 -04:00
mabashian
8c1cd9ee71 Fixes bug where source list page would crash if first sync was running 2021-06-16 15:41:07 -04:00
Alex Corey
da951714d1 resolves iinfinite loop 2021-06-16 15:41:07 -04:00
Alan Rominger
2309feb6bd Make ExecutionEnvironment awxkit class able to handle null values in payload 2021-06-16 15:41:06 -04:00
nixocio
4d2c64ebb4 Add RBAC rules to the side-nav
Add RBAC rules to the side-nav

System Admin
System Auditor
Org Admin
Notification Admin
Execution Environment Admin
Normal User

Those are the user profiles taken in consideration when displaying the
side-nav.

See: https://github.com/ansible/awx/issues/4426
2021-06-16 15:37:25 -04:00
nixocio
04f6fe6cd2 Disable inventory field when editing host
Disable inventory field when editing host

See: https://github.com/ansible/awx/issues/10229
2021-06-16 15:37:25 -04:00
Bill Nottingham
372baa12a5 Update runner version. 2021-06-16 15:37:25 -04:00
mabashian
21e6e5701e Addresses bug where advanced search by groups wasn't working on host list 2021-06-16 15:37:25 -04:00
Alex Corey
276a18b339 fixes next button and internationalizes nav buttons on wizard 2021-06-16 15:37:25 -04:00
mabashian
666acb9756 Extract strings 2021-06-16 15:37:25 -04:00
mabashian
0eff3e6bac Pull brand name from default.strings.json 2021-06-16 15:37:24 -04:00
mabashian
9af16c18c9 Dont reconnect job output socket if it closes cleanly 2021-06-16 15:37:24 -04:00
Elijah DeLee
f0bcfc6024 add EE information to assert_status
This should help debugging to know what the EE was when an unexpected
status was found.
2021-06-16 15:37:24 -04:00
Elijah DeLee
d946103961 log perf of requests at debug level 2021-06-16 15:37:24 -04:00
Alan Rominger
52d6f36b7c Incorporate review comments about EE docs 2021-06-16 14:24:48 -04:00
softwarefactory-project-zuul[bot]
b10eb6f4c2 Merge pull request #10382 from AlanCoding/downstream_waterslide
Handle inventory types where Automation Hub collection names differ

Some collections will be moving, which is #10323
Yet, other collections will change name, which this is intended to address.

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Sarabraj Singh <singh.sarabraj@gmail.com>
Reviewed-by: Elijah DeLee <kdelee@redhat.com>
2021-06-16 18:15:08 +00:00
Alan Rominger
21aa1fc11f Handle inventory types where Automation Hub collection names differ
Move imports added by Bill to be in-line, because utils should not import models at top

Remove more get_licenser inline imports
2021-06-16 13:39:52 -04:00
softwarefactory-project-zuul[bot]
d4a3143b0e Merge pull request #10456 from jbradberry/danger-danger-will-robinson
Remove isolated instances and groups

SUMMARY
before we remove the fields that allow us to correctly identify them.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Chris Meyers <None>
2021-06-16 15:30:48 +00:00
Alan Rominger
4478052b71 Update and expand docs/ folder for EEs 2021-06-16 11:23:59 -04:00
softwarefactory-project-zuul[bot]
b92c5076a2 Merge pull request #10446 from fosterseth/fix_a10431_validate_ee_image_field
Add validation for EE image field name

related #10431
SUMMARY

Adds validation for the EE image name

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.2.1

Reviewed-by: Seth Foster <None>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Jeff Bradberry <None>
2021-06-16 14:34:45 +00:00
Tim
a3383716ab Update Dockerfile.j2
Jobs unable to start because podman trying to use systemd cgroup manager. See error below :

```
WARN[0000] Failed to add conmon to systemd sandbox cgroup: dial unix /run/systemd/private: connect: no such file or directory
Error: OCI runtime error: systemd cgroup flag passed, but systemd support for managing cgroups is not available
```

* According to this PR https://github.com/containers/podman/pull/7009, podman switch references from libpod.conf to containers.conf.
* According to containers.conf man (https://github.com/containers/common/blob/main/docs/containers.conf.5.md), configuration file is a TOML file but engine section declaration is missing.
2021-06-16 15:03:37 +02:00
Seth Foster
61846e88ca Add validator for ee image field name
awxkit default ee image name is now a fixed valid (but bogus) name, rather than random unicode
2021-06-15 20:06:49 -04:00
Jeff Bradberry
93e90228a2 Remove isolated instances and groups
before we remove the fields that allow us to correctly identify them.
2021-06-15 17:36:26 -04:00
softwarefactory-project-zuul[bot]
395af1b5e4 Merge pull request #10425 from sarabrajsingh/bugfix/preflight-check-postgres-version-4940
introduced a pre-flight check for postgres 12

SUMMARY


Introduced a pre-flight check to check the version of Postgres 12 before the application starts - ansible/tower#4940
ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.2.0

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Sarabraj Singh <singh.sarabraj@gmail.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-15 13:46:58 +00:00
softwarefactory-project-zuul[bot]
5d7bdb3cbc Merge pull request #10449 from mscherer/patch-1
Update irc server

SUMMARY

See ansible/community#613

ISSUE TYPE


Docs Pull Request

COMPONENT NAME


Doc

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-15 11:18:12 +00:00
mscherer
95d40f037d Update irc server
See https://github.com/ansible/community/issues/613
2021-06-15 10:19:40 +02:00
softwarefactory-project-zuul[bot]
ef67f9c65d Merge pull request #10436 from AlanCoding/installed_default
Prefer installer defaults over user-defined global EEs

The installer knows better than the user

Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Elijah DeLee <kdelee@redhat.com>
2021-06-15 00:59:06 +00:00
softwarefactory-project-zuul[bot]
8a4421dc0c Merge pull request #10290 from amigus/dsv
Add Thycotic DevOps Secrets Vault support

SUMMARY
Add a Credential Plugin for Thycotic DevOps Secrets Vault
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

API
UI

AWX VERSION
awx: 19.1.0

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Adam C. Migus <adam@migus.org>
Reviewed-by: Matthew Jones <bsdmatburt@gmail.com>
2021-06-14 19:22:59 +00:00
softwarefactory-project-zuul[bot]
2900bbbbd8 Merge pull request #10441 from shanemcd/bump-19.2.1
AWX 19.2.1

Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-06-14 19:05:42 +00:00
softwarefactory-project-zuul[bot]
a6c09daf1e Merge pull request #10414 from sean-m-sullivan/devel
Add Job data to return on wait failures

SUMMARY
This adds the returned results to the returned data when jobs fail when waited on. This brings it inline with information returned on success.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

awx collection

AWX VERSION
19.2.0

ADDITIONAL INFORMATION
before:
{
  "changed": false,
  "elapsed": 3.806,
  "finished": "2021-06-10T15:24:52.861344Z",
  "id": 153,
  "msg": "The Workflow Node - fail, failed",
  "started": "2021-06-10T15:24:49.055652Z",
  "status": "failed"
}
after:
{
  "changed": false,
  "elapsed": 3.806,
  "finished": "2021-06-10T15:24:52.861344Z",
  "id": 153,
  "job_data": {
    "allow_simultaneous": false,
    "artifacts": {
      "test": "fail"
    },
    "canceled_on": null,
    "controller_node": "",
    "created": "2021-06-10T15:24:48.504122Z",
    "custom_virtualenv": "/var/lib/awx/venv/ansible",
    "description": "",
    "diff_mode": false,
    "elapsed": 3.806,
    "event_processing_finished": true,
    "execution_node": "localhost",
    "extra_vars": "{\"fail\": \"workflow\"}",
    "failed": true,
    "finished": "2021-06-10T15:24:52.861344Z",
    "force_handlers": false,
    "forks": 0,
    "host_status_counts": {
      "failures": 1
    },
    "id": 153,
    "instance_group": 1,
    "inventory": 1,
    "job_args": "[\"bwrap\", \"--die-with-parent\", \"--unshare-pid\", \"--dev-bind\", \"/\", \"/\", \"--proc\", \"/proc\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/ansible_runner_pi_uai8yldi/tmp5wid0rwm\", \"/etc/ssh\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/ansible_runner_pi_uai8yldi/tmp5wmz8ule\", \"/etc/tower\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/ansible_runner_pi_uai8yldi/tmp4akvmhfo\", \"/home\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/ansible_runner_pi_uai8yldi/tmplpgjkbaw\", \"/tmp\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/ansible_runner_pi_uai8yldi/tmpgrdxeea3\", \"/var/lib/awx\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/ansible_runner_pi_uai8yldi/tmp2hidif23\", \"/var/lib/awx/job_status\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/ansible_runner_pi_uai8yldi/tmps2sv03e3\", \"/var/lib/awx/projects\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/ansible_runner_pi_uai8yldi/tmpoqb_xxh7\", \"/var/log\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/ansible_runner_pi_uai8yldi/tmpyjok4bi3\", \"/var/tmp\", \"--ro-bind\", \"/var/lib/awx/venv/ansible\", \"/var/lib/awx/venv/ansible\", \"--ro-bind\", \"/var/lib/awx/venv/awx\", \"/var/lib/awx/venv/awx\", \"--bind\", \"/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm\", \"/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm\", \"--chdir\", \"/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/project\", \"ssh-agent\", \"sh\", \"-c\", \"ssh-add /tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/artifacts/153/ssh_key_data && rm -f /tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/artifacts/153/ssh_key_data && ansible-playbook -u excalibrax --ask-pass -i /tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/tmp93bq8ck1 -e @/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/env/extravars fail.yml\"]",
    "job_cwd": "/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/project",
    "job_env": {
      "ANSIBLE_CALLBACK_PLUGINS": "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/ansible_runner/callbacks",
      "ANSIBLE_COLLECTIONS_PATHS": "/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/requirements_collections:~/.ansible/collections:/usr/share/ansible/collections",
      "ANSIBLE_FORCE_COLOR": "True",
      "ANSIBLE_HOST_KEY_CHECKING": "False",
      "ANSIBLE_INVENTORY_UNPARSED_FAILED": "True",
      "ANSIBLE_PARAMIKO_RECORD_HOST_KEYS": "False",
      "ANSIBLE_RETRY_FILES_ENABLED": "False",
      "ANSIBLE_ROLES_PATH": "/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/requirements_roles:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles",
      "ANSIBLE_SSH_CONTROL_PATH_DIR": "/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/cp",
      "ANSIBLE_STDOUT_CALLBACK": "awx_display",
      "ANSIBLE_VENV_PATH": "/var/lib/awx/venv/ansible",
      "AWX_HOST": "https://10.42.42.212",
      "AWX_ISOLATED_DATA_DIR": "/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm/artifacts/153",
      "AWX_PRIVATE_DATA_DIR": "/tmp/bwrap_153_uqo3h55g/awx_153_rvlvv4nm",
      "DJANGO_LIVE_TEST_SERVER_ADDRESS": "localhost:9013-9199",
      "DJANGO_SETTINGS_MODULE": "awx.settings.production",
      "HOME": "/var/lib/awx",
      "INVENTORY_ID": "1",
      "INVOCATION_ID": "6dfbb88bc6484622a4f44ffbc1196b44",
      "JOB_ID": "153",
      "JOURNAL_STREAM": "9:24634",
      "LANG": "en_US.UTF-8",
      "MAX_EVENT_RES": "700000",
      "PATH": "/var/lib/awx/venv/ansible/bin:/var/lib/awx/venv/awx/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
      "PROJECT_REVISION": "debeb7bd98d23a5d69103f024280ac5f8927d58a",
      "PROOT_TMP_DIR": "/tmp",
      "PS1": "(awx) ",
      "PWD": "/var/lib/awx",
      "PYTHONPATH": "/var/lib/awx/venv/ansible/lib/python3.6/site-packages:",
      "RUNNER_OMIT_EVENTS": "False",
      "RUNNER_ONLY_FAILED_EVENTS": "False",
      "SHLVL": "0",
      "SUPERVISOR_ENABLED": "1",
      "SUPERVISOR_GROUP_NAME": "tower-processes",
      "SUPERVISOR_PROCESS_NAME": "awx-dispatcher",
      "SUPERVISOR_SERVER_URL": "unix:///var/run/supervisor/supervisor.sock",
      "TZ": "UTC",
      "USER": "awx",
      "VIRTUAL_ENV": "/var/lib/awx/venv/ansible"
    },
    "job_explanation": "",
    "job_slice_count": 1,
    "job_slice_number": 0,
    "job_tags": "",
    "job_template": 14,
    "job_type": "run",
    "launch_type": "workflow",
    "limit": "",
    "modified": "2021-06-10T15:24:48.953892Z",
    "name": "fail",
    "organization": 1,
    "passwords_needed_to_start": [
      
    ],
    "playbook": "fail.yml",
    "playbook_counts": {
      "play_count": 1,
      "task_count": 3
    },
    "project": 13,
    "related": {
      "activity_stream": "/api/v2/jobs/153/activity_stream/",
      "cancel": "/api/v2/jobs/153/cancel/",
      "create_schedule": "/api/v2/jobs/153/create_schedule/",
      "created_by": "/api/v2/users/1/",
      "credentials": "/api/v2/jobs/153/credentials/",
      "inventory": "/api/v2/inventories/1/",
      "job_events": "/api/v2/jobs/153/job_events/",
      "job_host_summaries": "/api/v2/jobs/153/job_host_summaries/",
      "job_template": "/api/v2/job_templates/14/",
      "labels": "/api/v2/jobs/153/labels/",
      "notifications": "/api/v2/jobs/153/notifications/",
      "organization": "/api/v2/organizations/1/",
      "project": "/api/v2/projects/13/",
      "relaunch": "/api/v2/jobs/153/relaunch/",
      "source_workflow_job": "/api/v2/workflow_jobs/152/",
      "stdout": "/api/v2/jobs/153/stdout/",
      "unified_job_template": "/api/v2/job_templates/14/"
    },
    "result_traceback": "",
    "scm_branch": "",
    "scm_revision": "debeb7bd98d23a5d69103f024280ac5f8927d58a",
    "skip_tags": "",
    "start_at_task": "",
    "started": "2021-06-10T15:24:49.055652Z",
    "status": "failed",
    "summary_fields": {
      "created_by": {
        "first_name": "",
        "id": 1,
        "last_name": "",
        "username": "admin"
      },
      "credentials": [
        {
          "cloud": false,
          "description": "",
          "id": 1,
          "kind": "ssh",
          "name": "Demo Credential"
        }
      ],
      "instance_group": {
        "id": 1,
        "is_containerized": false,
        "name": "tower"
      },
      "inventory": {
        "description": "",
        "has_active_failures": true,
        "has_inventory_sources": false,
        "hosts_with_active_failures": 1,
        "id": 1,
        "inventory_sources_with_failures": 0,
        "kind": "",
        "name": "Demo Inventory",
        "organization_id": 1,
        "total_groups": 0,
        "total_hosts": 1,
        "total_inventory_sources": 0
      },
      "job_template": {
        "description": "",
        "id": 14,
        "name": "fail"
      },
      "labels": {
        "count": 0,
        "results": [
          
        ]
      },
      "organization": {
        "description": "",
        "id": 1,
        "name": "Default"
      },
      "project": {
        "description": "",
        "id": 13,
        "name": "fail",
        "scm_type": "git",
        "status": "successful"
      },
      "source_workflow_job": {
        "description": "",
        "elapsed": 4.89,
        "failed": true,
        "id": 152,
        "name": "fail_workflow",
        "status": "failed"
      },
      "unified_job_template": {
        "description": "",
        "id": 14,
        "name": "fail",
        "unified_job_type": "job"
      },
      "user_capabilities": {
        "delete": true,
        "start": true
      }
    },
    "timeout": 0,
    "type": "job",
    "unified_job_template": 14,
    "url": "/api/v2/jobs/153/",
    "use_fact_cache": false,
    "verbosity": 0,
    "webhook_credential": null,
    "webhook_guid": "",
    "webhook_service": ""
  },
  "msg": "The Workflow Node - fail, failed",
  "started": "2021-06-10T15:24:49.055652Z",
  "status": "failed"
}

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-06-14 18:58:38 +00:00
Alan Rominger
92c6ddf13c Prefer installer defaults over user-defined global EEs
Add a basic level of testing around get_default_execution_environment
2021-06-14 14:13:39 -04:00
Jake McDermott
c6ac2f56dc Update CHANGELOG.md 2021-06-14 14:09:53 -04:00
Sarabraj Singh
7a130a0616 flipped MODE switch for postgres check 2021-06-14 13:55:11 -04:00
Shane McDonald
188f0417d2 Fix typo 2021-06-14 13:38:41 -04:00
Shane McDonald
d38401fd18 Bump version to 19.2.1 2021-06-14 12:32:20 -04:00
Shane McDonald
dadf8940cc Remove outdated info from changelog 2021-06-14 12:32:10 -04:00
softwarefactory-project-zuul[bot]
6a36f802c2 Merge pull request #10434 from wenottingham/runner-update
Update runner to 2.0b1

SUMMARY
Newly released.

Reviewed-by: Elijah DeLee <kdelee@redhat.com>
2021-06-12 04:26:17 +00:00
Adam Migus
5509686f5b Remove unused imports to fix build. 2021-06-11 23:49:45 -04:00
Adam Migus
1ee241199e Refactor to simplify
- Remove eval and the expression metadata attribute
- Remove locale conditional on the tld field
2021-06-11 23:49:45 -04:00
Adam Migus
67d828cf80 Backout accidential changes to settings/defaults 2021-06-11 23:49:45 -04:00
Adam Migus
86c91509b3 Add Thycotic DevOps Secrets Vault support 2021-06-11 23:49:45 -04:00
Adam Migus
bfd1abd79c Add license for python-dsv-sdk to docs/licenses 2021-06-11 23:49:44 -04:00
Adam Migus
c169cf6d58 Fix test_credential.py
- Add 'thycotic_dsv' to the list of expected credential types
2021-06-11 23:49:44 -04:00
Adam Migus
9679c154f3 Backout accidential changes to settings/defaults 2021-06-11 23:49:44 -04:00
Adam Migus
a317b6bede Add Thycotic DevOps Secrets Vault support 2021-06-11 23:49:44 -04:00
Sarabraj Singh
f73de11acc introduced a pre-flight check for postgres 12 2021-06-11 23:18:38 -04:00
softwarefactory-project-zuul[bot]
6f16d64929 Merge pull request #10429 from AlanCoding/teardown_global_ee
Make ExecutionEnvironment awxkit class able to handle null values in …

This is how the Project class does it, and I can confirm it makes factories.execution_environment(organization=None) work correctly.

Reviewed-by: Jeff Bradberry <None>
2021-06-11 20:36:47 +00:00
softwarefactory-project-zuul[bot]
8a6656aa90 Merge pull request #10417 from mabashian/10411-inv-src-sync-details
Fixes bug where source list page would crash if first sync was running

SUMMARY
link #10411
The ID being passed to the cancel button was incorrect as well.  We want to reference current_job not last_job.

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Kersom <None>
Reviewed-by: Sarah Akus <sarah.akus@gmail.com>
2021-06-11 20:33:33 +00:00
Bill Nottingham
95ba6de172 Update runner to 2.0b1 2021-06-11 15:04:43 -04:00
softwarefactory-project-zuul[bot]
63aacd4e38 Merge pull request #10416 from mabashian/10400-search-keys
Addresses bug where advanced search by groups wasn't working on host list

SUMMARY
link #10400
OK so this got a bit more complicated than I wanted it to but I think on the whole this is a nice improvement.  In the initial bug report it was noted that we were ignoring the or/not operators when searching on a related key (in this case it was groups).  We were also ignoring the modifier at the end (icontains, exact, startswith, etc).  Since we were always defaulting to __search for these types of keys this was actually valid.  The API doesn't like us attempting to do something like ?or__groups__search=foo or ?groups__search__icontains because they aren't valid.  So, I changed the UX a little bit.  A user can still do a fuzzy search on a related key but the prefix is disabled in this case:

I changed the third dropdown (specifically for related keys) to contain the following options: search, id, name__icontains which I think would be the three most general cases.  id and name__icontains do allow for prefixing (or, not, and).
This should make searching on related keys a little bit easier and a little bit more flexible since name and id weren't possible in the UI before.
Once place where this is a little different is the host filter in the smart inventory form.  Using __search currently throws an error when the user attempts to save.  I believe this is an API bug and will file it as such but for now I prevent users from attempting to use __search by removing it as an option for this particular list.  When this bug gets fixed in the API we can remove this logic.
I also noticed that there was a bug where or__ search terms were being converted to and when using the Smart Inventory button on the host list so I fixed that.
Here's the fix in action:

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-11 18:12:01 +00:00
Alan Rominger
b39b80b036 Make ExecutionEnvironment awxkit class able to handle null values in payload 2021-06-11 13:32:46 -04:00
sean-m-ssullivan
214c27a5cf add job data to filed wait jobs 2021-06-11 09:45:28 -04:00
mabashian
ae83032ff3 Swap underscore for hyphen 2021-06-10 16:42:03 -04:00
softwarefactory-project-zuul[bot]
2e0dd61bb6 Merge pull request #10413 from AlexSCorey/10404-RoleAccessSaveButton
fixes next button and internationalizes nav buttons on wizard

SUMMARY
Resolves #10404 and it internationalizes the next button.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-10 19:13:19 +00:00
mabashian
25aae9abc6 Fixes bug where source list page would crash if first sync was running 2021-06-10 15:06:13 -04:00
mabashian
8b20d770a2 Addresses bug where advanced search by groups wasn't working on host list 2021-06-10 13:46:27 -04:00
Alex Corey
6726b72fe2 fixes next button and internationalizes nav buttons on wizard 2021-06-10 11:21:57 -04:00
softwarefactory-project-zuul[bot]
e610b77f8d Merge pull request #10397 from mabashian/job-output-socket-reconnect
Don't reconnect job output socket if it closes cleanly

SUMMARY
See #9795 (comment)
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-10 14:51:14 +00:00
softwarefactory-project-zuul[bot]
2490929fd5 Merge pull request #10394 from mabashian/brand-name
Pull brand name from default.strings.json

SUMMARY
We were pulling this string from variables.js.
There were several places where the brand name was not being pulled dynamically - this PR addresses that.  This changes the way we set the document title a little bit.  Since we needed access to a dynamic string, I went down the JS route to set this.

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Sarah Akus <sarah.akus@gmail.com>
2021-06-09 23:07:37 +00:00
softwarefactory-project-zuul[bot]
29ec0dc82a Merge pull request #10376 from mabashian/3831-settings-changes
Changes settings revert all to send DELETE on individual endpoint rather than PATCHing

SUMMARY
Resolves #3831
#3831 (comment) is a good explanation of the state of the new UI as well as the old.  The Misc System settings were the most problematic part of this since that form pulled fields from both /api/v2/settings/system and /api/v2/settings/authentication.  In order to revert these fields with a DELETE request I needed to split this form up into Miscellaneous System and Miscellaneous Authentication.  The Activity Stream Settings also needed to be absorbed by the Miscellaneous System Settings.
All settings forms (except noted below) will now issue a DELETE request to revert all the fields for a particular settings subsection.
There was one form that I did not change the Revert All functionality on and that was the LDAP Settings form(s).  The UI splits these fields out into 5 different subforms and reverting one (issuing a DELETE on /api/v2/settings/ldap) would revert all the ldap settings which I think is undesirable.
This fix has the added benefit of cleaning up future activity stream entries for reverting an entire settings category.
I also consulted with @wenottingham and @gamuniz on some fields that were present in the api but missing in the ui and I added those.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-09 21:29:06 +00:00
Shane McDonald
301d7a02c2 Update README.md 2021-06-09 17:21:39 -04:00
Shane McDonald
81e6ead99c Update README.md 2021-06-09 17:20:44 -04:00
softwarefactory-project-zuul[bot]
158fe23d7c Merge pull request #8650 from wenottingham/discovering-new-insights
Add support for Insights as an inventory source

SUMMARY
Use the insights inventory plugin as an inventory source.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

API

ADDITIONAL INFORMATION
Requires at minimum RedHatInsights/ansible-collections-insights#14

Reviewed-by: Bill Nottingham <None>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Chris Meyers <None>
2021-06-09 21:08:35 +00:00
softwarefactory-project-zuul[bot]
b3705357ba Merge pull request #10403 from nixocio/ui_issue_8890
Fix host filter chips on smart inventory

Fix host filter chips on smart inventory

See: #8890

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Sarah Akus <sarah.akus@gmail.com>
2021-06-09 20:58:34 +00:00
Bill Nottingham
f460f70513 Remove host insights view 2021-06-09 16:34:32 -04:00
Bill Nottingham
b6ced2b8dc Add UI bits 2021-06-09 16:34:32 -04:00
Bill Nottingham
be18803250 Add support for Insights as an inventory source 2021-06-09 16:34:32 -04:00
softwarefactory-project-zuul[bot]
f26d975005 Merge pull request #10378 from jbradberry/control-plane-ee
Control plane EE

SUMMARY
Per discussion, we are now going to have privileged execution environments for use on the control plane, and these will not be allowed to be edited or deleted.
related ansible/tower#5016
TODO

 reinstate the restrictive RBAC for managed_by_tower=True EEs
 convert any EEs automatically installed prior into managed_by_tower=False EEs
 change the resolver so that ordinary jobs do not get a managed EE, and project updates only get a managed EE
 allow sysadmin users to edit the pull field for managed EEs
 automatically disassociate EEs that get deleted from the DEFAULT_EXECUTION_ENVIRONMENT setting #10363

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Seth Foster <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-06-09 20:25:37 +00:00
mabashian
a7a17a2063 Extract strings 2021-06-09 16:13:20 -04:00
mabashian
9e657059f3 Pull brand name from default.strings.json 2021-06-09 16:11:04 -04:00
Jeff Bradberry
486bcd80f8 Make sure that the delete capability isn't hardcoded to be the same as edit 2021-06-09 15:45:02 -04:00
softwarefactory-project-zuul[bot]
e4f21ec294 Merge pull request #10291 from AlexSCorey/10152-AddsPFDatePicker-v2
Resolves issue where FireFox users could not schedule a job template

SUMMARY
This addresses #10152 and #6214
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

ADDITIONAL INFORMATION

Reviewed-by: Michael Abashian <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-09 18:52:29 +00:00
softwarefactory-project-zuul[bot]
3cb3819be9 Merge pull request #10395 from mabashian/10333-default-galaxy-cred
Preselect default galaxy cred when creating new org

SUMMARY
link #10333

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Yago Marques <yagomarquesja@gmail.com>
2021-06-09 18:16:52 +00:00
softwarefactory-project-zuul[bot]
122b36dcc5 Merge pull request #10388 from jakemcdermott/fix-favico
Use favicon for dev and prod builds

SUMMARY

Reviewed-by: Michael Abashian <None>
Reviewed-by: Sarah Akus <sarah.akus@gmail.com>
2021-06-09 18:10:39 +00:00
Jeff Bradberry
2d1a859719 Remove unused import 2021-06-09 13:48:23 -04:00
Shane McDonald
f882ac420d Fix tests 2021-06-09 13:48:23 -04:00
Shane McDonald
373cd9c20b Remove usage of AWXReceptorJob in metadata.py 2021-06-09 13:48:23 -04:00
Shane McDonald
673afdf1b5 Only install ansible-core for collection tests
Faster!
2021-06-09 13:48:23 -04:00
Jeff Bradberry
7a16782ebf Fix a problem with using PrimaryKeyRelatedField in our settings registry
DRF, when using this field, short-circuits the call to
.to_representation() when the value is None, since clearly you aren't
going to be able to get the .pk attribute off of it in that case.  We
were previously unconditionally calling .to_representation() which
throws an error when we try to clear the value of
DEFAULT_EXECUTION_ENVIRONMENT.
2021-06-09 13:48:23 -04:00
Jeff Bradberry
8ede74a7f6 Deal with the possibility of get_default_pod_spec not finding an EE 2021-06-09 13:48:23 -04:00
Jeff Bradberry
19da9955ce Make sure that managed EEs can't be deleted 2021-06-09 13:48:23 -04:00
Jeff Bradberry
e6e1f97048 Add a signal handler to remove the default EE if it gets deleted 2021-06-09 13:48:16 -04:00
softwarefactory-project-zuul[bot]
0a63c2d4a0 Merge pull request #10385 from mabashian/version_context_processor
Adds version context processor back in to fix api browser doc link

SUMMARY
Here's what it looks like on devel now (note the URL in the bottom left):

Here's what it looks like after the change (note the URL in the bottom left):

I dropped this in as it was before the removal of the old UI.  I believe the new UI needs access to some of these variables as well to force assets to be refetched after upgrade.
Also of note: I have no idea what I'm doing with django so please help me to become educated if I've done something silly here.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-06-09 15:44:45 +00:00
softwarefactory-project-zuul[bot]
493109782d Merge pull request #10402 from AlexSCorey/10350-TeamAddLoop
Stops infinte REST calls on ResourcesAccessAdd workflow

SUMMARY
resolves #10350
There is no functionality changes, I just moved the location of the variables so they are defined outside of the component.
E2E test triggered
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-09 15:33:11 +00:00
mabashian
0195bab931 Drop in favicon.ico from old app 2021-06-09 11:22:40 -04:00
Jake McDermott
e570810bdb Use favicon for dev and prod builds 2021-06-09 11:22:40 -04:00
Jeff Bradberry
9f1e8a1ae2 Allow sysadmins to be able to change the pull field for managed EEs 2021-06-09 11:11:56 -04:00
nixocio
9a0c159943 Fix host filter chips on smart inventory
Fix host filter chips on smart inventory

See: https://github.com/ansible/awx/issues/8890
2021-06-09 10:26:18 -04:00
Jeff Bradberry
9aa56b1247 Update the EE resolver logic
so that the control plane managed EE is kept separate.
2021-06-09 10:03:35 -04:00
Jeff Bradberry
d4d21a1511 Remove the managed flag from all existing EEs
This flag henceforth is going to be used only for the "control plane"
execution environments, which sysadmins will not be allowed to alter.
2021-06-09 10:03:35 -04:00
Alex Corey
27a2c842ac resolve infinite api calls 2021-06-09 07:50:00 -04:00
softwarefactory-project-zuul[bot]
87dcc49429 Merge pull request #10380 from nixocio/ui_remove_not
Do not show `not` as choice for Advanced Search on Smart Inventory

Do not show not set type as a  choice for Advanced Search on Smart Inventory since
this feature is not implemented on the API side yet.

See: #2817

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-08 21:43:54 +00:00
softwarefactory-project-zuul[bot]
805ca53765 Merge pull request #10390 from rooftopcellist/update-translations
Update translation make target for ui_next

SUMMARY
This adds the --clean flag to the extract-strings command (cleans up obsolete strings) and separates out the extract-template command.
ISSUE TYPE


Feature Pull Request

COMPONENT NAME


Translation Automation

AWX VERSION

19.2.0

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
2021-06-08 21:36:02 +00:00
Shane McDonald
070034047c Merge pull request #10377 from kdelee/control_plane_ee
Break out control plane EE as its own thing
2021-06-08 17:25:01 -04:00
softwarefactory-project-zuul[bot]
53c50947d1 Merge pull request #10347 from nixocio/ui_issue_9232
Update advanced search for Smart Inventories

Update advanced search for Smart Inventories
Update usage of conditional operators for advanced search for Smart Inventories
Not operator is not supported yet - See: #2817
See: #9232

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-08 21:16:35 +00:00
softwarefactory-project-zuul[bot]
108a6e11f4 Merge pull request #10384 from keithjgrant/6189-instance-list-table
Convert InstanceList to table

SUMMARY
Converts InstanceList to Paginated Table
addresses #6189 and #10160
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Kersom <None>
Reviewed-by: Sarah Akus <sarah.akus@gmail.com>
2021-06-08 21:04:22 +00:00
softwarefactory-project-zuul[bot]
a4bc306b96 Merge pull request #9084 from marshmalien/5057-launched-by
Extend launched by details to handle scheduled JTs and WFJTs

SUMMARY
Issue: #5057
Launched By detail should link to the schedule that launched the job.

ISSUE TYPE


Enhancement Pull Request

COMPONENT NAME


UI

Reviewed-by: Kersom <None>
Reviewed-by: Sarah Akus <sarah.akus@gmail.com>
2021-06-08 20:49:39 +00:00
softwarefactory-project-zuul[bot]
9106c3f813 Merge pull request #10373 from AlanCoding/limit_docs
Add OPTIONS documentation for new job limit feature

Looking at the docs and stuff from #10023
I'm sure this is somewhere else too, but this is the place that users should naturally expect it to be.

Reviewed-by: Chris Meyers <None>
2021-06-08 20:22:55 +00:00
softwarefactory-project-zuul[bot]
3340ef9c91 Merge pull request #10053 from AlanCoding/dropsies
Intentionally drop job event websocket messages in excess of 30 per second (configurable)

SUMMARY
The UI no longer follows the latest job events from websocket messages. Because of that, there's no reason to send messages for all events if the job event rate is high.
I used 30 because this is the number of events that I guesstimate will show in one page in the UI.
Needs the setting added in the UI.
This adds skip_websocket_message to event event_data. We could promote it to a top-level key for job events, if that is preferable aesthetically. Doing this allows us to test this feature without having to connect a websocket client. Ping @mabashian @chrismeyersfsu
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

API
UI

ADDITIONAL INFORMATION
Scenario walkthrough:
a job is producing 1,000 events per second. User launches it, the screen fills up in, say 1/4 of a second. The scrollbar indicates content beyond the bottom of the screen. Now, for 3/4ths of a second, the scrollbar stays still. After that, it updates the scrollbar to the current line number that the job is on. The scrollbar continues to update the length of the output effectively once per second.

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Chris Meyers <None>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-06-08 20:10:45 +00:00
mabashian
fc171deb79 Dont reconnect job output socket if it closes cleanly 2021-06-08 16:08:39 -04:00
Elijah DeLee
f2dac36dd1 Remove the cred too if not passed
NOW....should be idempotent and remove the the cred if it is not passed
2021-06-08 15:52:53 -04:00
Christian M. Adams
fb1a5c0db5 Update translation make target for ui_next 2021-06-08 15:26:00 -04:00
mabashian
d6a06c40f1 Preselect default galaxy cred when creating new org 2021-06-08 15:19:36 -04:00
softwarefactory-project-zuul[bot]
a6383e7f79 Merge pull request #10324 from shanemcd/default_queue_name
Introduce distinct controlplane instance group

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Matthew Jones <bsdmatburt@gmail.com>
Reviewed-by: Yanis Guenane <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-06-08 19:18:35 +00:00
Shane McDonald
3063073395 Merge pull request #9980 from fosterseth/fix_t4958_rename_collection
Rename awx_collection modules
2021-06-08 15:12:04 -04:00
Seth Foster
9eda6359f0 False to false to fix linter 2021-06-08 14:33:30 -04:00
Seth Foster
1deaf55ba4 syntax error in runtime.yml 2021-06-08 14:33:30 -04:00
Seth Foster
44c50bbbf7 add redirect for lookup and inventory plugins 2021-06-08 14:33:29 -04:00
Seth Foster
c9e7747f2d black ignore awx_collection 2021-06-08 14:33:29 -04:00
Seth Foster
199b4b6b47 fixed up jinja2 templating and documentation 2021-06-08 14:33:29 -04:00
Seth Foster
f06485feca fqcn redirects, and raise from sanity test fix 2021-06-08 14:33:29 -04:00
Seth Foster
4bd910493a sanity tests 2021-06-08 14:33:28 -04:00
Seth Foster
cd100fd770 fix super and kwargs 2021-06-08 14:33:28 -04:00
Seth Foster
157adb828e various sanity fixes 2021-06-08 14:33:28 -04:00
Seth Foster
b26e33ca34 remove eula_accepted 2021-06-08 14:33:28 -04:00
Sarabraj Singh
27a1254883 fixed ansible-test sanity import tests; removed sanity-ignore files 2021-06-08 14:33:28 -04:00
Sarabraj Singh
535bbfcc39 fixed validate-modules sanity tests 2021-06-08 14:33:27 -04:00
Sarabraj Singh
d2d511f596 switched to semenatic versioning for version numbers in plugins, library and tools packages 2021-06-08 14:33:27 -04:00
Sarabraj Singh
25ca8d22d6 added collection name to module.deprecate() calls; fixed pep8 linting issues 2021-06-08 14:33:27 -04:00
Sarabraj Singh
378a0711c2 linted AUTH_ARGSPEC to make it easier to read (<180 characters in the same line) 2021-06-08 14:33:26 -04:00
Sarabraj Singh
8fd9225629 removed un-reference-able python modules from ignore-2.9.txt 2021-06-08 14:33:26 -04:00
Seth Foster
ee8c1638c5 remove deprecated modules 2021-06-08 14:33:26 -04:00
Seth Foster
4add72b9d2 actually make use of option aliases 2021-06-08 14:33:25 -04:00
Seth Foster
54dd24b96b auth_plugin env alternative 2021-06-08 14:33:25 -04:00
Seth Foster
7d06fc74dd tower_username to controller_username, etc 2021-06-08 14:33:25 -04:00
Seth Foster
1a2e56c785 restore tower_legacy.py, update examples to include CONTROLLER_HOST 2021-06-08 14:33:25 -04:00
Seth Foster
a7b29f6112 controller_inventory.yml in addition to tower_inventory.yml 2021-06-08 14:33:24 -04:00
Seth Foster
39b26c8f0e Added env variable CONTROLLER_HOST, et al. Add awx.awx namespace to the runtime.yml redirects, and added templating task to change to ansible.controller 2021-06-08 14:33:24 -04:00
Seth Foster
1ade9b3a7d various references to tower 2021-06-08 14:33:24 -04:00
Seth Foster
82c5803e59 mostly includes renaming non-syntax references to tower 2021-06-08 14:33:24 -04:00
Seth Foster
9f4172ce7b upstream 2021-06-08 14:33:23 -04:00
Seth Foster
ef56571772 controller_meta, templating 2021-06-08 14:33:23 -04:00
Seth Foster
6911a59f39 fix unit tests 2021-06-08 14:33:23 -04:00
Seth Foster
7a63785255 more rename, mostly in test 2021-06-08 14:33:23 -04:00
Seth Foster
a695274cb6 regex replace tower_*: to '' 2021-06-08 14:33:22 -04:00
Seth Foster
44fed1d7c1 pycharm refactor rename files and class, linux rename tower_ controller_ 2021-06-08 14:33:22 -04:00
nixocio
be48d3eefd Update advanced search for Smart Inventories
Update usage of conditional operators for advanced search for Smart Inventories

Not is not supported yet - See: https://github.com/ansible/awx/issues/2817

See: https://github.com/ansible/awx/issues/9232
2021-06-08 13:41:06 -04:00
mabashian
3cc6a4cf44 Go back to tracking currentlyLoading via state and not ref 2021-06-08 13:33:54 -04:00
mabashian
ddf4fbc4ce Fix linting errors 2021-06-08 13:33:54 -04:00
mabashian
f0e7f2dbcd Adds logic to try to keep visible page accurate in follow mode 2021-06-08 13:33:54 -04:00
Alan Rominger
579d49033a Remove debugging log message 2021-06-08 13:33:54 -04:00
Alan Rominger
210d5084f0 Move skip flag up from event_data and pop it off 2021-06-08 13:33:54 -04:00
Alan Rominger
53e8a9e709 Fix bug 2021-06-08 13:33:53 -04:00
Alan Rominger
15effd7ade Add some conditions for always-send and never-send event types
Always send websocket messages for
  high priority events like playbook_on_stats

Never send websocket messages for
  events with no output
  unless they are a high priority event type
2021-06-08 13:33:53 -04:00
Alan Rominger
b919befc90 Add option to record websocket received time 2021-06-08 13:33:53 -04:00
Jake McDermott
faded278e3 Disable follow mode on scroll 2021-06-08 13:33:53 -04:00
Jake McDermott
768ac01f58 Add basic output tailing
When follow mode is enabled, fix the scroll position to the highest row
so that the output panel is always displaying the latest events.
2021-06-08 13:33:53 -04:00
Alan Rominger
4052603238 make sure log format does not error 2021-06-08 13:33:53 -04:00
Alan Rominger
b306c6f258 Put new setting in defaults so unit tests will run 2021-06-08 13:33:52 -04:00
Alan Rominger
4b6b8f2bdd Finish up the immediate or average rate method 2021-06-08 13:33:52 -04:00
Alan Rominger
70420dc3e4 THIS DOES NOT WORK pass events if they fit either timing criteria 2021-06-08 13:33:52 -04:00
Alan Rominger
50ca2d47ce Further log adjustments 2021-06-08 13:33:52 -04:00
Alan Rominger
faa0a6cf9a fix up log wording 2021-06-08 13:33:52 -04:00
Alan Rominger
01228cea02 Implement max event websocket rate as setting 2021-06-08 13:33:50 -04:00
Alan Rominger
cbb461ab71 Fix bug 2021-06-08 13:33:23 -04:00
Alan Rominger
b551608f16 Move websocket skip logic into event_handler 2021-06-08 13:33:22 -04:00
Marliana Lara
7a25f22078 Remove i18n prop 2021-06-08 13:33:03 -04:00
Alan Rominger
b43d8e2c7f Enforce a 30-per-second max event websocket rate 2021-06-08 13:32:05 -04:00
softwarefactory-project-zuul[bot]
2ad84b60b3 Merge pull request #10381 from AlanCoding/tox_configish
Enter flake8 rules in tox config as actual config entries

I really like to do things like
flake8 awx/main/models

but this is made impractical where running flake8 for the project carries with it an assumption that you will pass a specific set of options.
https://flake8.pycqa.org/en/latest/user/configuration.html
Blessedly, flake8 is flexible in their config options so that it may weather the storm of python project config wars.

Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-06-08 15:49:01 +00:00
Marliana Lara
d1981fcb4a Extend launched by details to handle scheduled JTs and WFJTs 2021-06-08 11:34:58 -04:00
softwarefactory-project-zuul[bot]
df8ce801cf Merge pull request #10325 from wenottingham/count-von-count
Add a field for hosts automated across to the subscription info

SUMMARY
This is populated by the new table we've added.
Update the subs check to check against this, not imported hosts.

ISSUE TYPE

Feature Pull Request
Bugfix Pull Request

COMPONENT NAME

API
UI

Reviewed-by: Bill Nottingham <None>
Reviewed-by: Amol Gautam <amol_gautam25@yahoo.co.in>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Chris Meyers <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-08 15:30:43 +00:00
nixocio
50e6348bef Do not show not as choice for Advanced Search on Smart Inventory
Do not show `not` as choice for Advanced Search on Smart Inventory since
this feature is not implemented on the API side yet.

See: https://github.com/ansible/awx/issues/2817
2021-06-08 11:17:01 -04:00
Alan Rominger
5ab449c90f Add event-specific template to all event types 2021-06-08 11:01:14 -04:00
softwarefactory-project-zuul[bot]
66a9ffc376 Merge pull request #10339 from mabashian/8596-websocket-connecting-state
Only attempt to reconnect socket if connection wasn't closed cleanly

SUMMARY
link #8596
After some investigation, I believe that this error is caused by the reconnect logic that we have.  When the component that references the ws hook unmounts, we disconnect the socket.  There's some logic in the onclose method that attempts to reconnect the socket but if we've disconnected cleanly we shouldn't try to reconnect (because we probably meant to disconnect in the first place).
This should clean up the console errors that we've been seeing about the socket already being in a connected state since we won't have timers running past the lifecycle of the component.
cc @keithjgrant does this sound good to you?
Here's the spec for the disconnect event https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#properties
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-08 14:36:41 +00:00
Alex Corey
16c6e2d716 uses pf date and time picker to schedule form 2021-06-08 10:32:38 -04:00
softwarefactory-project-zuul[bot]
ac5b53b13c Merge pull request #10334 from mabashian/outdated-revision
Adds ability to refresh project revision on sync'd rows in the project list

SUMMARY
This PR also adds the revision to the project details view as well as handles updating the revision on the project details view when the project is done syncing.
Since the project revision is not included in the websocket payload, when a project is done syncing the displayed revision may be out of date.  As such, we wanted to expose that information to the user and give them the ability to "refresh" and fetch the new revision.
Here's what that flow looks like:

When a particular row finishes syncing the user should see this in place of the revision:

Clicking on that refresh button goes out and fetches the updated project (and with it the potentially updated revision).
We don't do this automatically on the projects list (and force the user to click on the refresh button) is due to issues we've had in the past with the UI triggering API calls based on websocket events.
The flow when a user is on the project details view is a little different because I wasn't as worried about spamming the API with requests.
When a project finishes syncing and the user is viewing the details I do go ahead and automatically refresh the project data (and with it, the revision).  Here's what that looks like:

A few other notes:

@tiagodread @akus062381 @one-t I'm almost certain this is going to break some tests because I removed the ClipboardCopyButton in favor of PF's ClipboardCopy component.  This component looks and behaves slightly differently from our home grown solution.  Additionally, the PF ClipboardCopy button does not expose the ouiaId prop so I had to add a data-cy on that component.  You'll likely have to use that identifier to then grab the button inside in order to test out the clipboard copy functionality.
Source Control Revision is a net-new detail in the project details.  I think this was simply missed on our initial build of this page.

Here are the identifiers on the various bits:



Note that the identifiers on the project rows have the id of the project appended to them for uniqueness.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Michael Abashian <None>
Reviewed-by: Sarah Akus <sarah.akus@gmail.com>
2021-06-08 14:14:54 +00:00
softwarefactory-project-zuul[bot]
6d433cc42a Merge pull request #10379 from jakemcdermott/fix-logout-reload2
Avoid reload on manual logout

SUMMARY
#10383
Instead of reloading, set the authRedirectTo context variable to "/logout" and handle it as a special case when routing

Reviewed-by: Marliana Lara <marliana.lara@gmail.com>
2021-06-08 13:58:14 +00:00
softwarefactory-project-zuul[bot]
7c442f3f50 Merge pull request #10359 from AlanCoding/stop_setting_venv
Remove uses of ansible_virtualenv_path

Run a job with recent AWX, then inspect:
In [2]: Job.objects.order_by('-created').first().custom_virtualenv
Out[2]: '/var/lib/awx/venv/ansible'

We shouldn't do this. The job was ran after the custom_virtualenv field has become entirely informative / non-functional. It is very arguable whether jobs should keep this field. For pre-migration jobs, it is an accurate record of fact, so I'm not going out of my way to argue for removal.
With this change, new jobs will record a blank value for custom_virtualenv, which is more correct, because we don't do this.
I have carefully looked over @rebeccahhh's #10090, and I don't see any way that ansible_virtualenv_path is used. Model use is reported for templates, so that doesn't block removing the field on jobs either.

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Bill Nottingham <None>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-08 12:26:38 +00:00
Alan Rominger
d79f73ab7a Remove references to Ansible venv path because it does not exist 2021-06-07 21:14:35 -04:00
Alan Rominger
b26eaa3bd2 Remove uses of ansible_virtualenv_path 2021-06-07 21:14:35 -04:00
mabashian
de46fb409e Adds version context processor back in to fix api browser doc link 2021-06-07 19:52:01 -04:00
Keith J. Grant
8078daa733 convert InstanceList to table 2021-06-07 15:06:12 -07:00
softwarefactory-project-zuul[bot]
e4931bde6c Merge pull request #10346 from jakemcdermott/fix-9905
Disable cancel button on http 405

SUMMARY
for #9905
When a 405 is received, it means the job is already cancelled. Treat the
request as a success and don't show an error modal.
We disable the button to handle a rare scenario where we receive the 405 long before
the job status is properly updated to "cancelled" over websockets. We want to prevent
more cancel requests when this happens. We're disabling instead of hiding the button
because, assuming the status hasn't changed over sockets, the buttons that usually
replace the cancel button on the toolbar won't be shown yet and we don't want to
needlessly flicker and shift button positions around by rapidly loading and unloading
a different number of buttons onto the bar.

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Sarah Akus <sarah.akus@gmail.com>
2021-06-07 21:25:05 +00:00
Elijah DeLee
e2b0a4f7a7 Make changed result accurate for credentials 2021-06-07 17:16:14 -04:00
Jake McDermott
5da6b02801 Avoid reload on manual logout 2021-06-07 16:51:06 -04:00
Elijah DeLee
326184da0f fixup changed behavior for EEso its accurate 2021-06-07 16:50:53 -04:00
Alan Rominger
dad5533816 Enter flake8 rules in tox config as actual config entries 2021-06-07 16:21:50 -04:00
Bill Nottingham
ca07946c24 Adjust subscription calculation & warning behavior
- Add a field for hosts automated across

  This is populated by the new table we've added.
- Update the subs check to check against this, not imported hosts.
- Reword messages on inventory import
2021-06-07 15:47:55 -04:00
Elijah DeLee
2ce276455a Break out control plane EE as its own thing 2021-06-07 15:39:20 -04:00
mabashian
4db6b8c1fe Rolls back aggressive find/replace on fetchProjects 2021-06-07 14:21:34 -04:00
mabashian
03209fe2f2 Updates onCopy functions to use navigator.clipboard instead of deprecated execCommand 2021-06-07 14:18:27 -04:00
softwarefactory-project-zuul[bot]
7832639c25 Merge pull request #10361 from nixocio/ui_issue_10355
Update message for missing EE for Job pages

Update message for missing EE for Job pages
See: #10355

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Kersom <None>
Reviewed-by: Michael Abashian <None>
2021-06-07 18:18:15 +00:00
mabashian
121db42699 Fix data-cy 2021-06-07 13:33:08 -04:00
mabashian
ddb6c775b1 Adds dataCy to revision copy in project details 2021-06-07 13:33:07 -04:00
mabashian
7467779ea9 Remove clipboard copy button component 2021-06-07 13:33:07 -04:00
mabashian
66f140bb70 Adds ability to get latest revision from project list when a project is done syncing. Automatically refresh project data on project detail when it's done syncing. 2021-06-07 13:33:06 -04:00
mabashian
151f9e79ed Move debug message inside if statement so that it only triggers when we try to reconnect 2021-06-07 13:30:19 -04:00
mabashian
f83343592b Only attempt to reconnect socket if connection wasn't closed cleanly 2021-06-07 13:29:14 -04:00
mabashian
12504c9bc3 Changes settings revert all to send DELETE on individual endpoint rather than PATCHing 2021-06-07 13:19:16 -04:00
Shane McDonald
023cc68ba2 Surface default instance group names in /api/v2/settings/all 2021-06-07 12:22:58 -04:00
Shane McDonald
ec8ac6f1a7 Introduce distinct controlplane instance group 2021-06-07 11:25:59 -04:00
Yanis Guenane
82c4f6bb88 Define a DEFAULT_QUEUE_NAME 2021-06-07 11:25:23 -04:00
Alan Rominger
5beb68f527 Remove templates from views that were removed 2021-06-07 11:15:19 -04:00
Alan Rominger
2eb1e4bbe3 Add OPTIONS documentation for new job limit feature 2021-06-07 11:11:22 -04:00
Shane McDonald
d3b20e6585 Merge pull request #10362 from shanemcd/runner-alpha-5
Bump to Ansible Runner alpha 5 release
2021-06-04 16:51:19 -04:00
nixocio
310cc2fd03 Update message for missing EE for Job pages
Update message for missing EE for Job pages

See: https://github.com/ansible/awx/issues/10355
2021-06-04 16:04:39 -04:00
softwarefactory-project-zuul[bot]
1fd6ba0bfc Merge pull request #10349 from AlexSCorey/8401-MoreFiltersonDashboard
Adds more filters to dashboard chart

SUMMARY
Resolves #8401 and #10356
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

AWX VERSION



ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-04 19:56:10 +00:00
softwarefactory-project-zuul[bot]
b64f966db1 Merge pull request #10090 from rebeccahhh/custom_venv_command
add a new awx-manage command `custom_venvs`

add an awx-manage command that gets pip freeze data from custom_venv and outputs to command line stdout
SUMMARY

part of #7062  - this command is a glorified pip freeze + some extra stuff, people could navigate to each of their custom virtual environments themselves and run a pip freeze, but this allows them to not, and everyone likes their life to be easier. The extra stuff allows users to see the connections that their existing virtual envs have in awx to things like organizations, jobs, inventory updates, and projects.

ISSUE TYPE


Feature Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.1.0

ADDITIONAL INFORMATION

This is built off of existing code and there is a line that gets custom venv paths from the settings module, that line does not seem to be working. I have written around that but want to make a note of it.

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Elijah DeLee <kdelee@redhat.com>
2021-06-04 18:44:52 +00:00
softwarefactory-project-zuul[bot]
891eeb22a5 Merge pull request #10343 from chrismeyersfsu/doc-job_event_performance
add docs on debugging job event perf

related to ansible/tower#4985

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-06-04 17:17:16 +00:00
softwarefactory-project-zuul[bot]
0f6e221c14 Merge pull request #10023 from ansible/db_partition_analytics_cmeyers2
Db partition analytics cmeyers2

Keep old primary key based analytics gathering for unpartitioned
tables.
Use created time on new partitioned tables.

80 million partitioned + 1.5 million unpartitioned Events



Query
awx-manage gather_analytics --dry-run Time
Micro Benchmark Query Time*
Query Only Time**




sequential index scan, multiple ::json casts, 100,000 event batches
102m7.836s
6s
80 minutes


sequential index scan, optimized json cast, 100,000 event batches
48m9.276s
2.2s
30.4 minutes


sequential index scan, optimized json cast, 1,00,000 event batches
39m35.094s
10s
13.3 minutes


sequential table scan, optimized json cast, per-partition batch 600,000 ***
36m42.081s
11.5s
25.5 minutes



*micro benchmarking consists of simply copying a query, running it manually, and observing the runtime.
**micro benchmark time x (80 million / batch size)
**Note that this testing does NOT include the extra modified range query that is needed for correctness. We expect this to be quite fast and is only needed to catch edge case events.

Reviewed-by: Ladislav Smola <lsmola@redhat.com>
Reviewed-by: Elijah DeLee <kdelee@redhat.com>
2021-06-04 16:48:11 +00:00
Shane McDonald
239f20ede5 Bump to Ansible Runner alpha 5 release 2021-06-04 12:22:53 -04:00
Chris Meyers
ffbbcd2bf6 fix tests, add pagination tests
* job_created is a fake field as far as Django is concerned. Under the
hood, in postgres, this is the partition key so it is real. sqlite
doesn't support partitioning so we need to fake some things.
Specifically, we need to remove job_created from being auto-added to
get_event_queryset()
* Add pagination tests for <unified_job_name>/<id>/<job_events>?limit=x
endpoint to make sure the paginator is wired up.
2021-06-04 09:17:09 -07:00
Jake McDermott
b648957c8e Update pagination scheme for jobs
* Use an initial request for max event `counter` to get the total row count,
otherwise rely on websocket message counters to update remote row count

* For running jobs, request event ranges with counters to handle events getting
saved to db out of display order

* For jobs that are no longer running, continue to use page/pageSize scheme for
paging through the job events
2021-06-04 09:17:09 -07:00
Jim Ladd
31fe500921 move get_queryset handling to child view 2021-06-04 09:17:09 -07:00
Chris Meyers
2131703ca0 add/remove indexes, more get_event_querset()
* Do not cascade delete unified job events. We will clean those up in
cleanup_job runs
* Add limit pagination to all unified job events endpoints
2021-06-04 09:17:09 -07:00
Jim Ladd
c429563126 update view to handle hosts/N/ad_hoc_command_events 2021-06-04 09:17:09 -07:00
Chris Meyers
1a1d66d2a2 bump db partition migration 2021-06-04 09:17:09 -07:00
Chris Meyers
30871bd6cf close db and cache connection in new threads 2021-06-04 09:17:09 -07:00
Chris Meyers
321135da3d add limit pagination to jobs/<id>/job_events/
* trigger via jobs/<id>/job_events/?limit=10
* Can and should be used in conjunction with an indexed set of fields to
generate efficient pagination queries. i.e.
jobs/<id>/job_events?limit=10&start_line__gte=10
* If limit is not specified in the query params then the default
pagination will be used.
2021-06-04 09:17:09 -07:00
Jim Ladd
2a23b4c719 bump migration 2021-06-04 09:17:09 -07:00
Jim Ladd
f7d2f7a5e6 lint 2021-06-04 09:17:09 -07:00
Jim Ladd
e371de38ed update job cleanup tests for sqlite-based execution 2021-06-04 09:17:09 -07:00
Jim Ladd
84af610a1f remove rebase cruft 2021-06-04 09:17:09 -07:00
Jim Ladd
ef9f9129ba bump migration 2021-06-04 09:17:09 -07:00
Jim Ladd
7b188aafea lint 2021-06-04 09:17:09 -07:00
Chris Meyers
6ce227a6b6 bump migrations 2021-06-04 09:17:09 -07:00
Chris Meyers
1c97b9a046 no longer get the size of the gather set
* Before, we would get the min and max pk of the set we are to gather.
This changeset removes that.
* Before, we would, basically, know the size of the set we are to gather
and would query 100,000 of those job event records at a time. That logic
is now gone.
* Now, for unpartitioned job events we gather 4 hours at a time by
created time.
* Now, for partitioned job events we gather 4 hours at a time by
modified time.
2021-06-04 09:17:09 -07:00
Chris Meyers
137111351c bump migrations after devel rebase 2021-06-04 09:17:09 -07:00
Chris Meyers
c5a1e4c704 remove order by from partitioned events query
* The order by results in an in-memory sort that COULD blow out the
worker mem buffer and result in sorting having to take place on disk.
* This WILL happen with a default postgres 4MB mem buffer. We saw as
much as 20MB used. Note that AWX defaults postgres mem worker buffer to
3% of the DB memory on external installs and 1% on same-node installs.
So for a 16GB remote DB this would not be a problem.
* We are going to avoid this problem all together by NOT doing a sort
when gathering. Instead, we will sort remotely, in analytics.
2021-06-04 09:17:09 -07:00
Chris Meyers
4f058245e4 conditionally project job_created
* Old, _unpartitioned_main_jobevent table does not have the job_created
column
* New, main_jobevent does.
* Always in clude the job_created column. NULL if old, job_created if
new
* Bump events_table schema version from 1.2 to 1.3 because of the
job_created field
2021-06-04 09:17:08 -07:00
Chris Meyers
ecdf6cccf8 json cast optimization
* We found that having multiple `::json` casts in a query slows down
queries more and more by =~> 33%.
* This change coerces postgres into only casting once. Micro
benchmarking shows =~ 2-3x performance boost
2021-06-04 09:17:08 -07:00
Chris Meyers
4d7edbbad0 analytics support for db partitions
* Keep old primary key based analytics gathering for unpartitioned
tables.
* Use created time on new partitioned tables.
2021-06-04 09:17:08 -07:00
Jim Ladd
0f9f3f58e2 bump migration 2021-06-04 09:17:08 -07:00
Chris Meyers
34c4967d27 Revert "query for jobevents based on table location"
This reverts commit 278dc521fffb85d4faa023ccd634044cfd3b3d75.
2021-06-04 09:17:08 -07:00
Jim Ladd
6123b8e148 query for jobevents based on table location
* pre-migration jobevents live in unpartitioned table
  where only created field has index
* post-migration jobevents live in partitions
  where modified field has index
  (and should be used to ensure no events are missing)
2021-06-04 09:17:08 -07:00
Jim Ladd
b86d365dde collect job events based on job event modified time
* when collecting job events by creation time
  it is possible to miss events that were created
  at one point, but actually committed to the db
  much later.
* since events' modified time is set when they are
  committed to the db, we shouldn't miss any job events
* selecting job events by modified time wasn't possible
  beforehand because we didn't have an index for
  jobevent's modified field
2021-06-04 09:17:08 -07:00
Chris Meyers
4efbd45b3c add support for db partition in cleanup_jobs
Changes in old unpartitioned cleanup logic:
* Manually cascade delete events related to job(s)

(new partitions cleanup logic) For each event type:
* Get the event partitions that are within the cleanup date range
* Get a list of jobs to delete that are in the cutoff range.
* Jobs that are running, pending, or waiting in the job list are special.
* Use the special list to further filter the partition drop list.
* Drop partitions
* delete jobs
2021-06-04 09:17:08 -07:00
Jim Ladd
fb97687d14 lint 2021-06-04 09:17:08 -07:00
Jim Ladd
0f53d9b911 bump db partition migration 2021-06-04 09:17:08 -07:00
Jim Ladd
5a785798b0 is_partitioned should default to true when pk not set 2021-06-04 09:17:08 -07:00
Jim Ladd
14168297bd set event horizon to -1 for empty tables 2021-06-04 09:17:08 -07:00
Jim Ladd
7e1814e234 mock has_unpartitioned_events in collection tests
.. just like we do with the main awx tests
2021-06-04 09:17:08 -07:00
Jim Ladd
bdf11aa962 add migrations for Unpartitioned{Job}Event proxy models 2021-06-04 09:17:08 -07:00
Jim Ladd
46807205f8 Move created kwargs to right place 2021-06-04 09:17:08 -07:00
Jim Ladd
d749c172eb Ensure View.model exists before checking type 2021-06-04 09:17:08 -07:00
Jim Ladd
81db8091ea test updates
* when tests create a UnifiedJob and JobEvent,
  the two need to have the same value for job creation time
* some view validation was skipped due to `model` being
  a property in some cases now
2021-06-04 09:17:08 -07:00
Jim Ladd
5c1a33382c update mocks to reflect new migration
* instead of mocking `created_or_epoch` (which no longer exists)
* .. mock `Unified_Job.has_unpartitioned_events`
2021-06-04 09:17:08 -07:00
Jim Ladd
db6f565dca black formatting 2021-06-04 09:17:08 -07:00
Jim Ladd
6b4effc85a bump partition migration to 135 2021-06-04 09:17:08 -07:00
Jim Ladd
74a0c5bac5 Minor rebase fallout
* fix import
* remove dropped url
2021-06-04 09:17:08 -07:00
Jim Ladd
661cf0afb3 short-circuit event_processing_finished for wf jobs
* wf jobs are a wrapper for other jobs
* they do not process their own job events
2021-06-04 09:17:08 -07:00
Ryan Petrello
fbb74a9896 remove code that leaves behind old bigint tables on fresh installs
we don't need this code at all anymore - the bigint migration is long
gone, and anybody upgrading to this version of AWX has already
migrated their data
2021-06-04 09:17:08 -07:00
Ryan Petrello
200901e53b upgrade to partitions without a costly bulk data migration
keep pre-upgrade events in an old table (instead of a partition)

- instead of creating a default partition, keep all events in special
"unpartitioned" tables
- track these tables via distinct proxy=true models
- when generating the queryset for a UnifiedJob's events, look at the
  creation date of the job; if it's before the date of the migration,
  query on the old unpartitioned table, otherwise use the more modern table
  that provides auto-partitioning
2021-06-04 09:17:08 -07:00
Jim Ladd
0eddd5ce7f Enable partition pruning when fetching job's events 2021-06-04 09:17:07 -07:00
Jim Ladd
a7cabec3d0 bump partition migration to 0132 2021-06-04 09:17:07 -07:00
Jim Ladd
b98b3ced1c update tests to reflect new job_event schema 2021-06-04 09:17:07 -07:00
Jim Ladd
8501a45531 lint fixes 2021-06-04 09:17:07 -07:00
Jim Ladd
14b610dabf bump partition migration 2021-06-04 09:17:07 -07:00
Jim Ladd
a1d1e70e43 correct constraint name 2021-06-04 09:17:07 -07:00
Jim Ladd
0fa0a517ac create tmp schema to reference when creating partitioned table
* if we use the actual old job events table
  and make tweaks to its schema
  namely, dropping the pkey constraint,
  then when we go to migrate the old job events
  we will be forcing postgres to do a sequential scan
  on the old table, which effectively causes the migration to hang
2021-06-04 09:17:07 -07:00
Jim Ladd
28f9c0be0b Do not cascade delete job_events
* want to drop job_event _partitions_
  .. instead of having the job events associated with a job
     automatically get cleaned up for us
2021-06-04 09:17:07 -07:00
Jim Ladd
373edbf8c0 Update reference to partition migration 2021-06-04 09:17:07 -07:00
Ryan Petrello
b19bcdd882 remove the global /api/v2/job_events/ endpoint 2021-06-04 09:17:07 -07:00
Ryan Petrello
08b96a0bd7 correct filter events on the migration event horizon
events that existed *prior* to the partition migration will have
`job_created=1970-01-01` auto-applied at migration time; as such,
queries for these events e.g., /api/v2/job/N/job_events/
use 1970-01-01 in related event searche

events created *after* the partition migration (net-new playbook runs
will have `job_created` values that *exactly match* the related
`UnifiedJob.created` field.
2021-06-04 09:17:07 -07:00
Jim Ladd
1e45e2ab9b Rev migration number 2021-06-04 09:17:07 -07:00
Ryan Petrello
2a58605727 some more events view cleanup 2021-06-04 09:17:07 -07:00
Ryan Petrello
c7ab3ea86e move the partition data migration to be a post-upgrade async process
this copies the approach we took with the bigint migration
2021-06-04 09:17:07 -07:00
Jim Ladd
67046513ae Push changes before rebasing 2021-06-04 09:17:07 -07:00
Jim Ladd
f9b439ae82 include job_created field in all job event types 2021-06-04 09:17:07 -07:00
Jim Ladd
80b08d17e3 Continue updating job event views 2021-06-04 09:17:07 -07:00
Jim Ladd
f642c520bd Update fields for job event models to match raw sql operations
* raw sql commands were in migration to partition table
* .. just needed to add FakeAddField entries for the new
     job_created field added to each job event model
* .. and also needed to actually list the new field on the model classes
2021-06-04 09:17:07 -07:00
Jim Ladd
221ddeb915 Fix migration for _all_ job event tables
- each job event table has a different name for the
  fk referencing the unified job id
- create a mapping so that we get the col name correct
  for each table
2021-06-04 09:17:07 -07:00
Jim Ladd
d90d0fb503 fix initial partition creation
* call create_partition correctly (include tblname)
* reference 'awx_epoch'
2021-06-04 09:17:07 -07:00
Jim Ladd
2c529f50af Update querysets for remaining job event views
- search should use job creation date
  so that only the table partition with the relevant job events
  is searched
2021-06-04 09:17:07 -07:00
Jim Ladd
acfa1c4d1d Drop todo / question / conditional
* can safely assume job_created is set
* .. and if it isn't, we want to expose that bug
2021-06-04 09:17:07 -07:00
Jim Ladd
ea2afeec1f Drop todo / answered question 2021-06-04 09:17:07 -07:00
Jim Ladd
a5cfc3036f create_partition needs tblname 2021-06-04 09:17:07 -07:00
Jim Ladd
ec484f81cf Partition *all* job event tables 2021-06-04 09:17:06 -07:00
Jim Ladd
2ffa22e38f Misc doc clean-up 2021-06-04 09:17:06 -07:00
Jim Ladd
8fb313638c get job events based on job creation date 2021-06-04 09:17:06 -07:00
Jim Ladd
0eb1984b22 Only create partitions for regular jobs 2021-06-04 09:17:06 -07:00
Jim Ladd
f259b0a71b Move partition start date to 2000 2021-06-04 09:17:06 -07:00
Jim Ladd
82df3ebddb add option to create partitions that span a single minute
* turned on by default currently for testing
2021-06-04 09:17:06 -07:00
Jim Ladd
c87d7b0d79 fix import 2021-06-04 09:17:06 -07:00
Jim Ladd
612e91263c auto-create partition 2021-06-04 09:17:06 -07:00
Jim Ladd
445042c0f4 Create partition only if it doesn't exist 2021-06-04 09:17:06 -07:00
Jim Ladd
0c289205de Give new primary key constraint unique name, create first live partition 2021-06-04 09:17:06 -07:00
Jim Ladd
ba45592d93 create helper method to create partitions
* create_partition()
2021-06-04 09:17:06 -07:00
Jim Ladd
7e0f2b0f08 first partition is _not_ a special case after all 2021-06-04 09:17:06 -07:00
Jim Ladd
fb30528197 Dynamically create initial partitions
* First partition holds all events up to this very moment
* And second partition starts where first left off and runs
  .. through rest of current hour
* From there, dynamically generated partitions will cover
  one hour at a time
2021-06-04 09:17:06 -07:00
Jim Ladd
48f1910075 Remove temporary catch-all partition 2021-06-04 09:17:06 -07:00
Jim Ladd
0cb2d79889 Only save job_created field on JobEvent for the time being
* Once other job event tables are migrated, remove this
2021-06-04 09:17:06 -07:00
Jim Ladd
1af1a5e9da Convert job_created to string for serialization 2021-06-04 09:17:06 -07:00
Jim Ladd
c0d38e91f5 When saving JobEvents, include job_created
* this is the partition key
* .. used to determine which partition job event rows are sent to
2021-06-04 09:17:06 -07:00
Jim Ladd
2f737f644f Drop primary key index before creating partition table
* Partition tables require unique contstraints to include the
  partition key (uniqueness can only be enforced _inside_
  of a given partition table)
2021-06-04 09:17:06 -07:00
Jim Ladd
0574baf7f7 Create fake partition
* Just to get things working
* Will implement dynamic creation of partitions later
2021-06-04 09:17:06 -07:00
Jim Ladd
f70473dc0b When copying main_jobevent, include all table metadata
* copy the table just like we do in the bigint migration
* without this we lose sequences and very likely other things
  as well
* we want the new table to be identical to the old table,
  so 'including all' makes sense
2021-06-04 09:17:06 -07:00
Jim Ladd
de0b25862b By default, save job_created as null in db
* Want to avoid saving date as empty string
* Should default to null so that it's obvious the field is empty
2021-06-04 09:17:06 -07:00
Jim Ladd
6ff15a928a Register new column created by SQL
* .. using FakeAddField model type
* .. without doing this, Django won't know
     about the field we created using raw SQL
2021-06-04 09:17:06 -07:00
Jim Ladd
d10d1963c1 Rename / remove old main_jobevent table 2021-06-04 09:17:06 -07:00
Jim Ladd
c6acca08d5 first draft of db partitioning 2021-06-04 09:17:06 -07:00
Chris Meyers
9946959599 clarify reference to code to be pasted 2021-06-04 12:10:10 -04:00
Chris Meyers
9ce171d349 Merge pull request #8 from beeankha/doc_edits
Doc Edits
2021-06-04 11:12:47 -04:00
softwarefactory-project-zuul[bot]
12f2975809 Merge pull request #10358 from jakemcdermott/fix-credlink
Make IG credential linkable

SUMMARY
Make the instance group credential detail link to the cred

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-04 15:12:03 +00:00
softwarefactory-project-zuul[bot]
945125454b Merge pull request #10357 from jakemcdermott/fix-inventory-host-search-config
Add search config for inventory hosts

SUMMARY
Adds search config for inventory hosts.
(includes default icontains, etc.)

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-04 15:05:25 +00:00
softwarefactory-project-zuul[bot]
ea67c70437 Merge pull request #10257 from mabashian/6073-typeahead-lookup
Adds support for typing values into single select lookups

SUMMARY
link #6073
This adds support for typing values into single select lookups.  Multi-select lookups (credentials on the JT form, instance groups, etc) will remain unchanged.
An input is now rendered next to the lookup button which will allow users to type a value in.
Here's the button (which opens the modal):

Here's the input (which lets users type a value in):

There's a debounce on the input so that we only make a request to check to see if the name is valid after a second of no typing.
The tricky part of this implementation was handling validation on the lookup fields.  If a user types in a string that does not exactly match a value that they can use then we want to show an error indicating that no matching value was found:

but this was tricky because some of these fields are required so the validation functions would need to change a bit.
Since the typed text and the actual underlying value of the lookup are different the validation function would need to have access to both values whenever it runs for this to work.  This meant either storing the typed text up at the form level or pushing the validation down into the lookup(s).  After talking with @keithjgrant we decided to go down the route of pushing the validation down to the lookups.
You can now pass an optional validation function down to the various lookups that will get combined with the typeahead validation via the useField hook.
Here's the whole thing in action:

ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Michael Abashian <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-04 15:03:53 +00:00
beeankha
f2f2483708 Doc edits 2021-06-04 11:01:06 -04:00
Alex Corey
8c61a49e01 prevents dashboard counts from reloading with line chart filters change 2021-06-04 10:55:40 -04:00
Jake McDermott
88ff68295b Make IG credential linkable 2021-06-04 10:27:14 -04:00
Jake McDermott
d93f62c030 Add search config for inventory hosts 2021-06-04 09:51:43 -04:00
Chris Meyers
ae5b11a2a9 add docs on debugging job event perf 2021-06-04 09:12:23 -04:00
Rebeccah
baade775ab remove changes to root.py to keep the custom virtualenvs listed in api/config 2021-06-04 09:11:23 -04:00
Rebeccah
bd2da80cea restructure so the -q is actually completely quiet 2021-06-04 09:11:22 -04:00
Rebeccah
550ab82f63 add the conditionals for incorrect paths and helpful info for if a user does that
and remove unused import
2021-06-04 09:11:22 -04:00
Rebeccah
cece7ff741 add a -q flag to make scripting easier and general improvements for readability 2021-06-04 09:11:22 -04:00
Rebeccah
c0b812c47a split unified job templates out into jts and projects because workflows
don't have custom virtualenvs & rename file so the command is shorter

update copypasta and add sanity check
2021-06-04 09:11:22 -04:00
Rebeccah
b256e5b79d adding in a 3rd command that shows the associated templates, orgs, and invs the venv is tied to 2021-06-04 09:11:22 -04:00
Rebeccah
2ed3038a5c fixed what would be a rather embarrassing misspeeeling 2021-06-04 09:11:21 -04:00
Rebeccah
779ca8b260 split the one command into two for clarity and remove unused imports 2021-06-04 09:11:21 -04:00
Shane McDonald
137fedfc9b Rename custom venv export command and add usability tweaks
- Uses a positional argument instead of a named arg
- More helpful output
2021-06-04 09:11:21 -04:00
Shane McDonald
256a47618f Ignore awx venv
- General usability / readibility improvements
2021-06-04 09:11:20 -04:00
Rebeccah
dfaa69be51 add an awx-manage command that gets pip freeze data from custom_venvs and outputs to command line stdout
remove analytics tests for counts of custom venvs, bump collector version, and remove list of custom venvs from API
2021-06-04 09:11:16 -04:00
softwarefactory-project-zuul[bot]
c34fa30ea7 Merge pull request #10342 from mabashian/10338-checkbox-double-select
Fixes bug where checkbox list item was selecting things twice

SUMMARY
Resolves #10338
There was a click event on the row and the underlying checkbox.  I got rid of the underlying click event so now its only handled at the row level.

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-03 21:37:05 +00:00
softwarefactory-project-zuul[bot]
3e5ee9d57a Merge pull request #10322 from jbradberry/show-ee-resolver
Expose the EE resolver to the API

SUMMARY
This change exposes the output of .resolve_execution_environment() for job templates as a new summary field in the API.  Note that this is only exposed for the detail views, not the list views.  Also, there is the caveat for job templates that may be run under workflows that the workflow EE might override the results of this value.
related #10210
ISSUE TYPE

Feature Pull Request

COMPONENT NAME


API

AWX VERSION

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Chris Meyers <None>
Reviewed-by: Jeff Bradberry <None>
2021-06-03 21:11:33 +00:00
softwarefactory-project-zuul[bot]
c7dd3996df Merge pull request #10351 from AlanCoding/sliced_ee
Skip sliced jobs from the workflow EE logic

Addressing some unanticipated fallout from #10305
Sliced jobs rely on creating a workflow job, but they do not have a workflow_job_template, so in those cases, that was causing a traceback.
2021-06-03 20:10:52,319 ERROR    [a17ebd7f] awx.main.dispatch Worker failed to run task awx.main.tasks.RunJob(*[341], **{}
Traceback (most recent call last):
  File "/awx_devel/awx/main/dispatch/worker/task.py", line 90, in perform_work
    result = self.run_callable(body)
  File "/awx_devel/awx/main/dispatch/worker/task.py", line 65, in run_callable
    return _call(*args, **kwargs)
  File "/awx_devel/awx/main/tasks.py", line 759, in _wrapped
    return f(self, *args, **kwargs)
  File "/awx_devel/awx/main/tasks.py", line 1264, in run
    self.instance = self.update_model(self.instance.pk, execution_environment=self.instance.resolve_execution_environment())
  File "/awx_devel/awx/main/models/mixins.py", line 477, in resolve_execution_environment
    if wf_template.execution_environment is not None:
AttributeError: 'NoneType' object has no attribute 'execution_environment'

that is fixed with this, at least for my one simple test case
This left jobs hanging out in "waiting" status, which is really not good.

Reviewed-by: Jeff Bradberry <None>
2021-06-03 21:02:01 +00:00
softwarefactory-project-zuul[bot]
e342919735 Merge pull request #10323 from wenottingham/look-over-there
Add additional controller directory for collections for inventory update

SUMMARY
This may be present in some scenarios with additional collections for inventory usage.

Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-06-03 20:42:04 +00:00
Jeff Bradberry
d0991bab9e Expose the EE resolver to the job template detail API endpoints 2021-06-03 16:35:50 -04:00
Alan Rominger
efcbea1fc5 Skip sliced jobs from the workflow EE logic 2021-06-03 16:20:47 -04:00
Alex Corey
1537b84ec8 adds more filters to dashboard chart 2021-06-03 15:31:43 -04:00
softwarefactory-project-zuul[bot]
30b7535ca2 Merge pull request #10348 from rooftopcellist/container_groups_error
Fix error msg wording and sdb docs

SUMMARY

Fixes wording in container groups error message
Updates ports for sdb debugging docs

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-03 19:02:34 +00:00
Christian M. Adams
fe02c0b157 Fix error msg wording and sdb docs 2021-06-03 14:24:18 -04:00
mabashian
177901eca6 Adds assertion to ensure that only one chip is shown when a checkbox list item is selected 2021-06-03 14:01:04 -04:00
mabashian
c2c93e7a66 Fix unit test failures 2021-06-03 13:50:26 -04:00
Bill Nottingham
00e60d2698 Add additional controller directory for collections for inventory update 2021-06-03 13:26:23 -04:00
Jake McDermott
ec1408fbd1 Disable cancel button on http 405
When a 405 is received, it means the job is already cancelled. Treat the
request as a success and don't show an error modal.

We disable the button to handle a rare scenario where we receive the 405 long before
the job status is properly updated to "cancelled" over websockets. We want to prevent
more cancel requests when this happens. We're disabling instead of hiding the button
because, assuming the status hasn't changed over sockets, the buttons that usually
replace the cancel button on the toolbar won't be shown yet and we don't want to
needlessly flicker and shift button positions around by rapidly loading and unloading
a different number of buttons onto the bar.
2021-06-03 13:02:03 -04:00
softwarefactory-project-zuul[bot]
23c3e62211 Merge pull request #10345 from sarabrajsingh/bugfix/bump-ansible-runner-version
updated ansible-runner version from 2.0.0a2 -> 2.0.0a4 in requirement…

SUMMARY
version bump (ansible-runner 2.0.0a2 -> 2.0.0a4)
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

AWX VERSION

awx: 19.2.0

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-03 16:49:38 +00:00
Sarabraj Singh
383c2bba58 updated ansible-runner version from 2.0.0a2 -> 2.0.0a4 in requirements files 2021-06-03 11:53:57 -04:00
softwarefactory-project-zuul[bot]
8adb53b5a8 Merge pull request #10292 from mabashian/8824-role-modal
Fixes bug where user/team role add modal state is not cleared on close

SUMMARY
link #8824
I modeled these changes after the pattern that existed between ResourceAccessList and AddResourceRole.  The key to fixing this bug is that the component that renders the wizard needs to be unmounted when the wizard closes so that the state, etc get cleared out before the next time the wizard is opened.  In order to achieve that I needed to decouple the add button from the wizard.
The sort of weird part of this pattern (and this exists in the ResourceAccessList as well) is error handling.  We pass the error back and set that to state before rendering the modal which isn't quite as clean as having the request made out at the list level and leveraging our hooks for error handling but I decided to just get in and get out and not worry about trying to refactor too much.
Here it is in action:

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
2021-06-03 15:52:40 +00:00
softwarefactory-project-zuul[bot]
92401e5328 Merge pull request #10301 from kdelee/unqualified_images
Force fully qualified image names

If we try and pull an unqualified image name, jobs hang on a podman
prompt.
I set the permissions as 644 because thats what worked for me because rootless podman needs to be able to read the file, but maybe there is another way to achieve that

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-06-03 15:45:24 +00:00
softwarefactory-project-zuul[bot]
d360fb212e Merge pull request #10258 from kdelee/ee_singular_awx_cli
allow singular execution_environment for cli

this makes "execution_environments" or "execution_environment" work
which is helpful
Now these both work:
awx execution_environments create --name foobar --image quay.io/ansible/awx-ee:latest

awx execution_environment create --name foobar1 --image quay.io/ansible/awx-ee:latest

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Jeff Bradberry <None>
2021-06-03 14:11:27 +00:00
mabashian
4c1b0297e7 Fixes bug where checkbox list item was selecting things twice 2021-06-03 09:48:20 -04:00
softwarefactory-project-zuul[bot]
a0b14b994d Merge pull request #8763 from wenottingham/licenses-to-kill
Restore UI license checker

27219d3 removed the license checker for UI dependencies as part of removing the UI. We actually still need it, just pointed at the new UI.
This brings it back, and updates it to do so. It also removes no longer needed license files.
It doesn't pass yet, as I haven't added licenses for the new UI dependencies in this PR. Hi @jakemcdermott.

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-06-02 23:48:52 +00:00
softwarefactory-project-zuul[bot]
168c022d3e Merge pull request #10329 from keithjgrant/6853-select-all-quirks
Clear list selections on pagination/search/sort

SUMMARY
Updates nearly every list* so that URL param changes (pagination, search, or sort) clear the selection. This prevents the list of selected items in state from including items that may no longer appear on screen — preventing the user from accidentally deleting or otherwise altering an item they may not realize they still have selected.
This also updates the useSelected hook to provide selectAll and clearSelected functions. Any lists that weren't yet already using this hook have been updated to do so.
Addresses #6853 and #7509
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

ADDITIONAL INFORMATION
*Lists that do not include this change are modals where the user is expected to paginate through screens and make several selections along the way (e.g. Multi Credential select modal), and lists that still use PaginatedDataList and are yet to be converted to PaginatedTable
Note: I originally wanted to make the clearSelected prop on PaginatedTable required, so any lists that don't have this fix applied would fail loudly. Unfortunately that wasn't possible, as there were a few lists that should not have this behavior, so I had to leave it as an optional prop.

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-06-02 23:11:41 +00:00
Shane McDonald
5adfacba64 Merge pull request #10321 from kdelee/management_cmd_ee_creds
Create default EE in seperate awx-managment cmd
2021-06-02 18:37:52 -04:00
Shane McDonald
52eeace20f Register default EEs when booting dev env 2021-06-02 18:19:41 -04:00
Keith J. Grant
21ff1d714d add useSelected tests for new functions 2021-06-02 14:48:53 -07:00
Keith J. Grant
eeca5512be update remaining lists to clear selection on pagination/search/sort 2021-06-02 14:41:20 -07:00
Keith J. Grant
143a4a61b3 clear list selection on navigate (first batch) 2021-06-02 14:41:20 -07:00
softwarefactory-project-zuul[bot]
fef24355ab Merge pull request #9908 from marshmalien/session-work
Add Session context and redirects

SUMMARY
Issues:
#8272 #9197 #8155 #9311

When user is logged out due to inactivity, redirect to the Login Page with a warning alert stating that their session expired.
When a user logs in on one tab, redirect from login page to home on the other tabs.
Clear session state when it expires and/or when a user logs out.
Redirect users to direct link destination after authentication

@AlexSCorey is looking at possibly rolling #9915 (SSO login redirect override URL is not working) into this PR
ISSUE TYPE


Feature Pull Request

COMPONENT NAME


UI

Reviewed-by: Kersom <None>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Marliana Lara <marliana.lara@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-02 21:17:47 +00:00
softwarefactory-project-zuul[bot]
d70dfec6b6 Merge pull request #10215 from keithjgrant/9218-sort-in-modal
fix namespaced url params

SUMMARY
Fixes issues when multiple lists are on the page (generally only occurs now when on a list page with an open modal that contains a second list) — Navigating within the modal list currently wipes out URL parameters for the main list, causing the page to reload, which closes the modal. The fix prevents changes to one set of namespaced URL parameters from wiping out URL parameters from another namespace

Refactors query string utils to consolidate a lot of repeated logic from components into a new util, updateQueryString. Use this function to modify query string parameters while maintaining params for multiple namespaces at the same time.
QS utils that are no longer needed have been deleted: replaceParams and encodeNonDefaultQueryString

Addresses #10181 and #9218
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: John Mitchell <None>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
2021-06-02 21:01:49 +00:00
softwarefactory-project-zuul[bot]
49eccfb19f Merge pull request #10335 from mabashian/10129-multi-choice-survey
Properly validate multiple choice survey questions

SUMMARY
link #10129
In action:

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
2021-06-02 20:41:20 +00:00
Shane McDonald
223c5bdaf6 Tweaks to register_default_execution_environments command
- The credential will always be updated. I dont think we want to decrypt the password here for comparison
- Preserve newlines in help text
2021-06-02 16:26:58 -04:00
Elijah DeLee
e740cfcb52 revert change to serializer and use get_or_create
still need to fix up the handling of the verify-ssl bool, since
it is not being respected
2021-06-02 16:16:36 -04:00
softwarefactory-project-zuul[bot]
65b03174ea Merge pull request #10304 from akus062381/add-ouia-to-yaml-jason-buttons
Adds ouiaId to YAML and JSON buttons in Variables Detail

small change to add a better locator to these buttons. if we do not do this, our locators for our visual tests are not good and will eventually break tests

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-06-02 19:51:31 +00:00
mabashian
134d84ded9 Adds unique ouiaId to MultiButtonToggle 2021-06-02 14:48:37 -04:00
akus062381
5707d65d0f fix 2021-06-02 14:48:10 -04:00
akus062381
9956538224 yay 2021-06-02 14:48:10 -04:00
Elijah DeLee
7818b2008f Allow modifications of managed_by_tower creds
Sysadmins may need to modify managed_by_tower credentials, the
only known case of which is a default container registry credential
for use by the default execution environments, which are also managed_by_tower
and allow modifications.
2021-06-02 13:05:02 -04:00
Elijah DeLee
043aff6a8c Create default EE in seperate awx-managment cmd
Create EE at a seperate time and also attach a registry credential if
auth information provided

This command can be run multiple times on the same instance and should be
idempotent.
2021-06-02 12:23:01 -04:00
softwarefactory-project-zuul[bot]
7725c6f18f Merge pull request #10305 from jbradberry/resolve-workflow-ee
Include the EE set on a workflow template in the resolver hierarchy

SUMMARY
This step comes immediately after checking the actual job/template for
an explicitly set EE.
Note that now, because of how jobs are spawned off of workflow nodes,
the call to .resolve_execution_environment() no longer happens in
.create_unified_job().  The job instance within .create_unified_job()
doesn't yet have access to the node that it will be attached to,
making it impossible to use this information in the resolver if called
there.
related #9560
ISSUE TYPE


Feature Pull Request
Bugfix Pull Request

COMPONENT NAME

API

AWX VERSION

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-06-02 16:22:39 +00:00
mabashian
16a3f7c2df Properly validate multiple choice survey questions 2021-06-02 10:38:11 -04:00
softwarefactory-project-zuul[bot]
896d895934 Merge pull request #10326 from chrismeyersfsu/fix-iso_path_sharing
when sharing paths use little z

AWX_ISOLATION_SHOW_PATHS will be shared between containers. Strange
file not found error can crop up when concurrently accessing shared
directories between multiple containers that are bind mounted with big
Z. So make sure we use little z.

Fixes errors like below:
fatal: [localhost]: FAILED! => {"changed": false, "cmd": "/usr/bin/git ls-remote file:///opt/tmpawx/at_DrunkMail525450112299457413919634186288881628802211907645041298254_test/ -h refs/heads/HEAD", "msg": "fatal: '/opt/tmpawx/at_DrunkMail525450112299457413919634186288881628802211907645041298254_test/' does not appear to be a git repository\\nfatal: Could not read from remote repository.\\n\\nPlease make sure you have the correct access rights\\nand the repository exists.", "rc": 128, "stderr": "fatal: '/opt/tmpawx/at_DrunkMail525450112299457413919634186288881628802211907645041298254_test/' does not appear to be a git repository\\nfatal: Could not read from remote repository.\\n\\nPlease make sure you have the correct access rights\\nand the repository exists.\\n", "stderr_lines": ["fatal: '/opt/tmpawx/at_DrunkMail525450112299457413919634186288881628802211907645041298254_test/' does not appear to be a git repository", "fatal: Could not read from remote repository.", "", "Please make sure you have the correct access rights", "and the repository exists."], "stdout": "", "stdout_lines": []}```

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-01 19:55:14 +00:00
Chris Meyers
067e6a5163 when sharing paths use little z
* AWX_ISOLATION_SHOW_PATHS will be shared between containers. Strange
file not found error can crop up when concurrently accessing shared
directories between multiple containers that are bind mounted with big
Z. So make sure we use little z.
2021-06-01 15:11:25 -04:00
Marliana Lara
92f567539f Update .po strings 2021-06-01 14:43:11 -04:00
Marliana Lara
951f6d4636 Redirect user after authenticating through social auth 2021-06-01 13:28:33 -04:00
Marliana Lara
811fa514d2 Remove useMemo from session context 2021-06-01 13:28:33 -04:00
Marliana Lara
a097602d7f Add Session context and redirect on auth 2021-06-01 13:28:29 -04:00
softwarefactory-project-zuul[bot]
a286324ab7 Merge pull request #10313 from YoungjuWang/patch-1
Update README.md

SUMMARY
Guide for running docker-compose with detached mode
ISSUE TYPE


Docs Pull Request

AWX VERSION

19.1.0

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-06-01 16:16:08 +00:00
Shane McDonald
64bd49da16 Delete dependabot.yml 2021-06-01 09:19:33 -04:00
softwarefactory-project-zuul[bot]
5622bf1a0a Merge pull request #10260 from mabashian/8249-resource-name-launch
Adds resource name and description to launch and schedule prompt wizards

SUMMARY
link #8249
link #7254
Launch with description:

Launch without description:

ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Kersom <None>
Reviewed-by: Michael Abashian <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-06-01 13:14:37 +00:00
softwarefactory-project-zuul[bot]
862f40a643 Merge pull request #10320 from shanemcd/bump-19.2.0
Bump version and update for 19.2.0

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-06-01 12:59:22 +00:00
softwarefactory-project-zuul[bot]
41e3a69001 Merge pull request #10225 from AlanCoding/deletions
Remove code and settings no longer used

Connect #8740

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-06-01 12:42:32 +00:00
Shane McDonald
cabc60792b Bump version and update for 19.2.0 2021-06-01 08:18:21 -04:00
왕영주 (Youngju Wang)
eb305edafd Update README.md
How to run docker-compose with '-d' option
2021-05-31 17:49:43 +09:00
Keith J. Grant
e6cfd726c6 don't reload host if query string changes 2021-05-27 13:22:47 -07:00
mabashian
ec78f5a9ec Add name/description to mock resources in tests 2021-05-27 16:18:03 -04:00
mabashian
d711a9aed3 Mark string for translation 2021-05-27 16:11:19 -04:00
mabashian
4836a5b1a9 Extract strings 2021-05-27 15:57:00 -04:00
softwarefactory-project-zuul[bot]
57b093aa2a Merge pull request #10294 from kdelee/clarify_help_msg
clarify format of date for host_metric

SUMMARY


@amolgautam25 @AlanCoding let me know what you think -- I was taking a second look at the CLI and took me a bit to remember the format it wants is YYYY-MM-DD

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Amol Gautam <amol_gautam25@yahoo.co.in>
2021-05-27 19:26:48 +00:00
Jeff Bradberry
d3cc439fa8 Include the EE set on a workflow template in the resolver hierarchy
This step comes immediately after checking the actual job/template for
an explicitly set EE.

Note that now, because of how jobs are spawned off of workflow nodes,
the call to .resolve_execution_environment() no longer happens in
.create_unified_job().  The job instance within .create_unified_job()
doesn't yet have access to the node that it will be attached to,
making it impossible to use this information in the resolver if called
there.
2021-05-27 15:22:44 -04:00
softwarefactory-project-zuul[bot]
fabc67eeb3 Merge pull request #10279 from mabashian/8852-checkbox-list-item
Fixes bug where users were unable to click on text next to checkboxes/radios in modals

SUMMARY
link #8852
This should impact lists in modals where the user can select one or more of the rows.  They should now be able to click on the text/row in order to select.  Examples:

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-27 19:06:50 +00:00
softwarefactory-project-zuul[bot]
c29a7ccf8b Merge pull request #10102 from jbradberry/disable-local-users
Add the ability to disable local authentication

SUMMARY
When an external authentication system is enabled, users would like the ability to disable local authentication for enhanced security.
related #4553
TODO

 create a configure-Tower-in-Tower setting,  DISABLE_LOCAL_AUTH
 expose the setting in the settings UI
 be able to query out all local-only users

User.objects.filter(Q(profile__isnull=True) | Q(profile__ldap_dn=''), enterprise_auth__isnull=True, social_auth__isnull=True)
see: awx/main/utils/common.py, get_external_account


 write a thin wrapper around the Django model-based auth backend
 update the UI tests to include the new setting
 be able to trigger a side-effect when this setting changes
 revoke all OAuth2 tokens for users that do not have a remote
auth backend associated with them
 revoke sessions for local-only users

ultimately I did this by adding a new middleware that checks the value of this new setting and force-logouts any local-only user making a request after it is enabled


 settings API endpoint raises a validation error if there are no external users or auth sources configured

The remote user existence validation has been removed, since ultimately we can't know for sure if a sysadmin-level user will still have access to the UI.  This is being dealt with by using a confirmation modal, see below.


 add a modal asking the user to confirm that they want to turn this setting on

ISSUE TYPE


Feature Pull Request

COMPONENT NAME


API
UI

AWX VERSION

Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Mat Wilson <mawilson@redhat.com>
Reviewed-by: Michael Abashian <None>
Reviewed-by: Chris Meyers <None>
2021-05-27 18:37:47 +00:00
mabashian
af162b6897 Use expandable section when description is longer than 512 characters to avoid making the wizard unusably long 2021-05-27 14:28:54 -04:00
softwarefactory-project-zuul[bot]
dd269804fd Merge pull request #10234 from rooftopcellist/rm_eula_acceptance
Remove explicit eula acceptance

SUMMARY
Issue: ansible/tower#4948
This PR changes the entitlement process to no require explicit acceptance of the Eula, but still display it for the user to read.
ISSUE TYPE


Feature Pull Request

COMPONENT NAME


API
UI

AWX VERSION

19.1.0

ADDITIONAL INFO
If the eula_accepted field is passed, it will just be ignored.

Reviewed-by: Bill Nottingham <None>
2021-05-27 17:54:21 +00:00
mabashian
ad5cc3a393 Adds click event to table row to handle selecting/unselecting checkbox/radio 2021-05-27 12:23:03 -04:00
mabashian
50de068a02 Refactor functions that check typed text in lookups 2021-05-27 11:09:06 -04:00
Elijah DeLee
5d838b8980 Force fully qualified image names
If we try and pull an unqualified image name, jobs hang on a podman
prompt.
2021-05-27 10:59:25 -04:00
mabashian
4ec7ba0107 Adds support for typing values into single select lookups 2021-05-27 10:53:36 -04:00
mabashian
fa7a459e50 Fixes bug where user/team role add modal state is not cleared on close 2021-05-27 10:51:46 -04:00
mabashian
4b4e57889e Remove unused disabled prop 2021-05-27 10:50:11 -04:00
mabashian
f4ba87ea4f Fixes bug where users were unable to click on text next to checkboxes in modals 2021-05-27 10:47:31 -04:00
mabashian
dc64da6f72 Adds resource name and description to launch and schedule prompt wizards 2021-05-27 10:45:38 -04:00
softwarefactory-project-zuul[bot]
4e129d3d04 Merge pull request #10295 from wenottingham/nope--not-there-anymore
Move irc references to point to irc.libera.chat

c.f. ansible-community/community-topics#19 (comment)

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Matthew Jones <bsdmatburt@gmail.com>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-27 13:59:06 +00:00
softwarefactory-project-zuul[bot]
7542ebda48 Merge pull request #10293 from tchellomello/awx-doc
Redirect documentation to awx-operator docs

SUMMARY
CC: @shanemcd
Related: ansible/awx-operator#330
The PR ansible/awx-operator#330 enhances the AWX installation process via the awx-operator.
This PR redirects the installation notes to the awx-operator page so we can simplify and easy maintain the docs in one place.
ISSUE TYPE


Docs Pull Request

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-27 13:59:01 +00:00
mabashian
ff559a81db Remove eula checkbox from UI 2021-05-27 09:26:33 -04:00
Christian M. Adams
909cdc2425 Remove explicit eula acceptance 2021-05-27 09:26:32 -04:00
Bill Nottingham
8b183b5f5d Move irc references to point to irc.libera.chat
c.f. https://github.com/ansible-community/community-topics/issues/19#issuecomment-849071636
2021-05-27 00:36:30 -04:00
softwarefactory-project-zuul[bot]
da13196e59 Merge pull request #10278 from nixocio/ui_de_explanation
Update message about Default Execution Environment

Update message about Default Execution Environment
Organizations

Projects

See: #9715

Reviewed-by: Bill Nottingham <None>
Reviewed-by: Kersom <None>
2021-05-26 21:55:40 +00:00
Marcelo Moreira de Mello
d333b0080f Redirect documentation to awx-operator docs 2021-05-26 17:34:47 -04:00
Elijah DeLee
75de8a30f6 clarify format of date for host_metric 2021-05-26 17:31:11 -04:00
nixocio
3e2affb08e Update message about Default Execution Environment
Update message about Default Execution Environment

See: https://github.com/ansible/awx/issues/9715
2021-05-26 17:11:08 -04:00
softwarefactory-project-zuul[bot]
42dbd4ea73 Merge pull request #10289 from rooftopcellist/container-group-typo
The list secrets role rule is no longer not needed for container groups

SUMMARY
The list secrets role rule is no longer not needed for container groups.  This was simplified to just get the single matching secret using the read_namespaced_secret() method.

Reviewed-by: Seth Foster <None>
2021-05-26 19:18:07 +00:00
Christian M. Adams
36f47f3696 The list secrets role rule is no longer not needed for container groups 2021-05-26 14:38:56 -04:00
softwarefactory-project-zuul[bot]
c4eceb0915 Merge pull request #10180 from AlexSCorey/10162-ConvertOptionsList
Converts Options lists and other modal lists to tables

SUMMARY
This addresses #10162.  Note this issue I found while working on this #10181
Kicked Off E2E
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-26 15:11:46 +00:00
softwarefactory-project-zuul[bot]
a8b2b5892c Merge pull request #10267 from mabashian/10138-activity-stream
Fixes bug where activity stream changes were displaying as [object object]

SUMMARY
Resolves #10138
Here it is working:

In this case the value passed to the VariablesDetail component is a straight up JSON object (not a stringified JSON object) which that component does not seem to like in its current state.
Rather than looking at changing the VariablesDetail implementation I decided to just stringify the object before it gets passed in.  Since this object is generated by the backend I think it's safe to assume it will always be an object.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-26 15:01:23 +00:00
softwarefactory-project-zuul[bot]
f0129c857b Merge pull request #10271 from beeankha/galaxy_cred_export_bug
Enable Export of Galaxy Credentials Associated to Organizations

SUMMARY

Addresses #9342

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.1.0

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
2021-05-26 14:55:19 +00:00
softwarefactory-project-zuul[bot]
66789fa713 Merge pull request #10268 from wenottingham/branding-take-2
Update branding to match guidelines

SUMMARY
Name of product feature is Insights for AAP.

Reviewed-by: Michael Abashian <None>
2021-05-25 22:14:02 +00:00
softwarefactory-project-zuul[bot]
82a585dbe2 Merge pull request #10269 from nixocio/ui_migration_issue
Update migration page as per latest name changes

Update migration page as per latest name changes

  
    
    

    rename.mov
    
  

  

  


See: #8355

Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-05-25 21:44:54 +00:00
softwarefactory-project-zuul[bot]
2b4732f07b Merge pull request #10204 from rooftopcellist/container-groups-registry-creds
Container groups registry creds

SUMMARY
Fixes #10114
In VM-based installs, the user provides image pull creds to us, then we put them in an authfile and give it to podman via --authfile.
This is not so simple with ContainerGroups because we need to use the k8s API to apply a podspec to create containers in this paradigm.
Currently, the EE pod gets created, but errors when pulling the custom EE in from the private repo:

This work will modify the init() for the AWXReceptorJob class to create a k8s secret in the given namespace, then specify that secret name in the pod-spec as an imagePullSecret
Also, the imagePullPolicy was not being enforced when running JT's in EE's using container groups, this is because the imagePullPolicy nevery got set on the pod spec.
ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

devel

  
    
    

    
    

  


ADDITIONAL INFORMATION
Issues that this solves:

Image pull secret now gets created in the cluster namespace specified by the user for that container group.
imagePullSecret name gets set on the pod spec
If the pull secret already exists in the namespace, delete it, then create it.  (kube_api.replace_namespaced_secret did not work for this case...)
Enforce imagePullPolicy for EE's in container groups
Basic error handling

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Chris Meyers <None>
2021-05-25 21:03:44 +00:00
beeankha
02cd646b44 Update awxkit to enable export of Galaxy credentials associated to organizations 2021-05-25 16:52:54 -04:00
Bill Nottingham
c9ac18db24 Update branding to match guidelines 2021-05-25 16:25:34 -04:00
nixocio
5e369dc9e2 Update migration page as per latest name changes
Update migration page as per latest name changes

See: https://github.com/ansible/awx/issues/8355
2021-05-25 16:18:00 -04:00
mabashian
e0e66e3818 Fixes bug where activity stream changes were displaying as [object object] 2021-05-25 15:23:15 -04:00
Alex Corey
0a276a6276 resolves some poor styling on some lists 2021-05-25 15:21:01 -04:00
Christian M. Adams
536c02dc55 Simplify hostname parsing 2021-05-25 15:19:40 -04:00
Christian M. Adams
d607dfd5d8 Added error handling for pull secret creation requests
- Check (only) the existing secret to see if it's value would change.
2021-05-25 14:58:01 -04:00
softwarefactory-project-zuul[bot]
d2d62adcb9 Merge pull request #10248 from AlexSCorey/updatedPF
Updates PF

SUMMARY
This is a dependency bump for PF so that I can get an update that fixes a validation bug in pf date picker.
E2E test have been triggered
ISSUE TYPE
dep bump
COMPONENT NAME

UI

AWX VERSION



ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-25 18:57:55 +00:00
Christian M. Adams
cea6d8c3cb Use utf-8 & properly parse hostname from registry URL 2021-05-25 14:44:42 -04:00
Christian M. Adams
8316a1d198 Create pull secret in cluster and use it in PodSpec
- base64 encode secret values before creating the secret
  - Construct valid .dockerconfigjson
  - Cancel jobs where it will obviously fail & error handling
  - Check if the secret exists first, then attempts to replace it if it does.
2021-05-25 14:44:42 -04:00
Christian M. Adams
a0840ddec2 Enforce EE pull policy on Container Groups 2021-05-25 14:44:41 -04:00
softwarefactory-project-zuul[bot]
e28bed5a6c Merge pull request #9904 from MaximilianMeister/approval-docs
Document usage of workflow job template nodes with approvals

SUMMARY

I'm not sure if this procedure is mandatory, but it was the only way it worked for me.
It's already documented in one sentence that you can create all workflow template nodes first and then link them later. However in the Examples it has been missing to make it explicit, as it's not really intuitive when you create the nodes and link them at the same time, it won't work and you run into #8777
ISSUE TYPE


Docs Pull Request

AWX VERSION

awx: 19.0.0

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Maximilian Meister <None>
Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-05-25 17:22:08 +00:00
softwarefactory-project-zuul[bot]
25bb3fbd59 Merge pull request #10261 from shanemcd/bump-receptor
Bump receptor and receptorctl

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Yanis Guenane <None>
2021-05-25 17:09:30 +00:00
softwarefactory-project-zuul[bot]
f2cd630a90 Merge pull request #10251 from kdelee/options_ee
tweak message about image pull option

SUMMARY

I'm not sure if it is OK to change the migration in this way.
This message in the UI didn't make sense to me. If you all prefer the existing message, that is fine...I just think it is weird and doesn't tell you what it does.
If I don't care, I can leave it on --------- in the UI which is "do whatever the default is"
If I do care, its weird to choose an option saying I don't choose and option.

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Jeff Bradberry <None>
2021-05-25 16:19:41 +00:00
Shane McDonald
63d702d1aa Bump receptor and receptorctl 2021-05-25 11:58:10 -04:00
Elijah DeLee
b74990c480 allow singular execution_environment for cli
this makes "execution_environments" or "execution_environment" work
which is helpful
2021-05-25 11:28:47 -04:00
softwarefactory-project-zuul[bot]
d6c5a23e05 Merge pull request #10239 from mabashian/disable-pendo
Only initialize pendo if the key is available

SUMMARY
Don't bootstrap/init pendo if the key is missing or empty string

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-25 12:46:51 +00:00
mabashian
dd1bda3b67 Fix broken app container test 2021-05-25 08:06:06 -04:00
mabashian
82c3348b15 Only initialize pendo if the key is available 2021-05-24 17:34:00 -04:00
Elijah DeLee
058189dfcf tweak message about image pull option 2021-05-24 17:20:53 -04:00
softwarefactory-project-zuul[bot]
e2140ad7a8 Merge pull request #10250 from tiagodread/locators-screens
Add locators to screen page titles

Adds locators around the screen title so that we can use it in e2e tests.

Reviewed-by: Kersom <None>
2021-05-24 20:30:58 +00:00
softwarefactory-project-zuul[bot]
fedc40d578 Merge pull request #10230 from amolgautam25/issue_315_receptor
Adding AWX_CONTAINER_GROUP_POD_LAUNCH_TIMEOUT in defaults.py

--- Adding a new global variable AWX_CONTAINER_GROUP_POD_LAUNCH_TIMEOUT in defaults.py
--- Passing this parameter in receptor_params in AWXReceptorJob class
SUMMARY

Related issue : ansible/receptor#315
Corresponding PR on receptor side : ansible/receptor#316
I have added a global variable AWX_CONTAINER_GROUP_POD_LAUNCH_TIMEOUT  ( and set default value as 5 minutes ).
This will be passed onto Receptor in case a job is container group task.

ISSUE TYPE


Feature Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.1.0

ADDITIONAL INFORMATION




File Name : awx/main/tasks.py
Class Name : AWXReceptorJob
Function name: receptor_params(self)
Before the change the value of receptor_params before returning was :
{'secret_kube_config': '---\n'
                       'apiVersion: v1\n'
                       'clusters:\n'
                       '- cluster:\n'
                       '    insecure-skip-tls-verify: true\n'
                       '    server: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       '  name: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       'contexts:\n'
                       '- context:\n'
                       '    cluster: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       '    namespace: default\n'
                       '    user: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       '  name: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       'current-context: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       'kind: Config\n'
                       'preferences: {}\n'
                       'users:\n'
                       '- name: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       '  user:\n'
                       '    token: '
                       'sha256~otM0Z2vC8qfzm3eV0tfz-0V4DXKPqLC_Pp1gxXKuC-c\n',
 'secret_kube_pod': '---\n'
                    'apiVersion: v1\n'
                    'kind: Pod\n'
                    'metadata:\n'
                    '  labels:\n'
                    '    ansible-awx: 04366fdb-65ec-4efc-bb01-685e9ca7e05b\n'
                    "    ansible-awx-job-id: '21'\n"
                    '  name: automation-job-21\n'
                    '  namespace: default\n'
                    'spec:\n'
                    '  containers:\n'
                    '  - args:\n'
                    '    - ansible-runner\n'
                    '    - worker\n'
                    '    - --private-data-dir=/runner\n'
                    '    image: quay.io/ansible/awx-ee:0.2.0\n'
                    '    name: worker\n'}
>>>

After the change the value of receptor_params before returning is :
{'pod_pending_timeout': '5m',
 'secret_kube_config': '---\n'
                       'apiVersion: v1\n'
                       'clusters:\n'
                       '- cluster:\n'
                       '    insecure-skip-tls-verify: true\n'
                       '    server: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       '  name: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       'contexts:\n'
                       '- context:\n'
                       '    cluster: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       '    namespace: default\n'
                       '    user: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       '  name: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       'current-context: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       'kind: Config\n'
                       'preferences: {}\n'
                       'users:\n'
                       '- name: '
                       'https://api.tower.ocp4.testing.ansible.com:6443\n'
                       '  user:\n'
                       '    token: '
                       'sha256~otM0Z2vC8qfzm3eV0tfz-0V4DXKPqLC_Pp1gxXKuC-c\n',
 'secret_kube_pod': '---\n'
                    'apiVersion: v1\n'
                    'kind: Pod\n'
                    'metadata:\n'
                    '  labels:\n'
                    '    ansible-awx: 04366fdb-65ec-4efc-bb01-685e9ca7e05b\n'
                    "    ansible-awx-job-id: '21'\n"
                    '  name: automation-job-21\n'
                    '  namespace: default\n'
                    'spec:\n'
                    '  containers:\n'
                    '  - args:\n'
                    '    - ansible-runner\n'
                    '    - worker\n'
                    '    - --private-data-dir=/runner\n'
                    '    image: quay.io/ansible/awx-ee:0.2.0\n'
                    '    name: worker\n'}
>>>

We can see that an extra parameter has been added : 'pod_pending_timeout': '5m',
####Additional changes :
--- Removed AWX_CONTAINER_GROUP_POD_LAUNCH_RETRIES from defaults.py as it was not being used anywhere
--- Removed AWX_CONTAINER_GROUP_POD_LAUNCH_RETRY_DELAY from defaults.py as it was not being used anywhere

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Amol Gautam <amol_gautam25@yahoo.co.in>
Reviewed-by: Seth Foster <None>
2021-05-24 20:05:52 +00:00
Tiago
aeed2e0128 add locators to screen page titles 2021-05-24 16:22:38 -03:00
fedora
0c917caa2a --- Adding AWX_CONTAINER_GROUP_POD_LAUNCH_TIMEOUT in defaults.py
--- Passing this parameter in receptor_params in AWXReceptorJob class
--- Removed AWX_CONTAINER_GROUP_POD_LAUNCH_RETRIES from defaults.py as it was not being used anywhere
--- Removed AWX_CONTAINER_GROUP_POD_LAUNCH_RETRY_DELAY from defaults.py as it was not being used anywhere
2021-05-24 11:33:01 -04:00
Alex Corey
4fe4856d02 updates patternfly react core so that we can get time picker validation bug fix 2021-05-24 10:57:50 -04:00
Alan Rominger
cb1df4a334 Remove code and settings no longer used 2021-05-24 09:44:58 -04:00
Alex Corey
c456b944a5 Converts all Lists inside a modal, mostly components that use OptionsList, to paginated tables 2021-05-24 09:08:06 -04:00
Bill Nottingham
6d052fdab4 UI licenses 2021-05-21 16:25:55 -04:00
softwarefactory-project-zuul[bot]
7801590bef Merge pull request #10245 from tiagodread/add-testability
Add testability to the search and pagination fields

Add locators to search fields
See: #10241

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-05-21 17:26:27 +00:00
Tiago
d834afd541 Pagination 2021-05-21 12:40:42 -03:00
Tiago
34ac60b35c Search and AdvancedSearch 2021-05-21 12:31:55 -03:00
Bill Nottingham
51538b7688 Restore UI license checker removed as part of removing old UI
Remove no longer needed license files.
2021-05-21 00:37:11 -04:00
softwarefactory-project-zuul[bot]
b771929b6e Merge pull request #10195 from nixocio/ui_issue_9377
Fix null issue for limit

Fix null issue for limit.
See: #9377

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-05-20 21:33:48 +00:00
softwarefactory-project-zuul[bot]
a25eec5cfa Merge pull request #9654 from amolgautam25/issue_4687
Adding host_metrics for customers who don't have automation analytics

SUMMARY

I am trying to accomplish the following:

 Create a new model that stores details about hostname
 create corresponding migrations for it
 Update the table (main_hostmetrics) after playbook execution
 retrieve the data with custom awx-manage command :  awx-manage host_metrics --since <date> --until <date>


ISSUE TYPE


Feature Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 18.0.0


ADDITIONAL INFORMATION

Reviewed-by: Ryan Petrello <ryan@ryanpetrello.com>
Reviewed-by: Amol Gautam <amol_gautam25@yahoo.co.in>
Reviewed-by: Chris Meyers <None>
Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Bill Nottingham <None>
Reviewed-by: Ladislav Smola <lsmola@redhat.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-05-20 13:55:46 +00:00
Alex Corey
3b5641c41b adds confirmation modal to switch 2021-05-20 09:31:31 -04:00
Keith J. Grant
8ac3cc1542 delete qs utils that are no longer used 2021-05-19 13:49:57 -07:00
Keith J. Grant
908263df50 Rewrite updateQueryString to preserve namespaces
* Refactors ActivityStream to use updateQueryString
2021-05-19 13:23:46 -07:00
softwarefactory-project-zuul[bot]
68f214c2be Merge pull request #8185 from AlanCoding/sniff_files_final
Use inventory and env private_data_dir subfolders

SUMMARY
This is another part of trying to get AWX to follow ansible-runner best practices.
See docs:
https://ansible-runner.readthedocs.io/en/stable/intro.html#runner-input-directory-hierarchy
So what runner & people expect is:
.
├── env
│   ├── envvars
│   ├── extravars
│   ├── passwords
│   ├── cmdline
│   ├── settings
│   └── ssh_key
├── inventory
│   └── hosts
└── project
    ├── test.yml
    └── roles
        └── testrole
            ├── defaults
            ├── handlers
            ├── meta
            ├── README.md
            ├── tasks
            ├── tests
            └── vars

What we were producing was something more like
├── cp
├── env
│   ├── cmdline
│   ├── envvars
│   ├── extravars
│   ├── passwords
│   ├── settings
│   └── ssh_key
├── project
│   ├── ansible.cfg
│   ├── ansible_env.yml
│   ├── async_tasks.yml
<snip>
│   └── vault.yml
└── tmp3evnorsu

There was no inventory folder, and inventory was stored in tmp3evnorsu as a top-level file. Any credential files were also saved in that same structure.
With this change, it's more like:
├── cp
├── env
│   ├── cmdline
│   ├── envvars
│   ├── extravars
│   ├── passwords
│   └── settings
├── inventory
│   └── tmp94xjm0d7
└── project
    ├── ansible.cfg
    ├── ansible_env.yml
    ├── async_tasks.yml
<snip>
    └── vault.yml

and any credential files (starting with tmp) are dumped into the env folder.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

API

AWX VERSION
14.1.0

ADDITIONAL INFORMATION
The motivation for this is that ansible-runner may require specific mounts for every file of directory in the private_data_dir. As such, we really don't want randomized filenames in the top level directory. I don't know for sure this is the direction we are going to go, but this seems like a defensible change on its own, to better adhere to the practices someone familiar with ansible-runner would expect.

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Chris Meyers <None>
2021-05-19 17:24:33 +00:00
Jeff Bradberry
2aa3fe756e Remove the remote user existence validation
since we are going to do a confirmation modal dialog instead.
2021-05-19 10:27:51 -04:00
softwarefactory-project-zuul[bot]
20dd436ee9 Merge pull request #10226 from wenottingham/one-more
Rename one more Tower bit.

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-05-19 00:59:02 +00:00
Bill Nottingham
34f4dc521b Rename one more Tower bit. 2021-05-18 19:26:18 -04:00
softwarefactory-project-zuul[bot]
7e307a69ce Merge pull request #10217 from AlexSCorey/updatelingui
Updates LingUI Again

SUMMARY
This updates ling ui to bring in their latest release so that we don't have to run npm extract-strings every time we add/update a <Plural> or a string with a variable inside it.
ISSUE TYPE
-dependency upgrade
COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-05-18 22:01:55 +00:00
Keith J. Grant
7f6e022852 rename replaceNamespacedParams to updateQueryString 2021-05-18 14:15:26 -07:00
softwarefactory-project-zuul[bot]
282914e809 Merge pull request #10191 from chrismeyersfsu/fix-threading_tracebacks
close db and cache connection in new threads

It's not safe to share or re-use django db connections nor django cache connections across new threads nor processes.

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-18 19:41:58 +00:00
Keith J. Grant
d324c12348 add qs test confirming default values are omitted 2021-05-18 12:20:24 -07:00
Keith J. Grant
fd5e22a3f6 fix integer fields in removeParams; maintain page_size/sort 2021-05-18 12:00:20 -07:00
softwarefactory-project-zuul[bot]
7eaf1db3e0 Merge pull request #10206 from tchellomello/update_ee_via_operator
Commits settings.DEFAULT_EXECUTION_ENVIRONMENTS updates into the database

SUMMARY
Fixes: ansible/awx-operator#256
cc: @shanemcd
Cannot update execution environment version in place by updating the AWX spec via awx-operator.  For example, consider the scenario below:
spec:
  tower_ee_images:
    - image: registry.tatu.home/ansible/awx-ee:0.1.0
      name: My Custom Execution Environment

The expectation would be once you modify the AWX spec to the version below, the EE should reflect this change once the awx-operator finishes its reconciliation.
After:
spec:
  tower_ee_images:
    - image: registry.tatu.home/ansible/awx-ee:0.2.0
      name: My Custom Execution Environment

-- deployment got updated
- args:
        - receptor
        - --config
        - /etc/receptor.conf
        image: registry.tatu.home/ansible/awx-ee:0.2.0
        imagePullPolicy: IfNotPresent
        name: awx-devel-ee-ee
Besides the awx-operator updated the YAML deployment as expected, the change did not hit the database.
awx=# select * from main_executionenvironment;
 id |    created    |   modified    | description |     image      | managed_by_tower | created_by_id | credential_id | modified_by_id | organization_id |      name      | pull 
----+---------------+---------------+-------------+----------------+------------------+---------------+---------------+----------------+-----------------+----------------+------
  1 | 2021-05-11 15.| 2021-05-11 15.|             | registry.tatu..| t                |             1 |               |              1 |                 | My Custom Exec.| 
    |.:24:02.674302.|.:24:02.674327.|             |.home/ansible/a.|                  |               |               |                |                 |.ution Environm.| 
    |.+00           |.+00           |             |.wx-ee:0.1.0    |                  |               |               |                |                 |.ent            | 
(1 row)
ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

devel

ADDITIONAL INFORMATION


Quick proof of concept
>>> settings.DEFAULT_EXECUTION_ENVIRONMENTS
[{'name': 'My Custom Execution Environment', 'image': 'registry.tatu.home/ansible/awx-ee:0.2.0'}]
>>> [a.name for a in  ExecutionEnvironment.objects.all()]
['My Custom Execution Environment']
>>> [a.image for a in  ExecutionEnvironment.objects.all()]
['registry.tatu.home/ansible/awx-ee:0.2.0']

*** updating to new but keeping name 
>>> _, created = ExecutionEnvironment.objects.update_or_create(name='My Custom Execution Environment', defaults={'image': 'registry.tatu.home/ansible/awx-ee:0.3.0', 'managed_by_tower': True})
>>> [a.name for a in  ExecutionEnvironment.objects.all()]
['My Custom Execution Environment']
>>> [a.image for a in  ExecutionEnvironment.objects.all()]
['registry.tatu.home/ansible/awx-ee:0.3.0']

*** adding a new name
>>> _, created = ExecutionEnvironment.objects.update_or_create(name='My Custom Execution Environment2', defaults={'image': 'registry.tatu.home/ansible/awx-ee:0.3.0', 'managed_by_tower': True})
>>> [a.name for a in  ExecutionEnvironment.objects.all()]
['My Custom Execution Environment2', 'My Custom Execution Environment']
>>> [a.image for a in  ExecutionEnvironment.objects.all()]
['registry.tatu.home/ansible/awx-ee:0.3.0', 'registry.tatu.home/ansible/awx-ee:0.3.0']

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-18 18:36:07 +00:00
softwarefactory-project-zuul[bot]
1b1608cff9 Merge pull request #10221 from jbradberry/check-for-pre-commit-script
Add a check for the existence of pre-commit.sh

SUMMARY
so that you don't get stuck when working on branches that don't have this yet.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

AWX VERSION

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-05-18 18:33:54 +00:00
fedora
cb7b2289b7 Fixed Migration 2021-05-18 14:08:42 -04:00
fedora
c1ea489043 created a new model 'HostMetrics' which will contain the first timestamp and the most recent timestamp of any automation on a given object and Added a new 'awx-manage' command. command : awx-manage host_metrics --since <datetime> --until <datetime> 2021-05-18 13:56:45 -04:00
Jeff Bradberry
c887f84a05 Add a check for the existence of pre-commit.sh
so that you don't get stuck when working on branches that don't have this yet.
2021-05-18 13:20:55 -04:00
softwarefactory-project-zuul[bot]
fb7c827bff Merge pull request #10068 from wenottingham/fail-early-fail-often
Have the project update playbook warn if role/collection syncing is disabled

In recent AWX, a galaxy credential (even a blank one for galaxy.ansible.com) is required to sync role/collection content. This is done so that server precedence can be properly set, and so that it can be configured to pull only from a private content host.
This does lead to bug reports where the credentials are not set, and users don't understand why their content is not syncing. This makes that more clear.

Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-05-18 15:29:21 +00:00
Alex Corey
5f03768f5d updates ling ui so that we do not need to run npm extract-strings as often 2021-05-18 10:53:36 -04:00
softwarefactory-project-zuul[bot]
df3bd2e082 Merge pull request #10133 from mabashian/ui-next-pendo
Adds support for pendo initialization across the app

SUMMARY
We were already bootstrapping pendo as part of the subscription code I just moved that code to a more general place.  When the app container mounts (after login or on refresh) we check to see if the pendo flag is turned on.  If it is, we initialize pendo.  If it's not then we do nothing.  If a user goes into settings and manually changes the pendo tracking setting then we trigger a hard reload of the browser tab (to take the new setting into account and either initialize or not).  This functionality existed in the old UI as well.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

Reviewed-by: Michael Abashian <None>
Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-18 14:51:07 +00:00
softwarefactory-project-zuul[bot]
3d80eb30b3 Merge pull request #10209 from beeankha/fix_integration_tests
Fix failing integration test playbooks

SUMMARY

Addressing issue #10104

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


Collections

Reviewed-by: Seth Foster <None>
Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-05-18 14:13:25 +00:00
softwarefactory-project-zuul[bot]
5ad48bda6c Merge pull request #10203 from jakemcdermott/add-default-error-boundary
Add default error boundary around screens

SUMMARY
Catch any unhandled non-async errors with an error boundary around screens. This will show a generic error message instead
of crashing the page.
The react docs decently summarize the general concept of error boundaries. The example code is informative, but there appears to be a few more edge cases that need to be dealt with. Rather than re-implement solutions for those, I decided to pull in a simple and well-tested library.
ADDITIONAL INFORMATION
before

after

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-18 00:30:29 +00:00
softwarefactory-project-zuul[bot]
fd60105db3 Merge pull request #10005 from AlanCoding/force_on_override
Update with force option if branch_override

Addresses a reported issue where force-pushing to feature branches did not work.
Connect #9371 (comment)

Reviewed-by: Bill Nottingham <None>
2021-05-17 23:58:31 +00:00
Keith J. Grant
25903431bc refactor JobOutput to use replaceNamespacedParams util 2021-05-17 15:25:16 -07:00
Keith J. Grant
f8374def64 refactor ListHeader to use replaceNamespacedParams 2021-05-17 15:09:37 -07:00
beeankha
82807a1b20 Update ad hoc command cancel test 2021-05-17 16:46:01 -04:00
softwarefactory-project-zuul[bot]
61ae80819f Merge pull request #10212 from sarabrajsingh/bugfix/create-seperator-worker-thread-for-transmit-jobs-9952
created a TransmitterThread class to start transmit jobs within. Surr…

SUMMARY

Surfaced this bug while fixing issue #9952.
Receptor-ctl would hang trying to read from a socket pair that is never closed, when the transmit job was executed yet threw an exception. This anomaly occurred when using a k8s cluster (Openshift in our case) as the execution environment.
FYI - for now, this only applies to container groups.
We moved the transmit function to execute in its own thread, and rejoin the calling function (_run_internal) when it finishes transmitting, and bubbling up exceptions if any occurred in the thread.

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.1.0

ADDITIONAL INFORMATION

Steps to reproduce bug:

Create an ansible project with some files (or roles) and commit to a git repository
Purposely commit a broken symlink on any file in the project files to git
Create a credential set that authenticates to your k8s cluster in AWX
Create a container instance group that leverages the credentials from Step 3 in AWX
Create a project in AWX that leverages the ansible project/git repo from Step 1
Create a job template that leverages the AWX project from Step 4 and set your EE to the container instance group from Step 3
Execute the job from Step 5

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-17 20:16:12 +00:00
beeankha
62a9c74040 Fix failing integration test playbooks 2021-05-17 15:56:39 -04:00
softwarefactory-project-zuul[bot]
0e74f51aa3 Merge pull request #10134 from AlexSCorey/10132-RelatedGroupsCnverttoTables
converts inventory groups related groups and related hosts to tables

SUMMARY
This addresses #10132
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-05-17 19:07:57 +00:00
Keith J. Grant
9bbaa6993f refactor param changes to use new util function 2021-05-17 11:49:02 -07:00
softwarefactory-project-zuul[bot]
966eead93f Merge pull request #10121 from saito-hideki/issue/10104
Remove source_script from tower_inventory_source integration test

SUMMARY
source_script parameter is on longer available in the current version AWX API(#9822), so we need to remove it from the integration test of tower_inventory_source module

Fixes #10104

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

awx_collections

AWX VERSION
devel

  
    
    

    
    

  


ADDITIONAL INFORMATION
None

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Hideki Saito <saito@fgrep.org>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-05-17 18:46:24 +00:00
Sarabraj Singh
12cea1191e created a TransmitterThread class to start transmit jobs within. Surrounded ansible_runner.interface.run() in a try/except block to prevent the call from hanging on a socket pair that doesn't close 2021-05-17 14:35:13 -04:00
Alan Rominger
5dac46cd7d Update with force option if branch_override 2021-05-17 11:57:46 -04:00
softwarefactory-project-zuul[bot]
2c2aaa7fea Merge pull request #10182 from jakemcdermott/standardize-dependency-updates
Use development container when updating dependencies

GOAL
When adding, updating, or removing a package, the resultant changeset to the package.json and package-lock.json files that we check into devel should be consistent and reproducible, regardless of who is doing the update or what machine they're doing the update on.
SUMMARY OF CHANGES

Even though we usually run the ui development tooling outside of the awx development container, we should standardize on using this environment to update packages to ensure some consistency.
Use npm ci instead of npm install as the default package installation command, since we generally want to modify package files only when updating deps
You can run into memory limits from docker or node when building in the container, so increase the node memory limit and add a note to the docs that you may need to increase the container memory limit in your docker-for-mac settings (or similar tool, if you use it)

Reviewed-by: Kersom <None>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-17 15:22:16 +00:00
Marcelo Moreira de Mello
997525076d update_or_create EE via settings.DEFAULT_EXECUTION_ENVIRONMENTS 2021-05-17 00:41:06 -04:00
softwarefactory-project-zuul[bot]
3b280e1b32 Merge pull request #10205 from jbradberry/favicon-fix
Add an nginx location directive for the favicon

SUMMARY
Add an nginx location directive for the favicon so that the rewrite rule that adds slashes to the ends of requested
urls doesn't get to it.
related #8618
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API
UI

AWX VERSION

Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-05-14 19:25:35 +00:00
softwarefactory-project-zuul[bot]
a8b6db3967 Merge pull request #10179 from nixocio/ui_issue_9126_2
Update login message to avoid duplicate brand name

Returned brandName already contain the name brand Ansible. Update to
avoid name brand repetition.
Also update brandName on document title.
See: #9126

Reviewed-by: Kersom <None>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-14 19:04:36 +00:00
Jeff Bradberry
bcf93810ad Add an nginx location directive for the favicon
so that the rewrite rule that adds slashes to the ends of requested
urls doesn't get to it.
2021-05-14 14:00:57 -04:00
Hideki Saito
0cb33bd278 Remove source_script from tower_inventory_source integration test
* Fixes #10104

Signed-off-by: Hideki Saito <saito@fgrep.org>
2021-05-15 00:18:37 +09:00
Jake McDermott
8c2ca29f4e Add default error boundary around screens
Catch any unhandled non-async errors with an error boundary
around screens. This will show a generic error message instead
of crashing the page.
2021-05-14 10:40:48 -04:00
softwarefactory-project-zuul[bot]
f1767d05b0 Merge pull request #10202 from tiagodread/3420-fix
Use non-root path links

Resolves ansible/tower#3420
Use non-root path for links

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-05-14 13:44:45 +00:00
softwarefactory-project-zuul[bot]
b1cd7eb997 Merge pull request #9988 from mabashian/9163-admin-approvals-page
Fixes bug where workflow approvals page would crash if deleted username was referenced

SUMMARY
link #9163
The tooltip on the status labels for completed workflow approvals attempts to show the username of the user that acted on it.  If that user has been deleted then the key is not present in the object.  This would cause the page to crash.
To fix this, I conditionally show a different string when the username is not available.  If a user wants to see which deleted user acted on the approval they'll have to go to the activity stream.

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Mat Wilson <mawilson@redhat.com>
2021-05-14 13:17:37 +00:00
Tiago
0f8533f123 use non-root path 2021-05-14 10:00:18 -03:00
softwarefactory-project-zuul[bot]
2191ab1c6c Merge pull request #10148 from keithjgrant/8907-launch-prompt-vars-validation
Add Variables field validation in launch prompt

SUMMARY

Adds validation for the Variables field during launch prompts.
Prevents unexpected expanding of YAML expressions in the default value (similar to #7506) — this was caused by the default value being parsed into a JavaScript object and then re-translated back to YAML when mounting the "Other Prompts" step

addresses #8907
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-13 21:01:09 +00:00
mabashian
9975d4764d Extract strings 2021-05-13 16:38:41 -04:00
mabashian
31907423ce Fixes bug where workflow approvals page would crash if deleted username was referenced 2021-05-13 16:37:04 -04:00
nixocio
94d46a6e96 Fix null issue for limit
Fix null issue for limit.

See: https://github.com/ansible/awx/issues/9377
2021-05-13 14:26:18 -04:00
Jeff Bradberry
6f4c41a8d3 Add validation checks
that prevent the setting from being turned on if remote auth systems
and users are not already present.
2021-05-13 13:57:33 -04:00
Jeff Bradberry
81de931711 Add a new middleware to force-logout local-only users
when the DISABLE_LOCAL_AUTH setting is set.  This avoids the ugliness
of getting a SuspiciousOperation error for any request/response cycles
that are in flight when a user gets bounced.
2021-05-13 13:55:44 -04:00
Jeff Bradberry
9e7f004ca6 Add a signal handler to invalidate sessions and tokens for local users
when this setting gets turned on.
2021-05-13 13:55:44 -04:00
Jeff Bradberry
5c664eadf9 Write a thin wrapper around the standard Django auth backend 2021-05-13 13:55:44 -04:00
Jeff Bradberry
26b7e9de40 Add a new setting, DISABLE_LOCAL_AUTH
and expose it in the settings UI.
2021-05-13 13:55:44 -04:00
softwarefactory-project-zuul[bot]
09801d0a9a Merge pull request #10159 from AlanCoding/inventory_ig
Add instance_group to inventory update serializer

SUMMARY
Inventory updates run remotely, in the execution plane. This adds the instance_group field to the inventory update serializer to help clarify this reality.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

API

Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-13 17:50:45 +00:00
softwarefactory-project-zuul[bot]
a332f46f31 Merge pull request #10171 from jakemcdermott/remove-job-isolated-settings
Remove all AWX_ISOLATED* fields

I believe this should address #10123. The issue mentions a worker-json.js 404 and, while we should fix that at some point, I don't think it's actually related to the save not working.
SUMMARY
I noticed the job settings form wasn't saving on devel.
After some debugging, I found that removing the AWX_ISOLATED_CHECK_INTERVAL and AWX_ISOLATED_LAUNCH_TIMEOUT made the form saveable again.
It doesn't seem like we use any of the AWX_ISOLATED* fields anymore (not to be confused with AWX_ISOLATION* fields, which we do use) so this PR removes them all.
cc @wenottingham @shanemcd @marshmalien  @gamuniz @tiagodread @jbradberry

Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Bill Nottingham <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-13 17:32:15 +00:00
Jake McDermott
6f6d9e2f15 Update dependency update examples
There's no need to make a production build when updating dependencies,
just reiinstall
2021-05-13 13:09:30 -04:00
Jake McDermott
cd7c85490b Handle and document potential memory limit issues
* Increase node memory limit
* Add note to docs that you may need to increase container memory thresholds
imposed by docker-for-mac and similar tools if you're using them
2021-05-13 12:55:37 -04:00
Jake McDermott
a9ec7038de Use npm ci as default package installation command
We don't want to generate new package.json and package-lock.json
files unless we're explicitly updating new dependencies.
2021-05-13 12:55:28 -04:00
Jake McDermott
795e3c84fc Use development container when updating dependencies 2021-05-13 12:55:22 -04:00
softwarefactory-project-zuul[bot]
f2b2e64426 Merge pull request #10190 from jbradberry/fix-precommit-for-macs
Remove the shebang line from pre-commit.sh

SUMMARY

since bash isn't available by default on OS X.

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION



  
    
    

    
    

  


ADDITIONAL INFORMATION

Reviewed-by: Kersom <None>
Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
2021-05-13 15:24:24 +00:00
Chris Meyers
9b7bc5109a close db and cache connection in new threads 2021-05-13 11:13:26 -04:00
Jeff Bradberry
d07887bd91 Remove the shebang line from pre-commit.sh
since bash isn't available by default on OS X.
2021-05-13 10:49:24 -04:00
softwarefactory-project-zuul[bot]
bb47bdbc43 Merge pull request #10185 from jakemcdermott/fix-10170
Drop the word 'name' from image field, add examples

for #10170
We call this field "Image" in other places, so we want it to match. Also, "Image name" can be confusing because people may think they just need to provide the image name instead of the full image location, which includes registry and tag version.
cc @gamuniz @nixocio @beeankha @tiagodread

Reviewed-by: Kersom <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Julen Landa Alustiza <None>
2021-05-13 14:44:38 +00:00
softwarefactory-project-zuul[bot]
d477f04d75 Merge pull request #10175 from AlanCoding/only_have_eyes_for_you
Add more fields to .only since they get referenced

SUMMARY
Fixes a performance bottleneck when saving playbook_on_stats for jobs that use --limit against a small number of hosts while it has a large number in the inventory.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

ADDITIONAL INFORMATION
'tis the problem with .only(), that only the developer who wrote the queryset remembers that the other fields cannot be referenced except at the cost of another query
https://github.com/ansible/awx/pull/7352/files

Reviewed-by: Chris Meyers <None>
Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-05-13 14:44:33 +00:00
Alan Rominger
e5f059806b Add instance_group to inventory update serializer 2021-05-13 09:00:43 -04:00
Alan Rominger
6649b435ce Fix flake8 error 2021-05-13 08:57:19 -04:00
Alan Rominger
ae320ab228 Do not set openstack env var to blank string 2021-05-13 08:57:19 -04:00
Alan Rominger
29c961e52a Remove comment 2021-05-13 08:57:19 -04:00
Alan Rominger
fd466c5cff Finish converting the runner strings 2021-05-13 08:57:19 -04:00
Alan Rominger
623cf0b4cd Start migrating the /runner path references 2021-05-13 08:57:18 -04:00
Alan Rominger
d33a748eea Clean up and test patch changing methods 2021-05-13 08:57:18 -04:00
Alan Rominger
1f1cdf8859 start on path helper methods 2021-05-13 08:57:18 -04:00
Alan Rominger
334be9eb25 Use durable switch from container to host path 2021-05-13 08:57:18 -04:00
Alan Rominger
8f9373085a Fix credential env folder, test_tasks.py 2021-05-13 08:57:18 -04:00
Alan Rominger
11c5d577d6 Fix rel path for other inventories 2021-05-13 08:57:17 -04:00
Alan Rominger
0e17023ba3 Inventory directory already pre-created 2021-05-13 08:57:17 -04:00
Alan Rominger
3c785fbff3 update unit tests to new behavior 2021-05-13 08:57:16 -04:00
Alan Rominger
0061c57577 update inventory injector tests 2021-05-13 08:56:38 -04:00
Alan Rominger
f59da78328 Use inventory and env private_data_dir subfolders
This avoids writing files to the top level
  of the ansible-runner private_data_dir

Inventory is moved to be in the standard "inventory" folder

Credential related files are moved inside of the "env" folder

Also pre-create these folders when preparing for a job run

With this, args is the only top-level file still remaining
2021-05-13 08:56:38 -04:00
softwarefactory-project-zuul[bot]
117bb07f0d Merge pull request #10187 from jakemcdermott/warn-and-recompile-lint
Warn but still recompile on lint error

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
2021-05-12 21:32:55 +00:00
softwarefactory-project-zuul[bot]
01fdc482be Merge pull request #10169 from jakemcdermott/fix-10127
Always resolve launching status

SUMMARY
Resolves #10127
Always resolve the launching status after any intermediate async activity that needs to occur while loading prompts, etc.

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-12 21:31:35 +00:00
softwarefactory-project-zuul[bot]
875abcd31a Merge pull request #10161 from nixocio/ui_issue_10144
Display error for boolean fields

Display error when modifying Allow Override Branch on Projects.
See: #10144

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Kersom <None>
2021-05-12 21:30:09 +00:00
Jake McDermott
3468153619 Warn but still recompile on lint error 2021-05-12 16:47:49 -04:00
softwarefactory-project-zuul[bot]
27b1d15a7a Merge pull request #10063 from nixocio/ui_issue_7777_style
Add slider to adjust capacity_adjustment

Add slider to adjust capacity adjustment.
Also add a new custom hook, useDebounce.

See: #7777

Reviewed-by: Kersom <None>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-12 20:17:28 +00:00
Jake McDermott
39ce0ade6d Update image descriptions, add examples 2021-05-12 16:10:42 -04:00
nixocio
dfb0710d69 Add slider to adjust capacity_adjustment
Add slider to adjust capacity adjustment.

Also add a new custom hook, useDebounce.

See: https://github.com/ansible/awx/issues/7777
2021-05-12 15:42:31 -04:00
nixocio
f6c9621510 Display error for boolean fields
Display error when modifying Allow Override Branch on Projects.

See: https://github.com/ansible/awx/issues/10144
2021-05-12 14:49:16 -04:00
softwarefactory-project-zuul[bot]
7f90a8b2b3 Merge pull request #10183 from beeankha/null_ee_show_error
Show Error if No Execution Environment is Found on Project Sync or Job Run

SUMMARY

Duplicate of PR #10147 fixing issue #10118

Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-12 18:47:50 +00:00
mabashian
0d17dfcd87 Pass config request through to subscription edit 2021-05-12 14:47:07 -04:00
mabashian
91134b2537 Remove erroneouos extra param 2021-05-12 14:47:06 -04:00
mabashian
3a56d2447c Adds support for pendo initialization across the app 2021-05-12 14:47:06 -04:00
softwarefactory-project-zuul[bot]
550a66553e Merge pull request #10113 from AlexSCorey/10045-ProjectListIssues
Adds Job Cancel Button

SUMMARY
This addresses part of #10045 and adds a sync cancel button on the projects list.  It also expands the usage of that button to the Project details page, and the Inventory Source list.  It does this by introducing a new component called JobCancelButton, that basically takes the work of the job cancel button on the Output toolbar and refactors it slightly to make it useable in these other areas.  This button could also be used in the Inventory Source details page once we have websockets hooked up for that view and we can track the status of the sync. (#9013)
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Kersom <None>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-12 18:27:06 +00:00
Jake McDermott
7fbe01352f Drop the word name from image field input
This field is labeled as just "Image" in other places, so we want
it to match. Also, "name" can be confusing because users will think
they just need to provide the image name instead of the full image
location, which includes registry and tag version.
2021-05-12 14:26:18 -04:00
beeankha
3520a6e066 Update fixtures on unit tests 2021-05-12 14:00:04 -04:00
beeankha
19d7f3e346 Update unit tests 2021-05-12 13:56:46 -04:00
softwarefactory-project-zuul[bot]
71f9476a51 Merge pull request #9759 from ghjm/idempotence_is_a_thing
Make tower_license module idempotent

SUMMARY
Currently, the tower_license module always installs a license, without checking if Tower is already licensed.  In general, Ansible modules are supposed to be idempotent.  This PR updates the module to check whether Tower is already licensed, and do nothing in that case.  A new parameter force is provided so the user can always install the license, or override an existing license with a new one.
ISSUE TYPE
Bughancement
COMPONENT NAME
awx_collection
AWX VERSION
awx: 18.0.0
(but really Tower 3.8.2)

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Graham Mainwaring <graham@mhn.org>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-05-12 17:44:47 +00:00
Tiago
ffcf76ddd0 update ouiaId 2021-05-12 14:41:10 -03:00
softwarefactory-project-zuul[bot]
d36babf506 Merge pull request #10145 from nixocio/ui_issue_8788
Allow modify scm branch override

Source Control Branch was not being displayed as part of the
JobTemplate Edit, since the project did not have the variable
allow_override as part of the summary_fields.


Add source control details for JobDetail and WorkflowJobTemplateDetail


See: #8788

Reviewed-by: Kersom <None>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Mat Wilson <mawilson@redhat.com>
2021-05-12 17:37:14 +00:00
softwarefactory-project-zuul[bot]
a73cb0280c Merge pull request #10184 from jbradberry/explicit-pre-commit-script
Break out the pre-commit hook into an explicit script

SUMMARY

This means that

we don't have to be always updating the underlying .git/hooks/pre-commit file
updates to the logic will just work automatically
the logic of the conditional invocation of black has been fixed so that AWX_IGNORE_BLACK=1 should work correctly now


ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION



  
    
    

    
    

  


ADDITIONAL INFORMATION

Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Jeff Bradberry <None>
2021-05-12 16:37:27 +00:00
Jeff Bradberry
1e5a0dc7c5 Break out the pre-commit hook into an explicit script
This means that

- we don't have to be always updating the underlying .git/hooks/pre-commit file
- updates to the logic will just work automatically
- the logic of the black logic has been fixed so that AWX_IGNORE_BLACK=1 should work right now
2021-05-12 11:54:17 -04:00
beeankha
fd5f3a82d2 Show error if no Execution Environment is found on project sync/job run 2021-05-12 11:52:12 -04:00
softwarefactory-project-zuul[bot]
e970620672 Merge pull request #10174 from jbradberry/remove-isolated-instances
Data migration to remove the isolated instances from the database

SUMMARY


ISSUE TYPE


Feature Pull Request

COMPONENT NAME


API

AWX VERSION



  
    
    
  


ADDITIONAL INFORMATION

Reviewed-by: Elyézer Rezende <None>
Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-05-12 14:27:03 +00:00
nixocio
1befacaf39 Update login message to avoid duplicate brand name
Returned brandName already contain the name brand Ansible. Update to
avoid name brand repetition.

See: https://github.com/ansible/awx/issues/9126
2021-05-12 08:44:28 -04:00
softwarefactory-project-zuul[bot]
e9bf25f108 Merge pull request #10176 from shanemcd/bye-docker
Use base image from quay.io/centos/centos

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-05-11 21:04:25 +00:00
Alex Corey
6c06b0432b adds job cancel button to job detail page and to job list 2021-05-11 16:35:08 -04:00
softwarefactory-project-zuul[bot]
a7c50b77ea Merge pull request #10048 from wenottingham/analyze-that
Update analytics branding

SUMMARY
cc @kyleabenson @benthomasson
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API
UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-11 20:28:24 +00:00
Alan Rominger
164255e516 Remove fields not needed from .only 2021-05-11 16:26:12 -04:00
softwarefactory-project-zuul[bot]
74282c5dfb Merge pull request #10173 from nixocio/ui_issue_10078
Display Edit/Delete on EE details page as per last API changes

Display Edit/Delete buttons on details page for EE managed by tower.
See: #10078

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-11 20:25:31 +00:00
Shane McDonald
afa3501194 Use base image from quay.io/centos/centos 2021-05-11 16:24:59 -04:00
Alan Rominger
0f5629b514 Add more fields to .only since they get referenced 2021-05-11 16:14:55 -04:00
Tiago
0db58f0edd update ouiaId 2021-05-11 16:02:39 -04:00
Alex Corey
7f022b1555 adds job cancel button to job detail page 2021-05-11 16:02:39 -04:00
Alex Corey
9f80f918c5 allows canceling of all jobs on job output page 2021-05-11 16:01:52 -04:00
Alex Corey
34fe255336 disables delete button on project details page 2021-05-11 16:00:55 -04:00
Alex Corey
03265c05ca fixes setstate, and double tooltip 2021-05-11 16:00:55 -04:00
Alex Corey
6c7e1fc4eb Adds Job Cancel Button
This refactors the cancel button on the job output page so that it can be used on the Project List page,
the Project detail page, and the Inventory Source list page. Once websockets are ready for the Inventory Source details page
and we can track the status of the source we can use this button there too.
2021-05-11 16:00:55 -04:00
Bill Nottingham
8683872927 Update analytics branding 2021-05-11 15:46:56 -04:00
Jeff Bradberry
7b47d7e7f6 Data migration to remove the isolated instances from the database 2021-05-11 15:46:39 -04:00
softwarefactory-project-zuul[bot]
19d000e97f Merge pull request #10157 from AlanCoding/minikube_docs
minikube instructions adjustments from debugging

SUMMARY
The awx-operator examples expect the tower_image_version as a separate var, and can error without that.
Also, there's still an issue getting going with ansible/deploy-operator.yml's Deploy Operator task. I'm still looking into that, the associated hack might change.
ISSUE TYPE

Docs Pull Request

COMPONENT NAME

API

AWX VERSION
19.1.0

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-11 19:00:02 +00:00
nixocio
8f54627ea6 Display Edit/Delete on EE details page as per last API changes
Display Edit/Delete buttons on details page for EE managed by tower.

See: https://github.com/ansible/awx/issues/10078
2021-05-11 13:39:07 -04:00
Jake McDermott
6bb8fd3fd6 Remove all AWX_ISOLATED* fields 2021-05-11 13:21:18 -04:00
Jake McDermott
6e97020eae Always resolve launching status 2021-05-11 12:14:53 -04:00
softwarefactory-project-zuul[bot]
30997b30b6 Merge pull request #10168 from nixocio/ui_fix_typos
Fix typos

Fix typos
I had to run npm run extract-strings since the typos were present on the Plural component.

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
2021-05-11 14:17:42 +00:00
nixocio
499321cdf7 Fix typos
Fix typos
2021-05-11 09:30:40 -04:00
softwarefactory-project-zuul[bot]
a581e26414 Merge pull request #10163 from nixocio/ui_remove_dupe
Remove duplicated API calls unit-test

Remove duplicated API calls unit-test

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-05-10 21:18:28 +00:00
nixocio
26b1a82164 Remove duplicated API calls unit-test
Remove duplicated API calls unit-test
2021-05-10 16:03:47 -04:00
softwarefactory-project-zuul[bot]
f5cc927a15 Merge pull request #10086 from jakemcdermott/fix-9370
Avoid prop reference error when recreating survey

SUMMARY
For #9370
The survey object is undefined when recreating a survey after deleting it. Add optional chaining on survey fields to avoid prop reference error.

Reviewed-by: Kersom <None>
2021-05-10 15:34:36 +00:00
Alan Rominger
7ec0464072 minikube instructions adjustments from debugging 2021-05-10 11:30:14 -04:00
Jake McDermott
b94a9c19e7 Avoid prop reference error when recreating survey
The survey object is undefined when recreating a survey after deleting it.
Add optional chaining on survey fields to avoid prop reference error.
2021-05-10 10:39:04 -04:00
softwarefactory-project-zuul[bot]
1c73407edf Merge pull request #10150 from QiYuTechDev/devel
`console.warning` is not exists on browser

SUMMARY

fix typo error for console.warn

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


UI

AWX VERSION

19.1.0

ADDITIONAL INFORMATION

console.warning is not exists function in browser envirment.

Reviewed-by: Kersom <None>
2021-05-10 13:51:56 +00:00
奇遇科技
a4d15b20ff console.warning is not exists on browser
fix typo error for `console.warn`
2021-05-10 02:49:25 +00:00
Keith J. Grant
83b6a91623 validate variables field in launch prompt 2021-05-07 16:13:38 -07:00
nixocio
5fb9afc9f5 Allow modify scm branch override
* Source Control Branch was not being displayed as part of the
JobTemplate Edit, since the project did not have the variable
`allow_override` as part of the summary_fields.

* Add source control details for JobDetail and WorkflowJobTemplateDetail

See: https://github.com/ansible/awx/issues/8788
2021-05-07 15:34:34 -04:00
softwarefactory-project-zuul[bot]
82af78fe33 Merge pull request #10131 from AlexSCorey/10088-ConverTeamsSubTabstoTables
Converts Teams Roles tab to tables

SUMMARY
Addresses #10088.  Converts The Roles tab inside of Teams to tables view.
E2E workflows triggered
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-07 18:10:19 +00:00
softwarefactory-project-zuul[bot]
d60014987f Merge pull request #9924 from AlexSCorey/6464-SurveyMultipleChoiceRedesign
Redesign survey multiple choice 

SUMMARY
Addresses #6464.
This new design improves UI and reduces the risk to having mismatching choices and default values.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Kersom <None>
Reviewed-by: Marliana Lara <marliana.lara@gmail.com>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Sarah Akus <sarah.akus@gmail.com>
2021-05-07 17:37:23 +00:00
softwarefactory-project-zuul[bot]
55b8dcdd8d Merge pull request #10097 from sean-m-sullivan/devel
add custom_venv for backward compatibility

SUMMARY
As per #10055 , this is the proposal to add back custom virtual environments to the modules. With the understanding that they will not be tested. But to allow users of Ansible Tower 3.8 the ability to use newer features and bugfixes in awx.awx as applicable, without restorting to backporting these removals. Would expect these to remain for a time after Tower moves to Execution environments as teams/companies adopt the next version of tower.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

awx_collection

AWX VERSION
19.1.0

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-05-07 17:19:24 +00:00
softwarefactory-project-zuul[bot]
03261c4782 Merge pull request #10141 from nixocio/ui_fix_prop_typo
Fix prop typo

Fix prop typo.
See: https://www.patternfly.org/2020.04/documentation/react/components/select#props

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
2021-05-07 17:05:09 +00:00
Alex Corey
a6778604e1 updates strings 2021-05-07 12:53:51 -04:00
Alex Corey
c441d6cd55 adds ouiaId and blank target for tooltip 2021-05-07 12:51:33 -04:00
Alex Corey
eebcab610e allows for resetting the values in edit mode 2021-05-07 12:51:33 -04:00
Alex Corey
783a0963ff moves and renames new field component. adresses console errors, removes unneeded props adds back isVaid prop on formfield 2021-05-07 12:51:33 -04:00
Alex Corey
dbc235cfb6 updates strings 2021-05-07 12:51:33 -04:00
Alex Corey
9dde854baa This puts the formatted default and choice values on the formik object.
When we go to submit the form to the api we format it again in a way
the api will recognize.  Allowing formik to manage updating, the choices
and the default values this way cleans up the code and removes a bunch of unnecessary
splitting and joining of the choices an default choices strings
2021-05-07 12:50:31 -04:00
Alex Corey
98375a0328 Adds styling, and dynamic rendering of extra fields 2021-05-07 12:48:26 -04:00
Alex Corey
264b13f33c can write in inputs properly 2021-05-07 12:48:26 -04:00
Alex Corey
35a9e7e565 some refactoring, and checking and unchecking boxes 2021-05-07 12:48:26 -04:00
Alex Corey
e088c7385a adding and removing inputs properly 2021-05-07 12:48:26 -04:00
softwarefactory-project-zuul[bot]
372c80ee44 Merge pull request #10140 from AlexSCorey/boldifyUsersSubListsName
Adds bold to some list items 

SUMMARY
Some list items were not bolded during conversion to tables mistakenly
kicked off E2E tests
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Kersom <None>
2021-05-07 15:27:34 +00:00
Alex Corey
5a1810e191 fxes pagination and removes console warnings 2021-05-07 11:26:50 -04:00
nixocio
dee0b61bc2 Fix prop typo
Fix prop typo.

See: https://www.patternfly.org/2020.04/documentation/react/components/select#props
2021-05-07 11:13:07 -04:00
Alex Corey
2c82d32720 Adds bold to some list items that were missed during conversion to tables 2021-05-07 10:14:24 -04:00
sean-m-ssullivan
715aead961 add custom_venv for backward compatibility 2021-05-07 09:01:35 -05:00
softwarefactory-project-zuul[bot]
ddb1d12a79 Merge pull request #10019 from mabashian/9635-cred-bugs
Fixes for a couple of credential form bugs

SUMMARY
link #9635
This addresses the first and second bullet points in the linked issue.  The third is actually covered by a separate PR.
The ace editor fix was to simply wrap it in a div and apply the previous styling to that div instead of the editor.
The secret key/details page crashing was caused by a race condition when would redirect back to the details view after editing.  The details view was rendering with some stale data and a key that was expected to be there was not.  To fix this I wrapped the request to fetch the credential detail in a useRequest hook and show the loading spinner while this request is outstanding.  Only after the request resolves do we try to render the details view so that it always has the up to date object.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-06 21:49:55 +00:00
Alex Corey
8fe437380d converts inventory groups related groups and related hosts to tables 2021-05-06 16:32:12 -04:00
softwarefactory-project-zuul[bot]
2d81143c98 Merge pull request #10066 from tiagodread/ouia-ids
Add testability for e2e tests

Resolves #9511
Resolves #9503
Resolves #9512

Reviewed-by: Kersom <None>
2021-05-06 20:15:49 +00:00
softwarefactory-project-zuul[bot]
a219e27e0b Merge pull request #10116 from nixocio/ui_issue_9126
Update Login page

Update Login page.

See: #9126

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-06 20:15:45 +00:00
Tiago
d428a540a0 ouiaId to AddDropDownButton ToolbarAddButton TemplateList InventoryList
add testability to DataListToolbar.jsx

add testability to AssociateModal.jsx HostGroupsList.jsx

fix lint

add ouiaId to InventoryGroupHostList.jsx

add ouiaId to ExecutionEnvironmentList.jsx

add ouiaId to InstanceGroupList.jsx

add ouiaId to InstanceGroupDetails.jsx

add ouiaId to ScheduleList.jsx and ContainerGroupDetails.jsx
2021-05-06 16:29:52 -03:00
Alex Corey
e1b6e1509c Converts Teams Roles tab to tables 2021-05-06 12:00:02 -04:00
softwarefactory-project-zuul[bot]
1d6579e110 Merge pull request #10106 from rooftopcellist/compose-opts-order
Docker-compose requires the options to be passed before up

SUMMARY
The $(COMPOSE_UP_OPTS) in the docker-compose make target need to come before the up command or else they are not parsed correctly.
ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

19.0.0

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-05-05 19:20:34 +00:00
nixocio
c50bd8d6e6 Update Login page
Update Login page.

See: https://github.com/ansible/awx/issues/9126
2021-05-05 14:10:28 -04:00
softwarefactory-project-zuul[bot]
13e1fc9839 Merge pull request #10100 from Spredzy/rename-job
Rename awx to automation for pod names

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-05 12:28:50 +00:00
Christian M. Adams
a205ddeed6 Docker-compose requires the options to be passed before up 2021-05-04 16:54:16 -04:00
softwarefactory-project-zuul[bot]
d7742d7340 Merge pull request #10044 from AlexSCorey/9977-ScheduleSurvey
Properly adds survey default values on Schedules

SUMMARY
This addresses #9977. This also fixes a bug where the extra_data was not rendering properly in schedule details
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-04 19:43:18 +00:00
softwarefactory-project-zuul[bot]
ce675319b7 Merge pull request #10105 from nixocio/ui_update_date_tooltip
Make date consistent on tooltip display

Make date consistent on tooltip to display info about job.
There are 3 places that define similar function on the code basis. Make
them consistent in how to display date.
Search for generateLastJobTooltip on code basis.

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
2021-05-04 19:19:21 +00:00
Alex Corey
610138caeb Properly adds survey default values on Schedules 2021-05-04 14:56:19 -04:00
softwarefactory-project-zuul[bot]
25137b40d3 Merge pull request #10040 from keithjgrant/6189-misc-tables
Convert Inventory sub-lists to tables

SUMMARY
Converts Inventory Access, Hosts, Groups, and Sources lists to tables
Addresses #6189
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Marliana Lara <marliana.lara@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-04 18:40:53 +00:00
mabashian
9b92d1584d Run prettier 2021-05-04 14:21:36 -04:00
mabashian
11d024abdb Adds missing code after rebase 2021-05-04 14:16:13 -04:00
mabashian
57433a59d7 Fix bug where changing credential field from plugin to string crashed application 2021-05-04 14:14:13 -04:00
mabashian
5ac4a9aca6 Fix bug with credential plugin code editor width 2021-05-04 14:09:39 -04:00
nixocio
5b92c9e8f3 Make date consistent on tooltip display
Make date consistent on tooltip to display info about job.
There are 3 places that define similar function on the code basis. Make
them consistent in how to display date.
2021-05-04 13:51:08 -04:00
Tiago
7951c2f014 change testability locator 2021-05-04 14:26:55 -03:00
Tiago
2cfdf08500 add testability 2021-05-04 14:00:24 -03:00
softwarefactory-project-zuul[bot]
10474cd64c Merge pull request #10077 from sean-m-sullivan/job_launch_tags
Fix tower_job_launch tags being passed to API

SUMMARY
#10008
Fix tower_job_launch tags being passed to API
Previously the wrong field was being used on the api to pass tags, also while the module accepts lists, the API does not, so it would error. Take a users list, and converts to comma separated string, in order to maintain status quo.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

awx_collection

AWX VERSION
19.1.0

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-05-04 16:13:16 +00:00
softwarefactory-project-zuul[bot]
da9a075000 Merge pull request #10047 from sean-m-sullivan/org_label
add org search to labels

SUMMARY
After having an issue with labels I saw that orgs were referenced, Remembering #7567 implemented the code to do the search for orgs so you can search for labels within an org, Tests include creating the same named label in two orgs, and the search not erroring out that it found two labels of that name.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

awx_collection

AWX VERSION
19.0.0

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
2021-05-04 15:55:51 +00:00
Tiago
510a546d8c add testability 2021-05-04 11:00:48 -03:00
Yanis Guenane
562f78e53d Rename awx to automation for pod names 2021-05-04 14:17:45 +02:00
softwarefactory-project-zuul[bot]
e08590290c Merge pull request #10094 from jladdjr/awx_8853_add_notification_error_to_nt_listview
add notification error to notification template list view

In support of #8853
Updates /api/v2/notification_templates to include the error field for summary_fields -> recent_notifications

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-05-04 04:21:52 +00:00
Keith J. Grant
e2c8519b77 convert InventoryHostGroups list to table 2021-05-03 16:00:09 -07:00
softwarefactory-project-zuul[bot]
86b683a8f1 Merge pull request #10096 from shanemcd/devel
Fix CSP error on Safari

This was causing:
[Error] Refused to execute a script because its hash, its nonce, or
'unsafe-inline' does not appear in the script-src directive of the Content
Security Policy. (migrations_notran, line 16)

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-05-03 21:46:04 +00:00
Shane McDonald
1ad561c307 Fix CSP error on Safari
This was causing:

```
[Error] Refused to execute a script because its hash, its nonce, or
'unsafe-inline' does not appear in the script-src directive of the Content
Security Policy. (migrations_notran, line 16)
```
2021-05-03 17:12:30 -04:00
Keith Grant
7b60733da0 delete comment
Co-authored-by: Marliana Lara <marliana.lara@gmail.com>
2021-05-03 13:53:57 -07:00
Keith Grant
d7ce328046 fix id string
Co-authored-by: Marliana Lara <marliana.lara@gmail.com>
2021-05-03 13:53:57 -07:00
Keith J. Grant
25a4a112b3 remove unecessary i18n wrappers; fix HostToggle tooltip 2021-05-03 13:53:57 -07:00
Keith J. Grant
cbe2a78287 convert inventory source list to tables 2021-05-03 13:53:57 -07:00
Keith J. Grant
83ceacf588 convert inventory groups list to tables 2021-05-03 13:53:57 -07:00
Keith J. Grant
fe0ad30245 fix inventory access/hosts lists tests 2021-05-03 13:53:57 -07:00
Keith J. Grant
0ac6ba9c99 convert inventory access/hosts lists to tables 2021-05-03 13:53:57 -07:00
softwarefactory-project-zuul[bot]
f8ecdbf287 Merge pull request #10056 from keithjgrant/6189-user-sublist-tables
Convert user sub-lists to tables

SUMMARY
Converts User Organizations, Teams, and Roles lists to tables
Addresses #6189
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-03 20:20:11 +00:00
Jim Ladd
a6f3817488 verify notification errors included in NT list view 2021-05-03 13:17:34 -07:00
Jim Ladd
e4eb03259b include error field in notification template's list of recent notifs 2021-05-03 13:17:34 -07:00
softwarefactory-project-zuul[bot]
0ccc93a166 Merge pull request #10089 from jbradberry/fix-get-default-ee
Fix projects to use the utility function get_default_execution_environment

SUMMARY


ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION



ADDITIONAL INFORMATION

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-03 19:47:53 +00:00
Keith J. Grant
2672c2ffe3 add default ouia-id to paginated tables 2021-05-03 12:04:33 -07:00
Jeff Bradberry
204083fcdc Fix projects to use the utility function get_default_execution_environment 2021-05-03 14:00:19 -04:00
Keith J. Grant
b21db2fd31 fix user list sorting issues; clean up comments 2021-05-03 10:57:17 -07:00
Keith J. Grant
d1cb0781ce update tests for new user sub-list tables 2021-05-03 10:57:17 -07:00
Keith J. Grant
7c86edd825 convert user sub-lists to tables 2021-05-03 10:57:17 -07:00
softwarefactory-project-zuul[bot]
3addbeab4c Merge pull request #10085 from jbradberry/fix-check-migrations
Make the check_migrations command a direct alias of makemigration

SUMMARY
Make the check_migrations command a direct alias of makemigration.
It already more or less was, but it previously did some machinations
around copying and modifying the database settings.  These on-the-fly
changes to the database connection no longer work after the
rearrangement of settings files, so let's just get rid of it.
Example, from running make test:
  py3: commands succeeded
  congratulations :)
awx-manage check_migrations --dry-run --check  -n 'missing_migration_file'
Traceback (most recent call last):
  File "/var/lib/awx/venv/awx/lib64/python3.8/site-packages/django/db/backends/base/base.py", line 217, in ensure_connection
    self.connect()
  File "/var/lib/awx/venv/awx/lib64/python3.8/site-packages/django/db/backends/base/base.py", line 195, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/var/lib/awx/venv/awx/lib64/python3.8/site-packages/django/db/backends/sqlite3/base.py", line 194, in get_new_connection
    conn = Database.connect(**conn_params)
sqlite3.OperationalError: unable to open database file

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

AWX VERSION
awx: 19.1.0

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-03 15:45:40 +00:00
softwarefactory-project-zuul[bot]
5096f1459d Merge pull request #10059 from AlexSCorey/RemoveI18nStuff
Removes remaining I18n props, HOCs and misc objects

SUMMARY
This Removes withI18n, the i18n object and all the places that it is passed around as a prop, or argument.
E2E Tests have been triggered.  There should be no functional or visual impact. E2E results
ISSUE TYPE
-Dependency Upgrade
COMPONENT NAME

UI

AWX VERSION



ADDITIONAL INFORMATION

Reviewed-by: Kersom <None>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-03 15:24:50 +00:00
softwarefactory-project-zuul[bot]
a3de251732 Merge pull request #10084 from jbradberry/revert-managed-by-tower-ee-lock
Revert the code that prevents sysadmins from changing managed EEs

SUMMARY
related #10078
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

AWX VERSION
awx: 19.1.0

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-05-03 15:13:09 +00:00
Jeff Bradberry
686d750ad9 Make the check_migrations command a direct alias of makemigration
It already more or less was, but it previously did some machinations
around copying and modifying the database settings.  These on-the-fly
changes to the database connection no longer work after the
rearrangement of settings files, so let's just get rid of it.
2021-05-03 11:01:52 -04:00
Jeff Bradberry
39f26fe576 Revert the code that prevents sysadmins from changing managed EEs
ref #10078
2021-05-03 10:25:18 -04:00
Alex Corey
7a9bcc1e1e Removes remaining I18n props, HOCs and mics objects 2021-05-03 10:10:40 -04:00
softwarefactory-project-zuul[bot]
72a940bef1 Merge pull request #10081 from nixocio/ui_fix_style_warning
Fix unit-test styling warning

Fix unit-test styling warning.
      Warning: Unsupported style property white-space. Did you mean
      whiteSpace?

Style still valid after change:

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
2021-05-03 13:54:14 +00:00
softwarefactory-project-zuul[bot]
cb26087c2a Merge pull request #9931 from seiwailai/issue-9872-sync-feedback
project: Add last job status as for project sync feedback feature.

SUMMARY
Fixes #9872

Add last job status as for the project sync feedback feature. When users clicked the sync button on the project page, last job status will eventually update the status to Pending, Waiting, Running, and final result (Successful, Cancelled, Failed, Error). The implementation requires the WebSocket connection to ensure synchronous status update.
In particular, the last job status is similar to the functionality of status in the project list (status in ProjectListItem.jsx). More specifically, the last job status accompanied by a job link that allowing the user to navigate to the job output page. Besides, there is also the tooltip that allowing the user to view the information related to the most recent sync, covering information like JOB ID, STATUS, FINISHED.
The rationale of having the last job status instead of redirection or toast notification is that:

User has choices on whether to redirect to the job output. If the user wishes to navigate to job output, he/she can click the link. Besides, the user might have other projects to be synced right after the current project and he/she may want to proceed back to the project list page instead of the job output page. If we implement force redirection, it would take a longer time to navigate to the project list page.
The status update on last job status is fundamentally similar to toast notification where the user can immediately be notified if he/she already clicked the sync button to launch the job.

Nevertheless, this PR requires further discussion. Any comments are welcomed!

ISSUE TYPE


Feature Pull Request

COMPONENT NAME


UI


awx/ui_next/src/screens/Project/Project.jsx
awx/ui_next/src/screens/Project/useWsProject.js - Added websocket implementation
awx/ui_next/src/screens/Project/ProjectDetail/ProjectDetail.jsx

AWX VERSION

awx: 19.0.0

ADDITIONAL INFORMATION

In case if users spam the sync button, we will need to ensure the fluent UI on the most recent sync tooltip and last job status. Thus, we would not want to update our last job status to Pending if there is a current running job.
For instance, we clicked sync for a particular project twice.

For the first sync, our last job status should immediately change to Pending, then Waiting, then Running, then result (which are Successful, Failed, Error, Cancelled).
For the second sync, if we have a running job, we should not update our UI to Pending, otherwise our most recent sync tooltip UI will lose our current running job and we cannot navigate to the job link through the link provided by last job status tooltip.

Issue of sync button click spam
Ideally, we should prevent any spamming on the sync button using backend logic to reduce overload on the server as we already have a similar running project. Together with backend logic, we can disable the sync button right after we start to sync a project.
However, if we only disable sync through the frontend, this seems insecure as people with bad intentions might able to change the button disable attribute.

After

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Sei Wai Lai <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-05-03 13:28:40 +00:00
softwarefactory-project-zuul[bot]
7d6a8adb79 Merge pull request #10067 from mabashian/test-warning-cleanup-3
Unit test warning cleanup

SUMMARY
These commits target the warnings that look like:
Can't perform a React state update on an unmounted component
The underlying problem here is that we have network requests that are being made by components that are subsequently being unmounted.  When the network request resolves, we attempt to update some state but the component is no longer mounted and the warning is triggered.  To address this I consolidated a lot of isMounted code into a single hook which can be used across the app to check to see whether the component in question is still mounted before attempting to update state inside of a useEffect.  This primarily applies to network requests.
I think this points to a larger issue which is that we sometimes mount components prematurely.  For example, when the job template edit component is mounted we actually mount:

JobTemplateForm (briefly)
ContentLoading
JobTemplateForm

Network requests triggered by the first mount of JobTemplateForm are suscepitble to attempting to update state on an unmounted component.  I believe this pattern exists in many places across the app but I haven't tried to solve this in this PR.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Marliana Lara <marliana.lara@gmail.com>
Reviewed-by: Kersom <None>
2021-05-03 13:22:35 +00:00
nixocio
c1e0def013 Fix unit-test styling warning
Fix unit-test styling warning.

```console.error
      Warning: Unsupported style property white-space. Did you mean
      whiteSpace?
```
2021-05-03 09:22:18 -04:00
sean-m-ssullivan
5993db76d3 fix job launch inputs 2021-05-01 23:08:44 -05:00
Shane McDonald
929ed3e09d Merge pull request #10074 from shanemcd/bump-19.1.0
Bump changelog and version files for 19.1.0
2021-05-01 07:56:47 -04:00
Shane McDonald
f83a005038 Bump changelog and version files for 19.1.0 2021-05-01 07:43:01 -04:00
Bill Nottingham
c0afd67432 Have the project update playbook warn if role/collection syncing is disabled.
Make it more clear that a credential is required.
2021-04-30 16:06:00 -04:00
mabashian
5b71681494 Fixes test warnings where state updates were being triggered after component unmounts 2021-04-30 15:34:39 -04:00
mabashian
f63312c811 Prevent multi credential state updates from happening after unmount 2021-04-30 15:34:39 -04:00
seiwailai
0886414c72 ProjectList: Change job status UI update logic.
1. Render current job status if there is current waiting, pending or running job.\n 2. Render last job status if there is no current job.
2021-05-01 03:30:16 +08:00
seiwailai
30d78e8857 Project: Added project last job status UI with websocket feature
1. Activate web socket once get into project detail page to ensure job status update synchronization.\n 2. Show last job status if there is no current job.\n 3. Show current job status if there is any current pending, waiting or running job.
2021-05-01 03:30:16 +08:00
seiwailai
07d01c49c0 ProjectListItem: Disabled sync button and render tooltip on sync.
Added feature of disabling sync button when users click sync button and rendering tooltip when disabled sync button on hover.
2021-05-01 03:30:16 +08:00
seiwailai
bb896c0b02 ProjectSyncButton: Add tests.
Add 'disable button and set onClick to undefined on sync' and 'should render tooltip on sync'
2021-05-01 03:30:16 +08:00
seiwailai
95634bf0b8 useWsProject: Add tests for useWsProject.jsx.
Add tests like 'should return project detail', 'should establish websocket connection' and 'should update project status'.
2021-05-01 03:30:16 +08:00
seiwailai
e6735b595c project: Add disable sync button feature.
Disable sync button if there is any pending, waiting or running job
2021-05-01 03:30:16 +08:00
seiwailai
03d8987d93 project: Add last job status as for feedback feature. 2021-05-01 03:30:16 +08:00
softwarefactory-project-zuul[bot]
f5c176701b Merge pull request #10031 from wenottingham/whats-in-a-name--mostly-just-letters
Assorted renaming and string changes

SUMMARY
Goal was to hit user-facing strings and docs.
Didn't try and catch all comments, although did a few when in those files.

Reviewed-by: Bill Nottingham <None>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
2021-04-30 19:24:28 +00:00
Bill Nottingham
8a4bffcd50 Fix UI tests 2021-04-30 14:32:05 -04:00
Bill Nottingham
c8cf28f266 Assorted renaming and string changes 2021-04-30 14:32:05 -04:00
softwarefactory-project-zuul[bot]
e0d6b138b0 Merge pull request #10062 from shanemcd/fix-ee-cg
A couple EE bug fixes

See commit messages for more info

Reviewed-by: Seth Foster <None>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-04-30 17:10:23 +00:00
Shane McDonald
f94db36273 Forcibly ensure that the correct ansible-runner command is used for CG pods 2021-04-30 12:34:26 -04:00
Shane McDonald
77c573d64a Fix bug where incorrect EE was being used for Container Group pods 2021-04-30 12:21:03 -04:00
Shane McDonald
0badc2fff7 Explicitly set args for container group pods
A user may try to use an EE that does not have the custom entrypoint script used
by the default AWX EE
2021-04-30 12:16:52 -04:00
sean-m-ssullivan
666e9c5c2f add search label by org 2021-04-29 16:14:09 -05:00
softwarefactory-project-zuul[bot]
43d33281a5 Merge pull request #10004 from AlexSCorey/9864-AddEEtoAdHocWizard
Adds an execution environment step to the ad hoc commands

SUMMARY
This addresses some of #9864 by adding a step to select an execution environment to the ad hoc commands wizard
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-29 20:43:55 +00:00
softwarefactory-project-zuul[bot]
6bea5dd294 Merge pull request #9957 from jbradberry/isolated-removal
Isolated removal

SUMMARY
Removal of the isolated nodes feature.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

API

AWX VERSION

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Elyézer Rezende <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-04-29 19:15:43 +00:00
Alex Corey
1d442452b0 adds advanced search functionality and lists correct EEs 2021-04-29 14:23:28 -04:00
softwarefactory-project-zuul[bot]
ed259cf0aa Merge pull request #10036 from seiwailai/issue-10029-project-list-cols-misaligned
ProjectList: Fixes columns misalignment.

Fixes #10029.
SUMMARY


ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


UI - ProjectList.jsx

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-29 14:39:24 +00:00
Maximilian Meister
d57f2ab496 Document usage of workflow job template nodes with approvals
Fixes #8777
2021-04-29 10:56:57 +02:00
softwarefactory-project-zuul[bot]
ba7b55bfe3 Merge pull request #10041 from mabashian/test-warning-cleanup-2
Unit test warning cleanup

SUMMARY
Cleans up warnings thrown on several unit tests
COMPONENT NAME

UI

Reviewed-by: Kersom <None>
2021-04-28 19:15:28 +00:00
softwarefactory-project-zuul[bot]
64efc2c006 Merge pull request #10037 from nixocio/ui_fix_warning
Fix a few unit-tests warnings

Fix a few unit-test warnings

Reviewed-by: Michael Abashian <None>
2021-04-28 19:14:45 +00:00
softwarefactory-project-zuul[bot]
028c48c409 Merge pull request #10042 from AlanCoding/old_docs
Remove inventory-related docs which are outdated or wrong

SUMMARY
Around 10% of this is updating docs for #9822
The rest of it is updating for changes that took place long ago, but docs still has stuff which is now wrong.
ISSUE TYPE

Docs Pull Request

COMPONENT NAME

API

Reviewed-by: Chris Meyers <None>
2021-04-28 18:56:23 +00:00
Alan Rominger
ee68dd00aa Remove inventory-related docs which are outdated or wrong 2021-04-28 14:00:05 -04:00
mabashian
6f7d594d0f Fix linting errors 2021-04-28 12:59:54 -04:00
mabashian
cc5a73aeb9 Fixes React does not recognize the ouiaId prop on a DOM element warning in NotificationTemplateList test 2021-04-28 12:59:54 -04:00
mabashian
04ca1cb1a3 Fixes Invalid prop credential.id of type number supplied to CredentialEdit, expected object warning in CredentialEdit test 2021-04-28 12:59:54 -04:00
mabashian
94b9892a1b Fixes bug with workflow form test throwing warning about Failed prop type: The prop value.name is marked as required in OrganizationLookup, but its value is undefined 2021-04-28 12:59:54 -04:00
mabashian
61f0edc5e8 Fix Each child in a list should have a unique "key" prop warnings in unit tests 2021-04-28 12:59:54 -04:00
softwarefactory-project-zuul[bot]
24a903142a Merge pull request #10035 from sean-m-sullivan/survey_idempotent
Make Workflow Surveys Idempotent

SUMMARY
Update the Workflow survey check to be in line with job template check.
Resolving issue #7554
Found that it was returning json/status_code, and needed to reference json output.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
awx_collection
AWX VERSION
19.0.0

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-04-28 15:56:06 +00:00
nixocio
1471945b9e Fix a few unit-tests warnings
Fix a few unit-test warnings
2021-04-28 10:29:28 -04:00
seiwailai
58147f8bc1 ProjectList: Fixes columns misalignment.
Fixes #10029.
2021-04-28 22:21:00 +08:00
softwarefactory-project-zuul[bot]
cd6e8969d5 Merge pull request #10034 from akus062381/add-locators-template-list-jsx
add ouiaId to toolbar delete button

In working on fixing a broken e2e test, I discovered an element that needed a better locator in order to allow testability.

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-28 13:48:14 +00:00
sean-m-ssullivan
c22c0a393c update tests and survey change status 2021-04-27 19:32:21 -05:00
akus062381
efd9e22adc fixed failing test 2021-04-27 16:53:35 -04:00
softwarefactory-project-zuul[bot]
acb6e3e6e9 Merge pull request #10032 from nixocio/ui_update_timeout
Bump timeout for unit-tests

Bump timeout for unit-tests.

Reviewed-by: Michael Abashian <None>
2021-04-27 20:17:42 +00:00
softwarefactory-project-zuul[bot]
31c35fd473 Merge pull request #10033 from mabashian/test-warning-cleanup-1
Fix warning thrown about CodeDetail rows prop

SUMMARY
Warning:
  ● Console

    console.error
      Warning: Invalid argument supplied to oneOfType, expected an instance of array.

      61 |   dataCy: string,
      62 |   helpText: string,
    > 63 |   rows: oneOfType(number, string),
         |         ^
      64 |   mode: oneOf(['javascript', 'yaml', 'jinja2']).isRequired,
      65 | };
      66 | CodeDetail.defaultProps = {

      at printWarning (node_modules/prop-types/factoryWithTypeCheckers.js:23:15)
      at createUnionTypeChecker (node_modules/prop-types/factoryWithTypeCheckers.js:365:47)
      at Object.<anonymous> (src/components/DetailList/CodeDetail.jsx:63:9)
      at Object.<anonymous> (src/screens/Setting/shared/SettingDetail.jsx:5:1)

Reviewed-by: Kersom <None>
2021-04-27 20:01:21 +00:00
softwarefactory-project-zuul[bot]
881ea1295f Merge pull request #10025 from shanemcd/better-errors
Improve error handling / display when Ansible Runner errors

Before you would see unhelpful error messages like:
Traceback (most recent call last):
  File "/var/lib/awx/venv/awx/lib64/python3.8/site-packages/awx/main/tasks.py", line 1397, in run
    res = receptor_job.run()
  File "/var/lib/awx/venv/awx/lib64/python3.8/site-packages/awx/main/tasks.py", line 2957, in run
    return self._run_internal(receptor_ctl)
  File "/var/lib/awx/venv/awx/lib64/python3.8/site-packages/awx/main/tasks.py", line 3008, in _run_internal
    raise RuntimeError(detail)
RuntimeError: exit status 0

Now you will see the underlying error:
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/ansible_runner/streaming.py", line 108, in run
    utils.unstream_dir(zip_data, self.private_data_dir)
  File "/usr/local/lib/python3.8/site-packages/ansible_runner/utils.py", line 104, in unstream_dir
    data = base64.b85decode(data)
  File "/usr/lib64/python3.8/base64.py", line 463, in b85decode
    raise ValueError('bad base85 character at position %d'
ValueError: bad base85 character at position 121

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-04-27 19:40:51 +00:00
mabashian
86aad8b910 Fix warning thrown about CodeDetail rows prop 2021-04-27 15:26:59 -04:00
Shane McDonald
8374b41e21 Improve error handling / display when Ansible Runner errors 2021-04-27 14:20:27 -04:00
nixocio
f9dc5cd32b Bump timeout for unit-tests
Bump timeout for unit-tests.
2021-04-27 14:15:08 -04:00
akus062381
b2497a84ad small change 2021-04-27 14:11:57 -04:00
akus062381
315018b274 small fix 2021-04-27 13:17:49 -04:00
akus062381
033adcb8b8 fixed locators 2021-04-27 13:13:50 -04:00
softwarefactory-project-zuul[bot]
54d50e2459 Merge pull request #10000 from sean-m-sullivan/project_update_fix
Fix project update

SUMMARY
Fixing bug found in #8686
Found that the on change was not triggering due to no actual changes in the Post, Set so when project update is set to true, that the wait for update is Always triggered. Also added logic from project_update to set changed status depending on if refspec changes.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

awx_collection

AWX VERSION
19.0.0

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: John Westcott IV <None>
Reviewed-by: Sean Sullivan <None>
Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-04-27 16:53:01 +00:00
softwarefactory-project-zuul[bot]
cca3698d19 Merge pull request #9965 from mabashian/8835-team-permissions
Hide teams option when adding access role to a team

SUMMARY
link #8835
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-27 14:34:09 +00:00
softwarefactory-project-zuul[bot]
bf892443df Merge pull request #10003 from jbradberry/analytics-4-week-logging
Log adjustments made to the analytics interval due to the 4-week limit

SUMMARY
If the user passes in the since and/or until parameters, sometimes they will be truncated to limit the data to only 4 weeks.  Emit a log message when this happens.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

AWX VERSION

Reviewed-by: Jim Ladd <None>
Reviewed-by: Chris Meyers <None>
Reviewed-by: Jeff Bradberry <None>
2021-04-27 13:55:56 +00:00
softwarefactory-project-zuul[bot]
35e778b7ae Merge pull request #9960 from mabashian/9955-cred-bool
Fixes bug where credential form checkboxes were erroneously checked

SUMMARY
link #9955
A couple of things going on here.

Updating initialValues.inputs was also modifying credential.inputs because initialValues.inputs was originally a reference to credential.inputs.  I changed this so that initialValues.inputs now starts off as a clone of credential.inputs.
https://github.com/ansible/awx/compare/devel...mabashian:9955-cred-bool?expand=1#diff-db8df3eaf3e3b3117f845786dea77451fba53e9d6a3f49ae367a26137039fc35L256 <- this line was erroneously evaluating to false when the value of an input was false.  We actually just want to make sure the key exists in the object before dropping in to this block.  This is what actually fixes the bug.  Before this change we would fall in to https://github.com/ansible/awx/compare/devel...mabashian:9955-cred-bool?expand=1#diff-db8df3eaf3e3b3117f845786dea77451fba53e9d6a3f49ae367a26137039fc35R268 where the checkbox value would be erroneously set.

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-27 13:49:14 +00:00
softwarefactory-project-zuul[bot]
5c03fa9e84 Merge pull request #9435 from nixocio/ui_issue_9433
Fix misalignment checkbox final build

Fix misalignment checkbox final build on Organization Lookup.
See: #9433

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-27 13:16:40 +00:00
nixocio
2b5fe0e6c4 Fix misalignment checkbox final build
Fix misalignment checkbox final build on Organization Lookup.

See: https://github.com/ansible/awx/issues/9433
2021-04-26 21:43:57 -04:00
softwarefactory-project-zuul[bot]
7095e266a5 Merge pull request #10024 from rooftopcellist/build_awx_docs
Add docs for building and using custom awx image

SUMMARY
Docs for how to build and push a custom AWX image to be used by the awx-operator.
ISSUE TYPE


Docs Pull Request

AWX VERSION

19.0.0

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-04-27 01:43:34 +00:00
sean-m-ssullivan
a75cbe683c project update fix 2021-04-26 16:17:02 -05:00
Jeff Bradberry
584fda5178 Add some unit tests around the analytics interval calculations 2021-04-26 16:21:25 -04:00
Christian M. Adams
191a25cccc Add docs for building and using custom awx image 2021-04-26 15:50:57 -04:00
softwarefactory-project-zuul[bot]
6267b264bf Merge pull request #9998 from nixocio/ui_update_pf
Update patternfly packages

Update patternfly packages

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-26 18:42:13 +00:00
Alex Corey
e6bde23aea Adds an execution environment step to the ad hoc commands 2021-04-26 14:02:36 -04:00
Jeff Bradberry
4857c5edcb Break out the main interval trimming calculation into a new function 2021-04-26 13:31:05 -04:00
Jeff Bradberry
f4d848e596 Log adjustments made to the analytics interval due to the 4-week limit 2021-04-26 13:31:05 -04:00
softwarefactory-project-zuul[bot]
1e7b7d1a30 Merge pull request #10021 from AlanCoding/black_upgrade
Modify formatting in response to black update

This seems to have changed sometime between versions 20.8b1 and 21.4b0

Reviewed-by: Seth Foster <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-04-26 15:42:20 +00:00
Alan Rominger
67f7998ab9 Modify formatting in response to black update 2021-04-26 10:51:27 -04:00
softwarefactory-project-zuul[bot]
0bdd873bd3 Merge pull request #9896 from sean-m-sullivan/approval_node
Add workflow approval and node wait modules

SUMMARY
Please see #9878 this is a clean PR after redoing my fork.
Add a module to find a workflow approval node and approve or deny it, based on Issue #8013.
Add a module to wait for a specific workflow node to complete and return information on it.
Both of these are based on tests I have been creating for testing workflows.
Scenario
Launch workflow
Wait for A node in the workflow to finish, compare output to expected output.
If it matches, approve the approval node, otherwise deny the approval node.
Workflow completes.
Even used in concert I've added the wait feature to both of these so a user can wait on either to appear.
This does require a workflow to use unique names on the job nodes they are waiting on, As the job # is created on the fly, it would be difficult for user to specify, A future update could explore searching for a specific identifier among a workflow template and then finding that job created by that identifier.
Currently without the modules this depends on generous use of the uri module, with until and retry coupled together.
ISSUE TYPE
Feature Pull Request

COMPONENT NAME
awx-collection
AWX VERSION
19.0.0

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-04-24 22:52:50 +00:00
softwarefactory-project-zuul[bot]
cf51dc5cea Merge pull request #9895 from sean-m-sullivan/workflow_schema
Tower workflow schema

SUMMARY
See #9309 This is a clean PR of that, after an errant rebase
Adds a way to add entire workflow node schemas to workflows. Either through the workflow schema module or the workflow job template module.
This speeds up workflow creation vs the workflow node module by 3x.
The model for the schemas is the format used by the tower_export module.
The main difference between this and the workflow node module is that the loops are done in python. Traditionally if you have a workflow with 10 nodes, ansible tasks need to be invoked 19 times. 1x to create the workflow, 10 x to initially create the nodes, and then one time for each node that is not an endpoint in the schema. This removes the need to loop and invoke many times.
ISSUE TYPE
Feature Pull Request

COMPONENT NAME
awx-collection
AWX VERSION
17.0.1

Reviewed-by: John Westcott IV <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-04-23 22:00:34 +00:00
softwarefactory-project-zuul[bot]
c29fda0385 Merge pull request #10013 from shanemcd/bump-runner-and-ee
Upgrade Ansible Runner and AWX EE

Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-04-23 19:20:06 +00:00
softwarefactory-project-zuul[bot]
203f5763ad Merge pull request #10011 from beeankha/remove_custom_source_option
Remove 'custom' as a Source Option from inventory_source Module

These changes are related to PR #9822

Reviewed-by: Alan Rominger <arominge@redhat.com>
2021-04-23 19:03:29 +00:00
Shane McDonald
0cbfd1129f Update to AWX EE 0.2.0 2021-04-23 14:32:42 -04:00
Shane McDonald
208bde6215 Update to Runner 2.0.0 alpha 2 2021-04-23 14:32:30 -04:00
beeankha
ac42604aa7 Remove 'custom' as a source option from inventory_source module 2021-04-23 13:31:42 -04:00
softwarefactory-project-zuul[bot]
a744f0d30f Merge pull request #9897 from AlexSCorey/9891-Plural
Properly tags Plural-able strings for translation, and removes unnecessary i18n

SUMMARY
This resolves #9891.
It also begings the process of remove i18n._(t string) in places in favor of this syntax
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

AWX VERSION



ADDITIONAL INFORMATION

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Kersom <None>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-23 17:12:04 +00:00
softwarefactory-project-zuul[bot]
555b25321e Merge pull request #9982 from jladdjr/jladd_explain_setting_gather_no_matter_what_devel
[devel] add clarifying comment re: AUTOMATION_ANALYTICS_LAST_GATHER being set regardless

(the comment in the changeset pretty much says it all)

Reviewed-by: Chris Meyers <None>
2021-04-23 17:07:13 +00:00
sean-m-ssullivan
ec312358e2 fix completeness 2021-04-23 11:57:24 -05:00
softwarefactory-project-zuul[bot]
fa02fd8563 Merge pull request #9995 from mabashian/7670-delete-workflow-survey
Fixes bug deleting the last workflow survey question

SUMMARY
link #7670

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-23 16:54:28 +00:00
softwarefactory-project-zuul[bot]
eb648d9447 Merge pull request #10002 from shanemcd/goodbye-binaries
Stop installing kubectl/oc

Realized this when looking at #9428

Reviewed-by: Chris Meyers <None>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-04-23 16:43:01 +00:00
Alex Corey
2143b60ebf remove snapshots 2021-04-23 12:34:40 -04:00
Alex Corey
4acae40d4a fixes spelling error 2021-04-23 12:31:39 -04:00
Alex Corey
71500a6554 Properly tags Plural-able strings for translation, and removes unnecessary i18n 2021-04-23 12:31:38 -04:00
softwarefactory-project-zuul[bot]
8e579b2e74 Merge pull request #9996 from AlexSCorey/RemoveSnapShots
Removes Snapshot tests

SUMMARY
Removes snapshot tests
ISSUE TYPE
COMPONENT NAME

UI

AWX VERSION



ADDITIONAL INFORMATION

Reviewed-by: Michael Abashian <None>
2021-04-23 15:08:29 +00:00
softwarefactory-project-zuul[bot]
78195a4203 Merge pull request #9999 from shanemcd/password-policies
Allow users to set password policies via AUTH_PASSWORD_VALIDATORS

Reviewed-by: Elyézer Rezende <None>
2021-04-23 14:45:21 +00:00
Shane McDonald
146fb720db Stop installing kubectl/oc
These are no longer needed with Container Groups v2 under Receptor
2021-04-23 09:15:15 -04:00
softwarefactory-project-zuul[bot]
9fd2c5ba16 Merge pull request #9993 from chrismeyersfsu/fix-gather_analytics_first_time_run
fix running analytics for the first time

related to #9992

Reviewed-by: Jeff Bradberry <None>
2021-04-23 12:09:43 +00:00
Shane McDonald
27c15caddd Allow users to set password policies via AUTH_PASSWORD_VALIDATORS 2021-04-22 18:13:36 -04:00
Jake McDermott
a7fe519063 Update patternfly packages 2021-04-22 17:00:26 -04:00
softwarefactory-project-zuul[bot]
8d20add2d5 Merge pull request #9943 from AlexSCorey/9115-SSOFix
Fixes SSO Redirect

SUMMARY
This fixes #9115 by simply checking if there is a redirect url in and then replacing it with the existing url in history, navigating the user to the correct login url.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
2021-04-22 20:47:52 +00:00
Alex Corey
4d339fe275 Removes Snapshot tests 2021-04-22 16:44:54 -04:00
mabashian
9bfbf8d556 Fixes bug deleting the last workflow survey question 2021-04-22 16:30:47 -04:00
softwarefactory-project-zuul[bot]
bcbf0bac8c Merge pull request #9994 from pabelanger/devel
Add bindep.txt file for execution environments

This will be used by ansible-builder, for people creating EEs.
Signed-off-by: Paul Belanger pabelanger@redhat.com

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-04-22 20:06:30 +00:00
Alex Corey
c64fec0d98 Fixes SSO Redirect 2021-04-22 15:36:21 -04:00
Paul Belanger
6fb57fb5fc Add bindep.txt file for execution environments
This will be used by ansible-builder, for people creating EEs.

Signed-off-by: Paul Belanger <pabelanger@redhat.com>
2021-04-22 15:27:39 -04:00
sean-m-ssullivan
224c3de2c9 linting 2021-04-22 13:39:34 -05:00
sean-m-ssullivan
ce1f3009f9 add tower workflow schema update 2021-04-22 13:39:33 -05:00
softwarefactory-project-zuul[bot]
4cd4845617 Merge pull request #9990 from tchellomello/issue_238_wait_db_populate
Wait for the database migrations before starting

cc: @shanemcd  @Spredzy
SUMMARY
Before starting the tower-task container, we should wait for the database schema migrations to complete to avoid misleading users.
This is much more evident on newer installations as the tower-task container will be noisy and populated with SQL errors which is a false positive due to the database being populated.
See the ansible/awx-operator#238 for more information
Fixes: ansible/awx-operator#238

ISSUE TYPE


Feature Pull Request

COMPONENT NAME


API

AWX VERSION

devel

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-04-22 17:51:37 +00:00
Chris Meyers
afe4279e5f fix running analytics for the first time 2021-04-22 13:40:30 -04:00
softwarefactory-project-zuul[bot]
88f70253a5 Merge pull request #9945 from AlanCoding/fileglob
Move to fileglob loop for yml requirement locations

SUMMARY
Overdue followup on #8312
I knew there was more research needed, but didn't know what form it would take until I got my hands dirty.
This entails a look and feel change.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

API

ADDITIONAL INFORMATION

It has a warning... but I don't dislike it.

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Jake Jackson  <jljacks93@gmail.com>
2021-04-22 16:06:48 +00:00
Marcelo Moreira de Mello
f397679cc5 Wait for the database migrations before starting 2021-04-22 11:51:39 -04:00
softwarefactory-project-zuul[bot]
3fc4baae06 Merge pull request #9975 from mabashian/9852-delete-inv-src
Fixes bug where users could not delete a single inventory source

SUMMARY
link #9852
Also fixes a bug that I came across with deletion warnings.  The deletion warning was showing a count for workflow nodes that referenced any inventory source with the same parent inventory.  For example:
Create an inventory
Create two inventory sources invsrc1 and invsrc2
Create a workflow with a node that syncs invsrc1
Attempt to delete invsrc2
The warning will indicate that there's 1 workflow node that uses the inventory source but that's actually not true.  There should be no deletion warning in this case.
This PR addresses ^^
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-22 15:29:08 +00:00
Jeff Bradberry
65cee65fad Update the docs to remove references to isolated nodes 2021-04-22 10:20:11 -04:00
Jeff Bradberry
17e3279f1c Remove isolated nodes from the API views and serializers 2021-04-22 10:20:11 -04:00
Jeff Bradberry
a17c34f041 Remove the isolation-specific settings
- AWX_ISOLATED_PUBLIC_KEY
- AWX_ISOLATED_PRIVATE_KEY
- AWX_ISOLATED_KEY_GENERATION
- AWX_ISOLATED_HOST_KEY_CHECKING
- AWX_ISOLATED_USERNAME
- AWX_ISOLATED_CONNECTION_TIMEOUT
- AWX_ISOLATED_LAUNCH_TIMEOUT
- AWX_ISOLATED_PERIODIC_CHECK
- AWX_ISOLATED_CHECK_INTERVAL
2021-04-22 10:20:11 -04:00
Jeff Bradberry
1819a7963a Make the necessary changes to the models
- remove InstanceGroup.controller
- remove Instance.last_isolated_check
- remove .is_isolated and .is_controller methods/properties
- remove .choose_online_controller_node() method
- remove .supports_isolation() and replace with .can_run_containerized
- simplify .can_run_containerized
2021-04-22 10:17:02 -04:00
Jeff Bradberry
6a599695db Remove the IsolatedManager and its associated playbooks and plugins 2021-04-22 10:17:02 -04:00
Jeff Bradberry
b0cdfe7625 Clean up the management commands 2021-04-22 10:11:27 -04:00
Jeff Bradberry
efabc05270 Chop out the dev environment isolated node 2021-04-22 10:11:27 -04:00
softwarefactory-project-zuul[bot]
c1a009d128 Merge pull request #9958 from AlexSCorey/9910-PluralAriaLabel
Fixes object rendered on dom in aria-label

SUMMARY
This addresses #9910. Aria-labels that use <Plural/> won't work properly.  In this case I used aria-labelledby and passed it the id of the button.  I tested it with a screen reader and that fixed it.  I also fixed some JobListCancelButton tooltips
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-22 13:45:01 +00:00
softwarefactory-project-zuul[bot]
8142f5fb55 Merge pull request #9822 from AlanCoding/boom_no_scripts
Remove custom inventory scripts from the API

SUMMARY
Connect #7775
AWX VERSION
18.0.0

Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-04-22 13:17:15 +00:00
Alan Rominger
8241ebbc9a Fix migration order of operations bug 2021-04-22 08:36:49 -04:00
Alan Rominger
5f39b6276d Add command to export custom inventory scripts to tar file 2021-04-22 08:36:48 -04:00
Alan Rominger
8c0366675a Remove source_script from awx collection 2021-04-22 08:36:48 -04:00
Alan Rominger
b40e8d15c0 Fix migration bug
Bump migration number

Skip data migration for fresh migrations
  where ContentType for custom inventory scripts
  has not yet been created
    no scripts will exist in this case, so no-op
2021-04-22 08:36:48 -04:00
Alan Rominger
f28ad90bf3 Remove source_script field from serializers
Remove some other uses of source_script
2021-04-22 08:36:48 -04:00
Alan Rominger
8440e3f41d Remove ForeignKey relations involving CustomInventoryScript
Add migration to carry out corresponding schema change

Add data migration to delete inventory sources
  which are the custom type

Split migration into two files
  data migration touches same rows as schema migration
2021-04-22 08:36:48 -04:00
Alan Rominger
33b6da4456 Remove filter_by_class where it was not working 2021-04-22 08:36:48 -04:00
Alan Rominger
a54aab9717 Remove old uses of CustomInventoryScript
some uses are minor references

Fix some test fails
2021-04-22 08:36:48 -04:00
Alan Rominger
38352063e8 Remove custom inventory script API 2021-04-22 08:36:46 -04:00
Alan Rominger
855cb162b7 Change inventory source factory defaults
Also set source_path to a newly merged test-playbooks script
  this gives similar behavior to the prior default script
2021-04-22 08:34:38 -04:00
Jim Ladd
fb97a79aca add clarifying comment re: AUTOMATION_ANALYTICS_LAST_GATHER being set regardless 2021-04-21 21:28:32 -07:00
softwarefactory-project-zuul[bot]
4a8c63c579 Merge pull request #9649 from jakemcdermott/pkg-updates
Fix problematic dependencies

SUMMARY
Fixes high-severity warnings for problematic dependencies.
These fixes required updating react-scripts to a later version, which broke many of our tests due to breaking changes in how test setup works. As such, this PR also updates a lot of tests.

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-04-21 23:04:01 +00:00
softwarefactory-project-zuul[bot]
2740155877 Merge pull request #9883 from shanemcd/remove-resource-profiling
Remove resource profiling feature

Reviewed-by: Ryan Petrello <ryan@ryanpetrello.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-21 22:25:51 +00:00
softwarefactory-project-zuul[bot]
e67b5f57b4 Merge pull request #9951 from shanemcd/ignore-tls-container-registries
Add option for ignoring tls on Container Registry credentials

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-21 22:18:50 +00:00
Shane McDonald
cfc8b485ee Fix linter 2021-04-21 17:48:21 -04:00
Shane McDonald
21c493724c Remove resource profiling feature 2021-04-21 17:47:45 -04:00
Shane McDonald
658543c0fd Fix up some test fallout 2021-04-21 17:40:43 -04:00
Jake McDermott
562ba53833 Update to react-scripts 4
Co-authored-by: nixocio <nixocio@gmail.com>
2021-04-21 17:33:34 -04:00
Shane McDonald
17b8589ff2 Add option for ignoring tls on Container Registry credentials 2021-04-21 16:28:13 -04:00
Alex Corey
2d2d7b14a9 fixes object rendered on dom in aria-label 2021-04-21 16:07:13 -04:00
Shane McDonald
bcf911daf1 Fix permission assignment on rendered registry auth files
- This file shouldnt need the executable bit
- Should have been setting permissions before writing any data
- No need to close the file since we're using open w/ a context manager
2021-04-21 16:03:11 -04:00
mabashian
968c056057 Fix typo in test mock 2021-04-21 14:47:08 -04:00
mabashian
c48fbec30c Fixes bug where users could not delete a single inventory source 2021-04-21 14:42:38 -04:00
softwarefactory-project-zuul[bot]
0cdf57f31f Merge pull request #9974 from shanemcd/stop-using-devel
Stop instructing folks to install from devel

Reviewed-by: Chris Meyers <None>
2021-04-21 18:00:27 +00:00
Shane McDonald
edaec8dfbb Stop instructing folks to install from devel 2021-04-21 13:22:03 -04:00
softwarefactory-project-zuul[bot]
eec4f8dcc2 Merge pull request #9973 from shanemcd/fix-adhoc-commands
Fix issue where ad-hoc commands for multiple hosts ran on single host

Should resolve #9685

Reviewed-by: Matthew Jones <bsdmatburt@gmail.com>
2021-04-21 17:17:36 +00:00
softwarefactory-project-zuul[bot]
5ef7dd894a Merge pull request #9600 from keithjgrant/3167-variables-formatting
Initialize variables field/detail with formatted JSON strings

SUMMARY
When a variables detail or variables field are mounted with JSON code, this ensures the JSON is formatted with friendly whitespace, regardless how it was originally formatted when saved.
addresses #3167
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-21 17:07:46 +00:00
Shane McDonald
7fd5a4e79a Fix issue where ad-hoc commands for multiple hosts ran on single host 2021-04-21 12:41:51 -04:00
softwarefactory-project-zuul[bot]
b862434bec Merge pull request #9689 from rooftopcellist/i18n_devel_translations
I18n devel translations

SUMMARY
First round of translations for ui_next.  I have also included:

necessary changes to import fr, nl, es, zh, and also add them to the catalog.
fixed a syntax error that was keeping strings from compiling.

ISSUE TYPE


Feature

COMPONENT NAME


Translations

AWX VERSION

devel

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
2021-04-21 15:00:29 +00:00
softwarefactory-project-zuul[bot]
f5a69d37dc Merge pull request #9971 from ansible/chrismeyersfsu-more_debug_docs
add slow query tracing to docs

Add information on how to trace slow queries back to awx nodes.

Reviewed-by: Jeff Bradberry <None>
2021-04-21 14:26:04 +00:00
Chris Meyers
54a1712767 add slow query tracing to docs
Add information on how to trace slow queries back to awx nodes.
2021-04-21 09:02:24 -04:00
mabashian
fe4440f7e9 Hide teams option when adding access role to a team 2021-04-20 17:29:10 -04:00
softwarefactory-project-zuul[bot]
ddcbef8545 Merge pull request #9932 from marshmalien/5070-expanded-project-list
Add expanded row content to project list

SUMMARY
#5070
Add the following details to expanded area:

Description
Organization
Execution Environment
Last modified
Last used


ISSUE TYPE


Feature Pull Request

COMPONENT NAME


UI

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-20 21:10:15 +00:00
softwarefactory-project-zuul[bot]
fc2d877983 Merge pull request #9964 from tiagodread/update-ouiaid-relaunch-feature
Adding ouiaid to RelaunchDropdown.jsx

Adding testability to this component

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-20 20:47:55 +00:00
Christian M. Adams
40be9607ee Importing the langs is now done in the lingui config 2021-04-20 16:34:23 -04:00
akus062381
673579fe26 adding ouiaid to relaunchdropdown.jsx 2021-04-20 17:06:51 -03:00
softwarefactory-project-zuul[bot]
0ca024c929 Merge pull request #9912 from fosterseth/fix_t4919_jt_slow_load
Return distinct labels for normal Users

SUMMARY


Create a single label and add it to 2 or more JTs
Visit /api/v2/labels as superuser and you'll see a single label
Create a normal user and give admin role to each JT in step 1
Visit /api/v2/labels as this normal user and you will see duplicate entries for the label. Number of entries will be equal to the number of JTs in step 1


ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.0.0

Reviewed-by: Seth Foster <None>
Reviewed-by: Jeff Bradberry <None>
2021-04-20 17:22:35 +00:00
mabashian
07d08b57d1 Fixes typo 2021-04-20 13:12:31 -04:00
mabashian
9540ed4364 Fixes bug where credential form checkboxes were erroneously checked 2021-04-20 13:00:44 -04:00
softwarefactory-project-zuul[bot]
182d4d3098 Merge pull request #9907 from fosterseth/feat_a9212_image_cleanup
Add cleanup_images scheduled task

SUMMARY

#9212
Removes dangling podman images on the system
[70e6cc8a] awx.main.tasks Cleanup execution environment images: deleting quay.io/fosterseth/awx-ee:v1, 643 MB

ISSUE TYPE


Feature Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.0.0

Reviewed-by: Seth Foster <None>
Reviewed-by: Ryan Petrello <ryan@ryanpetrello.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-04-20 16:03:24 +00:00
Marliana Lara
95db251314 Test project list row renders expanded details 2021-04-20 11:28:17 -04:00
Seth Foster
8ab81216f3 unused import 2021-04-20 11:16:32 -04:00
Seth Foster
1e3cfdc986 just remove dangling images 2021-04-20 11:16:32 -04:00
Seth Foster
c64ec6bbf8 check if is_k8s 2021-04-20 11:16:32 -04:00
Seth Foster
4566e7a2a6 check subprocess returncode 2021-04-20 11:16:32 -04:00
Seth Foster
3912f2b57c remove migration file 2021-04-20 11:16:32 -04:00
Seth Foster
fa61ec6b3c Remove system job, replace with scheduled task 2021-04-20 11:16:31 -04:00
Seth Foster
33567f8729 delete_prefix local 2021-04-20 11:16:31 -04:00
Seth Foster
1c888ca58b cleanup stdout 2021-04-20 11:16:31 -04:00
Seth Foster
f98b92073d Add cleanup_images system job template
- Removes podman images on the system that are not assigned to an
execution environment
2021-04-20 11:16:31 -04:00
softwarefactory-project-zuul[bot]
1d89ecaf4f Merge pull request #9954 from jbradberry/missing-dry-run-check
Add in the missing dry-run check for csv analytics collectors

SUMMARY
Follow on bug fix for the analytics gathering feature.  @chrismeyersfsu noticed that dry-run gathers of sufficiently large data was breaking out of the loop after the first csv chunk was packaged.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

AWX VERSION
awx: 19.0.0

Reviewed-by: Chris Meyers <None>
Reviewed-by: Elijah DeLee <kdelee@redhat.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Julen Landa Alustiza <None>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-04-20 15:10:43 +00:00
Seth Foster
7583525366 Return distinct labels for non-admin Users 2021-04-20 10:59:38 -04:00
Christian M. Adams
b729377a2c Fix syntax error with fr translations 2021-04-20 10:57:10 -04:00
Christian M. Adams
c7de869a07 Manually commit in translated ui_next strings 2021-04-20 10:49:46 -04:00
ansible-translation-bot
459874e4b5 UI translation strings for devel branch 2021-04-20 10:24:09 -04:00
Marliana Lara
329df4c0b5 Add expanded row section to project list 2021-04-20 10:10:06 -04:00
Jeff Bradberry
b9389208dd Add in the missing dry-run check for csv analytics collectors 2021-04-20 09:36:29 -04:00
softwarefactory-project-zuul[bot]
ce588a6af5 Merge pull request #9950 from tiagodread/ouia-ids
[Testability] Job template details delete button

Resolves #9510

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-20 00:34:41 +00:00
softwarefactory-project-zuul[bot]
7223ab4d29 Merge pull request #9899 from seiwailai/issue-9898-invalid-type-field
metadata: Fixes invalid model classes field.

Fixes #9441.
SUMMARY

Set type' field's filterable as True only if the model classes contain type field such as UnifiedJob, WorkflowApproval, UnifiedJobTemplate, Project and SystemJobTemplate

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API - metadata.py

AWX VERSION

awx: 19.0.0

ADDITIONAL INFORMATION

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Sei Wai Lai <None>
2021-04-19 22:44:53 +00:00
Tiago
8135ac4883 job template details delete button 2021-04-19 19:38:25 -03:00
softwarefactory-project-zuul[bot]
16bd9b44dc Merge pull request #9933 from marshmalien/4977-expanded-job-list
Add expanded row content to job list

SUMMARY
#4977
Add the following details to expanded section:

Job Template
Workflow Job Template
Source Workflow Job
Project
Execution Environment


ISSUE TYPE


Feature Pull Request

COMPONENT NAME


UI

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-19 22:28:55 +00:00
softwarefactory-project-zuul[bot]
a857352e30 Merge pull request #9940 from seiwailai/issue-9911-not-display-error-message
CredentialPluginField: Fixes bug to display invalid helper text for empty required field.

Fixes #9911. Include the HTML element of displaying helper text which is similar to FormGroup.tsx's inValidHelperText implementation
Signed-off-by: seiwailai laiseiwai@gmail.com
SUMMARY

Under normal circumstances, we initiate input fields using FormGroup element. However, for credentials purpose, we customized the FormGroup by adding another children element called CredentialPluginInput which comprised of Input Group. Thus, events related to the input fields will happen within the InputGroup logic. However, the Input Group doesn't have the functionality of rendering error at the moment.
Thus, we should explicitly render the error under FormGroup element if there is an error and needed to be displayed.

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


UI: CredentialPluginField.jsx

AWX VERSION

awx=19.0.0

ADDITIONAL INFORMATION


After

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-19 22:20:50 +00:00
softwarefactory-project-zuul[bot]
19da1ad263 Merge pull request #9925 from keithjgrant/4249-prevent-double-launch
Prevent double-clicking/double-launching jobs

SUMMARY
Prevents double-launching a job if the user double-clicks the launch icon. This is done by disabling the button upon first launch. Applied to all instances of <LaunchButton>.
Addresses: #4249
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-19 22:17:21 +00:00
softwarefactory-project-zuul[bot]
e346dbfc97 Merge pull request #9934 from DiegoTc/devel
Updating installation documentation 

Updating installation documentation due to bug. Adding this will prevent users to encounter errrors at the moment of installing awx.
SUMMARY

New users will encounter problems installing awx, as there's a bug using a specific version of minikube. Adding a note, so users are aware of this and don't struggle in the installation process.

ISSUE TYPE


Docs Pull Request

AWX VERSION

latest

ADDITIONAL INFORMATION


https://github.com/ansible/awx-operator/issues/205

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-04-19 21:58:00 +00:00
Keith J. Grant
dff43e973e add LaunchButton test to cover disabled launch button behavior 2021-04-19 13:09:16 -07:00
Alan Rominger
27d56726a3 Remove yaml_exts play variable 2021-04-19 15:55:29 -04:00
Alan Rominger
032341c7fc Move to fileglob loop for yml requirement locations 2021-04-19 15:45:51 -04:00
seiwailai
a4de7fffaf metadata: Fixes invalid model classes field.
Fixes #9441.
2021-04-20 02:51:46 +08:00
Keith J. Grant
804cf74cd8 fix formatting JSON on initialize 2021-04-19 11:00:27 -07:00
Keith J. Grant
b817967377 delete unused function 2021-04-19 09:38:50 -07:00
Keith J. Grant
768fe94088 initialize variables field/detail with formatted JSON strings 2021-04-19 09:37:42 -07:00
softwarefactory-project-zuul[bot]
8375141d67 Merge pull request #9942 from shanemcd/dont-reap-pods-when-debugging
Dont reap pods when settings.RECEPTOR_RELEASE_WORK = False

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-04-19 16:06:50 +00:00
Keith J. Grant
5e228c4d98 LaunchButton: rename isSending to isLaunching 2021-04-19 09:05:15 -07:00
Shane McDonald
e30b4ca875 Dont reap pods when settings.RECEPTOR_RELEASE_WORK = False 2021-04-19 09:06:23 -04:00
seiwailai
850d04b5c0 CredentialPluginField: Fixes bug to display invalid helper text for empty required field.
Fixes #9911. Include the jsx element of displaying helper text which is similar to FormGroup.tsx's inValidHelperText implementation

Signed-off-by: seiwailai <laiseiwai@gmail.com>
2021-04-19 14:09:16 +08:00
Diego Turcios
54cb303ac5 Signed-off-by: Diego Turcios <diegoturciostc@gmail.com>
Updating installation documentation due to [bug](https://github.com/ansible/awx-operator/issues/205). Adding this will prevent users to encounter errrors at the moment of installing awx.
2021-04-16 19:34:33 -06:00
Marliana Lara
956cffe073 Add missing details to job list expanded row section 2021-04-16 15:31:08 -04:00
softwarefactory-project-zuul[bot]
d834519aae Merge pull request #9914 from dhoppe/fix_architecture
Define variables in the correct Ansible role

SUMMARY
This pull request is related to #9913.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

Docker

AWX VERSION
awx: 19.0.0

ADDITIONAL INFORMATION
This pull request ensures that tini is downloaded for the correct architecture.
$ grep tini Dockerfil
# Install tini
RUN curl -L -o /usr/bin/tini https://github.com/krallin/tini/releases/download/v0.19.0/tini-arm64 && \
    chmod +x /usr/bin/tini

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-04-16 17:41:41 +00:00
softwarefactory-project-zuul[bot]
d53d41b84a Merge pull request #9776 from AlexSCorey/9019-MultiChart
Observability Metrics

SUMMARY
This adds the chart for Observability Metrics (#9019).  To see the chart you need to navigate to /metrics.  Also, its best if you run a build that has multiple instances.  This will do that for you COMPOSE_TAG=devel CLUSTER_NODE_COUNT=2 make docker-compose.
When this feature loads the user has to select an instance (1, or all) and a metric to render data on the graph.  Once they select those items, the chart appears and we start to make requests to the api every 3 seconds to get the data. (Currently the api does not support web sockets for this feature) If the user changes the values for either of the drop down items the chart resets.  The chart also only show the last 50 data points.
There is a "tooltip" that is rendered at the bottom left hand side.  I decided to put it there, instead of on the chart itself because this chart could get quite crowded depending the number of data points rendered and the number of instances rendering lines.
The X axis is sort of meaningless.  The values below simply render the number of api requests. This isn't a value of time. Since the main goal of this feature is to show significant changes instead of tryin to pinpoint when the change occurs I felt that showing a time stamp on this axis would crowd the axis as well.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Kersom <None>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Mat Wilson <mawilson@redhat.com>
2021-04-15 21:59:28 +00:00
softwarefactory-project-zuul[bot]
a194dfdbbb Merge pull request #9884 from nixocio/ui_issue_9769
Do not allow EE to modify Org

Do not allow EE to modify Org.
See: #9769
Also: #9874

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-15 21:59:19 +00:00
Keith J. Grant
dc0256441f disable launch buttons to prevent double-clicking 2021-04-15 14:51:39 -07:00
softwarefactory-project-zuul[bot]
08a969bf8b Merge pull request #9922 from jbradberry/write-pre-commit-always
Always overwrite the contents of .git/hooks/pre-commit

SUMMARY
Set the make command to always write into the pre-commit hook file, even if it already exists.  This will allow this file to be updated when changes are made without the developer having to jump through hoops or remember that it is a thing.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

API

AWX VERSION

Reviewed-by: Ryan Petrello <None>
2021-04-15 20:25:26 +00:00
Jeff Bradberry
2793b5b01e Always overwrite the contents of .git/hooks/pre-commit 2021-04-15 14:21:53 -04:00
softwarefactory-project-zuul[bot]
32200cd893 Merge pull request #9875 from keithjgrant/a11y-fixes
Accessibility fixes

SUMMARY
Fixes numerous accessibility issues, including:

updates CodeEditor so label correctly points at associated textarea
fixes issues with tabs on dashboard and details pages
adds missings ids
adds alt text to logo
removes duplicate ids on some lists

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-15 17:39:07 +00:00
softwarefactory-project-zuul[bot]
6fef4e1ab7 Merge pull request #9593 from keithjgrant/7506-yaml-json-eval-fix-2
Don't unnecessarily expand YAML expressions

SUMMARY
Prevents variables fields from expanding YAML expressions when possible:

In the detail view, the user may toggle to JSON (seeing the data structure fully expanded), but toggling back to YAML will continue to display the original un-expanded value with expressions intact
In edit mode, this works the same way, UNLESS the user edits the value while in JSON mode.

Addresses #7506
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Chris Meyers <None>
2021-04-15 17:34:44 +00:00
softwarefactory-project-zuul[bot]
ad07d31b9a Merge pull request #9219 from mazhead/devel
Adding the scm_track_submodules option for project

SUMMARY
Adding the scm_track_submodules option which should fix the related #7846
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

API
UI

AWX VERSION
awx: 17.0.1

ADDITIONAL INFORMATION
This option will add the track_submodules option which is described in the ansible git module: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/git_module.html

if yes, submodules will track the latest commit on their master branch (or other branch specified in .gitmodules). If no, submodules will be kept at the revision specified by the main project. This is equivalent to specifying the --remote flag to git submodule update.

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: None <None>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
2021-04-15 17:28:41 +00:00
mazhead
5bb93e1f5d Update SharedFields.jsx 2021-04-15 15:23:05 +02:00
nixocio
95f5188462 Do not allow EE to modify Org
Do not allow EE to modify Org.

See: https://github.com/ansible/awx/issues/9769
2021-04-15 09:11:26 -04:00
Dennis Hoppe
1d4a83e613 Define variables tini_architecture and kubectl_architecture in the correct Ansible role 2021-04-15 12:38:49 +02:00
Keith J. Grant
8f2ef6ce01 VariablesField: don't run Formik validation on mode change 2021-04-14 16:15:18 -07:00
softwarefactory-project-zuul[bot]
c633313152 Merge pull request #9903 from nixocio/ui_remove_not_used_code
Remove not used code

Remove not used code

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-14 16:35:08 +00:00
Keith J. Grant
637b540a4d fix button selection in VariablesField tests 2021-04-14 09:25:15 -07:00
Keith J. Grant
8dd4e68385 change CodeEditor onChange back to our debounce implementation 2021-04-14 09:25:15 -07:00
Keith J. Grant
dff3103d96 add more robust handling of JSON/YAML toggle to prevent expanding YAML expressions 2021-04-14 09:25:15 -07:00
Keith J. Grant
1bd71024e3 Don't unecessarily expand YAML expressions
If the user toggles a VariablesField to JSON then back to YAML without
editing the field content, revert to the initial YAML value to maintain
any shorthand expressions
2021-04-14 09:22:57 -07:00
Keith J. Grant
634c9892df VariablesDetail: don't evaluate YAML expressions 2021-04-14 09:13:53 -07:00
nixocio
7435458a7b Remove not used code
Remove not used code
2021-04-14 10:36:18 -04:00
softwarefactory-project-zuul[bot]
2ebd4c72c1 Merge pull request #9862 from jakemcdermott/remove-suppress
Use built-in suppress from contextlib

In python3, we use the built-in suppress from contextlib.

Reviewed-by: Ryan Petrello <None>
2021-04-14 12:35:39 +00:00
Keith J. Grant
e05fdf9ebb update tests to match new ids 2021-04-13 13:11:44 -07:00
Keith J. Grant
1dc3b80c68 add missing titles/labels, remove duplicate IDs 2021-04-13 13:11:44 -07:00
Keith J. Grant
77cc3306a5 add typeahead aria labels to all Select boxes 2021-04-13 13:11:44 -07:00
Keith J. Grant
f807b76044 revert RoutedTabs to buttons pending PF fix 2021-04-13 13:11:44 -07:00
Keith J. Grant
ac0f534208 update inventory group tests 2021-04-13 13:11:44 -07:00
Keith J. Grant
c738772cd5 translate brand logo alt text 2021-04-13 13:11:44 -07:00
Keith J. Grant
79118cfbe2 fix Schedule tests 2021-04-13 13:11:44 -07:00
Keith J. Grant
445b2fef84 update VariablesField test for new id 2021-04-13 13:11:44 -07:00
Keith J. Grant
94038006aa fix a11y bugs in RoutedTabs, UserList 2021-04-13 13:11:44 -07:00
Keith J. Grant
be9622d03f fix missing ids/alt for a11y fixes 2021-04-13 13:11:44 -07:00
Keith J. Grant
03fbeb2a27 fix a11y labels on dashboard tabs 2021-04-13 13:11:43 -07:00
Keith J. Grant
30f08582ed add id to code editor input fields 2021-04-13 13:11:43 -07:00
softwarefactory-project-zuul[bot]
6dd5fc937b Merge pull request #9683 from rebeccahhh/devel
Pull with credentials from protected registries

SUMMARY

relates to #7066
if a credential is associated with an EE this will create a JSON authfile that is then passed with the pull request to the host of the registry

ISSUE TYPE


Feature Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 18.0.0


TODOs

 Remove separate token field from the registry credential.
 Rename the existing password field to say "password/token"
 Ensure only registry credentials can be associated with an EE #9628
 Write out the auth.json file to the pdd_wrapper_ directory. #9683 (comment)
 Use secure permissions for auth.json #9683 (comment)

Reviewed-by: Ryan Petrello <None>
Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Rebeccah Hunter <rhunter@redhat.com>
Reviewed-by: Elijah DeLee <kdelee@redhat.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Nana  <natr@hey.com>
2021-04-13 20:09:52 +00:00
mazhead
83d340ab1f Updated migration + serializers as suggested
Signed-off-by: mazhead <mazhead@gmail.com>
2021-04-13 21:39:24 +02:00
softwarefactory-project-zuul[bot]
b82318161c Merge pull request #9890 from ryanpetrello/schedule-invalid-ujt
allow schedules to be disabled even if the associated UJT isn't valid

see: #8641

Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Jeff Bradberry <None>
2021-04-13 17:20:51 +00:00
Alex Corey
90081e4e6e updates file names and adds breadcrumb 2021-04-13 12:40:05 -04:00
softwarefactory-project-zuul[bot]
cd372e4c74 Merge pull request #9889 from ryanpetrello/cors-allow-list
update django-cors-headers and switch to inclusive settings name

see: #9177

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
2021-04-13 16:38:15 +00:00
Alex Corey
b933155f07 fixes some domain issues for x and y axis 2021-04-13 12:13:25 -04:00
Alex Corey
51257a2f62 Adds observability metrics chart
wip

tooltip renders with colors and disappears

scales y axis properly

adds legend without buttlets

adds legend data but needs styling

adds legend, and cleans up code

show help text
2021-04-13 12:13:25 -04:00
Rebeccah
0d2ab5f61e add in OR to the UI label for editing a registry credential 2021-04-13 11:54:44 -04:00
Shane McDonald
4a62932ecd Store auth.json is pdd_wrapper directory 2021-04-13 11:54:43 -04:00
Rebeccah
e61d0c5cb7 credential validation for execution envs to allow only registry credentials to be associated with them, also adding security precautions for authfile and password, also combined token & password into one term to align with Quay, and added handling to account for users not filling in credential data and add a has_inputs function to simplify checking if the host, username, and password are present in the credential 2021-04-13 11:54:33 -04:00
Rebeccah
7c57aebd46 if there is a credential associated with an EE, create a JSON structure and write it to a file, then use that file to pull from protected registries from quay and edit the credential type for registries so that they combine the password and token fields into one field 2021-04-13 11:50:29 -04:00
softwarefactory-project-zuul[bot]
98bb296c6a Merge pull request #9874 from fosterseth/fix_a9769_ee_rbac_change_org
Prevent execution environment from being assigned to a new organization

SUMMARY

related #9769

ee organization can be changed to null (less restrictive)
if organization is null, cannot be assigned to org (more restrictive)
if org is assigned, it cannot be set to a different org


ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 19.0.0

Reviewed-by: Kersom <None>
Reviewed-by: Chris Meyers <None>
Reviewed-by: Jeff Bradberry <None>
Reviewed-by: Seth Foster <None>
2021-04-13 15:24:44 +00:00
softwarefactory-project-zuul[bot]
e67923382a Merge pull request #9892 from ryanpetrello/record-unit-id
record the receptor unit ID on the job record for debugging purposes

see: #8641

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-04-12 21:31:35 +00:00
softwarefactory-project-zuul[bot]
4de7cf0296 Merge pull request #9835 from ryanpetrello/saml-galaxy-cred
automatically setup default Galaxy credentials on SAML login

Reviewed-by: Chris Meyers <None>
2021-04-12 21:16:19 +00:00
Ryan Petrello
4db3c36ac3 record the receptor unit ID on the job record for debugging purposes
see: https://github.com/ansible/awx/issues/8641
2021-04-12 16:53:51 -04:00
softwarefactory-project-zuul[bot]
f5c00431bd Merge pull request #7391 from xstasi/devel
Add tower group for collection modules

SUMMARY
It would be useful to be able to declare module defaults for all tower modules, which is accomplished with module groups.
See: https://docs.ansible.com/ansible/latest/user_guide/playbooks_module_defaults.html
This very simple PR adds the group definition

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2021-04-12 20:53:02 +00:00
Ryan Petrello
b5f77bfe4c allow schedules to be disabled even if the UJT isn't valid
see: https://github.com/ansible/awx/issues/8641
2021-04-12 16:01:52 -04:00
Ryan Petrello
f137ff7d43 update django-cors-headers and switch to inclusive settings name
see: https://github.com/ansible/awx/issues/9177
2021-04-12 15:14:27 -04:00
Jake McDermott
2c61e8f6de Use built-in suppress from contextlib
In python3, we can use the built-in suppress from contextlib

https://docs.python.org/3/library/contextlib.html#contextlib.suppress
2021-04-12 14:47:50 -04:00
Seth Foster
1e4b44e54f Prevent ee from being assigned to a new organization
- ee organization can be changed to null (less restrictive)
- if organization is null, cannot be assigned to org (more restrictive)
- if org is assigned, it cannot be set to a different org
2021-04-12 14:15:21 -04:00
softwarefactory-project-zuul[bot]
c72cc6486c Merge pull request #9537 from AlexSCorey/lingUIUpdate
Updates Ling UI

SUMMARY
This PR updates Ling ui. One of the reasons for updating this dependency was that they were deprecating withI18n().  They changed their minds on that so we didn't need to urgently remove all those HOCs.  Thus, we can now make that conversion a bit slower a couple of files at a time.
One other thing:  When we are changing the string based on a count of an item (ie. Cancel Job vs. Cancel Jobs) we should use ling ui's <Plural> component. However, in order to show the update strings passed to that component the developer will have to run npm run extract-strings each time they are changed to render the updated strings properly. More info here.
ISSUE TYPE
-dependency  upgrade
COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Kersom <None>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Sergio Moreno <sergiomorenoalbert@gmail.com>
2021-04-12 17:57:27 +00:00
softwarefactory-project-zuul[bot]
9ee7281b0b Merge pull request #9886 from ryanpetrello/autoflake
sprinkle back in some flake8 to catch missing imports

Reviewed-by: Shane McDonald <me@shanemcd.com>
Reviewed-by: Christian Adams <rooftopcellist@gmail.com>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Ryan Petrello <None>
2021-04-12 17:35:40 +00:00
mazhead
5f93ba7690 Update awx/ui_next/src/screens/Project/shared/ProjectSubForms/SharedFields.jsx
Accept suggestion

Co-authored-by: Shane McDonald <me@shanemcd.com>
2021-04-12 19:02:51 +02:00
Ryan Petrello
300f5a3a1f use flake8 to lint for a few things black doesn't catch
black does *not* warn about missing or extraneous imports,
so let's bring back flake8 in our linting to check for them
2021-04-12 12:55:39 -04:00
mazhead
9f68ffc1cc Update default
Signed-off-by: mazhead <mazhead@gmail.com>
2021-04-12 18:27:16 +02:00
softwarefactory-project-zuul[bot]
ae1fd5a814 Merge pull request #9885 from beeankha/remove_old_tower_name_from_docs
Change Reference of 'ansible-tower-service' to 'automation-controller-service' in Docs File

Related to the work done in #9720

Reviewed-by: Shane McDonald <me@shanemcd.com>
2021-04-12 15:29:07 +00:00
mazhead
f1a987793c Black fix
Signed-off-by: mazhead <mazhead@gmail.com>
2021-04-12 16:58:28 +02:00
beeankha
7c13d749b1 Change 'ansible-tower-service' to 'automation-controller-service' 2021-04-12 10:56:55 -04:00
mazhead
d479237734 Fix merge issue
Signed-off-by: mazhead <mazhead@gmail.com>
2021-04-12 16:47:44 +02:00
softwarefactory-project-zuul[bot]
bdd41c70af Merge pull request #9847 from fosterseth/fix_t4922_job_elapsed_time_incorrect
Fix elapsed time on job showing incorrect value

SUMMARY

Elapsed time would always stay at zero

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME


API

AWX VERSION

awx: 18.0.0

Reviewed-by: Seth Foster <None>
Reviewed-by: Ryan Petrello <None>
Reviewed-by: Alan Rominger <arominge@redhat.com>
Reviewed-by: Jeff Bradberry <None>
2021-04-12 14:35:04 +00:00
mazhead
c6eb7da68d Adding the scm_track_submodules option which should fix the https://github.com/ansible/awx/issues/7846
Signed-off-by: mazhead <mazhead@gmail.com>
2021-04-12 16:22:23 +02:00
softwarefactory-project-zuul[bot]
311c44341e Merge pull request #9873 from wenottingham/not-any-more-they-arent
Update templates for installer changes

SUMMARY
Some of the options aren't valid any more.

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-09 22:20:47 +00:00
Bill Nottingham
d012362ade Update templates for installer changes 2021-04-09 17:42:42 -04:00
softwarefactory-project-zuul[bot]
ce2e41a6fa Merge pull request #9858 from marshmalien/7662-expanded-template-list-item
Add missing template list expanded section details

SUMMARY
Issue: #7662

Add the following detail items:

Description
Organization and link to organization details
Credentials


Move Credential and Label details to the bottom of the expanded section and make them stretch the entire width of the row.


COMPONENT NAME


UI

Reviewed-by: Kersom <None>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-09 21:10:12 +00:00
Marliana Lara
62c91aea4a Fix bug where falsy details return 0 2021-04-09 15:54:38 -04:00
softwarefactory-project-zuul[bot]
a0780aa287 Merge pull request #9586 from keithjgrant/8906-code-editor-validation-2
Add VariablesField YAML/JSON validation

SUMMARY
Validates YAML or JSON syntax in the variables field on blur. Prevents formik from submitting the form while this error is present.
addresses #8906, #8907
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

ADDITIONAL INFORMATION

Reviewed-by: Kersom <None>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-09 19:07:50 +00:00
Marliana Lara
0bc4702a26 Add execution environment detail to template expanded row 2021-04-09 14:40:59 -04:00
softwarefactory-project-zuul[bot]
6e46183ba6 Merge pull request #9814 from nixocio/ui_issue_9176
Do not validate optional survey

Do not validate optional survey.
See: #9176

Reviewed-by: Marliana Lara <marliana.lara@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
2021-04-09 17:35:22 +00:00
softwarefactory-project-zuul[bot]
8a86867f69 Merge pull request #9861 from jakemcdermott/fix-9296
Fix non-translatable template string

SUMMARY
The template string for the trademark doesn't seem like it can be used for a valid translation key. This caused the raw variable to be displayed for production builds instead of a readable string.  see: #9296 (comment)
ADDITIONAL INFORMATION
Screenshots, after applying this patch:
development environment


production build

Reviewed-by: Kersom <None>
2021-04-09 16:53:36 +00:00
softwarefactory-project-zuul[bot]
c7a2a1b9f6 Merge pull request #9869 from jakemcdermott/fix-cred-validation-prop
Use validated prop in cred plugin field

SUMMARY
Fxes an initialization bug for cred plugin fields, introduced by this commit
This pr applies the patch described below:
cc @marshmalien @unlikelyzero

before


after

Reviewed-by: John Hill <johill@redhat.com>
2021-04-09 16:20:20 +00:00
Jake McDermott
4e75e9438e Use validated prop in cred plugin field 2021-04-09 10:50:58 -04:00
Jake McDermott
b75d0c1dad Fix non-translatable template string 2021-04-08 19:09:19 -04:00
Marliana Lara
aa69a493b6 Add remaining expanded template list item details 2021-04-08 16:03:46 -04:00
softwarefactory-project-zuul[bot]
cb32f5b096 Merge pull request #9755 from nixocio/ui_issue_9752
Remove isolated and controller from the UI

Remove isolated and controller from the UI.
See: #9752

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
2021-04-08 18:48:17 +00:00
Seth Foster
89e28d6d4a fix awx_collections tests by comparing Decimal to float, instead of comparing strings 2021-04-08 13:38:35 -04:00
Seth Foster
f05ffa521a the returned self.elapsed should be decimal, instead of float, to match django model field type 2021-04-08 11:36:40 -04:00
Alex Corey
a3aab7228d updates importing messages properly 2021-04-08 09:58:53 -04:00
Alex Corey
385c4a16db updates the method of loading locales 2021-04-08 09:14:41 -04:00
Alex Corey
43c8cabaa6 Updates Lingui 2021-04-08 09:14:40 -04:00
softwarefactory-project-zuul[bot]
b85559fe13 Merge pull request #9848 from marshmalien/subscription-docs-link
Update subscription docs link to use single source of truth

SUMMARY
Related: #8428

Update subscription edit form documentation links to use the docs link utility.
Fix broken unit tests

COMPONENT NAME


UI

Reviewed-by: Keith Grant <None>
2021-04-07 21:54:27 +00:00
Seth Foster
09c176847d string 2021-04-07 17:30:46 -04:00
Marliana Lara
5ff2e7442c Update subscription docs link to use single source of truth 2021-04-07 16:21:52 -04:00
Seth Foster
8c73a51730 Fix elapsed time on job showing incorrect value
- job elapsed time showed 0.0, during and after the job run
2021-04-07 15:54:43 -04:00
Keith J. Grant
812a4e53df add VariablesField YAML/JSON validation 2021-04-07 11:16:44 -07:00
Ryan Petrello
8ea247123a automatically setup default Galaxy credentials on SAML login 2021-04-07 10:19:19 -04:00
nixocio
eda9bcbf62 Do not validate optional survey
Do not validate optional survey.

See: https://github.com/ansible/awx/issues/9176
2021-04-05 13:30:24 -04:00
Alessandro Grassi
664d19510f Add tower group for collection modules 2021-04-02 08:51:02 +02:00
Graham Mainwaring
b3d1c7ff9f Add force parameter to argument_spec 2021-04-01 20:47:30 -04:00
Graham Mainwaring
caec347371 Make sure changed is always set 2021-04-01 20:45:11 -04:00
Graham Mainwaring
26154d22d3 Make tower_license module idempotent
Signed-off-by: Graham Mainwaring <graham@mhn.org>
2021-04-01 20:45:11 -04:00
nixocio
e56c5dbfe3 Remove isolated and controller from the UI
Remove isolated and controller from the UI.

See: https://github.com/ansible/awx/issues/9752
2021-03-30 14:19:13 -04:00
1581 changed files with 114804 additions and 79918 deletions

View File

@@ -23,8 +23,8 @@ https://www.ansible.com/security
##### ENVIRONMENT
* AWX version: X.Y.Z
* AWX install method: openshift, minishift, docker on linux, docker for mac, boot2docker
* Ansible version: X.Y.Z
* AWX install method: operator, developer environment
* AWX deployment target: openshift, kubernetes, minikube
* Operating System:
* Web Browser:

View File

@@ -5,7 +5,7 @@ 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
- http://web.libera.chat/?channels=#ansible-awx
- https://groups.google.com/forum/#!forum/awx-project
We have to limit this because of limited volunteer time to respond to issues! -->

View File

@@ -5,7 +5,7 @@ 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
- http://web.libera.chat/?channels=#ansible-awx
- https://groups.google.com/forum/#!forum/awx-project
We have to limit this because of limited volunteer time to respond to issues! -->

View File

@@ -17,7 +17,6 @@ the change does.
<!--- Name of the module/plugin/module/task -->
- API
- UI
- Installer
##### AWX VERSION
<!--- Paste verbatim output from `make VERSION` between quotes below -->

View File

@@ -1,7 +0,0 @@
---
version: 2
updates:
- package-ecosystem: "pip"
directory: "/requirements"
schedule:
interval: "monthly"

View File

@@ -1,7 +1,7 @@
Coding Standards and Practices
==============================
This is not meant to be a style document so much as a practices document for ensuring performance and convention in the Ansible Tower API.
This is not meant to be a style document so much as a practices document for ensuring performance and convention in the AWX API.
Paginate Everything
===================

View File

@@ -1,6 +1,54 @@
# Changelog
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>`.
# 19.2.2 (June 28, 2021)
- Fixed bug where symlinks pointing to directories were not preserved (https://github.com/ansible/ansible-runner/pull/736)
- Various bugfixes found during testing (https://github.com/ansible/awx/pull/10532)
# 19.2.1 (June 17, 2021)
- There are now 2 default Instance Groups: 'controlplane' and 'default' (https://github.com/ansible/awx/pull/10324)
- Removed deprecated modules: `tower_send`, `tower_receive`, `tower_workflow_template` (https://github.com/ansible/awx/pull/9980)
- Improved UI performance when a large amount of events are being emitted by jobs (https://github.com/ansible/awx/pull/10053)
- Settings UI Revert All button now issues a DELETE instead of PATCHing all fields (https://github.com/ansible/awx/pull/10376)
- Fixed a bug with the schedule date/time picker in Firefox (https://github.com/ansible/awx/pull/10291)
- UI now preselects the system default Galaxy credential when creating a new organization (https://github.com/ansible/awx/pull/10395)
- Added favicon (https://github.com/ansible/awx/pull/10388)
- Removed `not` option from smart inventory host filter search as it's not supported by the API (https://github.com/ansible/awx/pull/10380)
- Added button to allow user to refetch project revision after project sync has finished (https://github.com/ansible/awx/pull/10334)
- Fixed bug where extraneous CONFIG requests were made on logout (https://github.com/ansible/awx/pull/10379)
- Fixed bug where users were unable to cancel inventory syncs (https://github.com/ansible/awx/pull/10346)
- Added missing dashboard graph filters (https://github.com/ansible/awx/pull/10349)
- Added support for typing in to single select lookup form fields (https://github.com/ansible/awx/pull/10257)
- Fixed various bugs related to user sessions (https://github.com/ansible/awx/pull/9908)
- Fixed bug where sorting in modals would close the modal (https://github.com/ansible/awx/pull/10215)
- Added support for Red Hat Insights as an inventory source (https://github.com/ansible/awx/pull/8650)
- Fixed bugs when selecting items in a list then sorting/paginating (https://github.com/ansible/awx/pull/10329)
# 19.2.0 (June 1, 2021)
- Fixed race condition that would sometimes cause jobs to error out at the very end of an otherwise successful run (https://github.com/ansible/receptor/pull/328)
- Fixes bug where users were unable to click on text next to checkboxes in modals (https://github.com/ansible/awx/pull/10279)
- Have the project update playbook warn if role/collection syncing is disabled. (https://github.com/ansible/awx/pull/10068)
- Move irc references to point to irc.libera.chat (https://github.com/ansible/awx/pull/10295)
- Fixes bug where activity stream changes were displaying as [object object] (https://github.com/ansible/awx/pull/10267)
- Update awxkit to enable export of Galaxy credentials associated to organizations (https://github.com/ansible/awx/pull/10271)
- Bump receptor and receptorctl versions to 1.0.0a2 (https://github.com/ansible/awx/pull/10261)
- Add the ability to disable local authentication (https://github.com/ansible/awx/pull/10102)
- Show error if no Execution Environment is found on project sync/job run (https://github.com/ansible/awx/pull/10183)
- Allow for editing and deleting managed_by_tower EEs from API/UI (https://github.com/ansible/awx/pull/10173)
# 19.1.0 (May 1, 2021)
- Custom inventory scripts have been removed from the API https://github.com/ansible/awx/pull/9822
- Old scripts can be exported via `awx-manage export_custom_scripts`
- Fixed a bug where ad-hoc commands targeted against multiple hosts would run against only 1 host https://github.com/ansible/awx/pull/9973
- AWX will now look for a top-level requirements.yml when installing collections / roles in project updates https://github.com/ansible/awx/pull/9945
- Improved error handling when Container Group pods fail to launch https://github.com/ansible/awx/pull/10025
- Added ability to set server-side password policies using Django's AUTH_PASSWORD_VALIDATORS setting https://github.com/ansible/awx/pull/9999
- Bumped versions of Ansible Runner & AWX EE https://github.com/ansible/awx/pull/10013
- If you have built any custom EEs on top of awx-ee 0.1.0, you will need to rebuild on top of 0.2.0.
- Remove legacy resource profiling code https://github.com/ansible/awx/pull/9883
# 19.0.0 (April 7, 2021)

View File

@@ -2,7 +2,7 @@
Hi there! We're excited to have you as a contributor.
Have questions about this document or anything not covered here? Come chat with us at `#ansible-awx` on webchat.freenode.net, or submit your question to the [mailing list](https://groups.google.com/forum/#!forum/awx-project).
Have questions about this document or anything not covered here? Come chat with us at `#ansible-awx` on irc.libera.chat, or submit your question to the [mailing list](https://groups.google.com/forum/#!forum/awx-project).
## Table of contents
@@ -28,7 +28,7 @@ Have questions about this document or anything not covered here? Come chat with
- You must use `git commit --signoff` for any commit to be merged, and agree that usage of --signoff constitutes agreement with the terms of [DCO 1.1](./DCO_1_1.md).
- Take care to make sure no merge commits are in the submission, and use `git rebase` vs `git merge` for this reason.
- If collaborating with someone else on the same branch, consider using `--force-with-lease` instead of `--force`. This will prevent you from accidentally overwriting commits pushed by someone else. For more information, see https://git-scm.com/docs/git-push#git-push---force-with-leaseltrefnamegt
- If submitting a large code change, it's a good idea to join the `#ansible-awx` channel on webchat.freenode.net, and talk about what you would like to do or add first. This not only helps everyone know what's going on, it also helps save time and effort, if the community decides some changes are needed.
- If submitting a large code change, it's a good idea to join the `#ansible-awx` channel on irc.libera.chat, and talk about what you would like to do or add first. This not only helps everyone know what's going on, it also helps save time and effort, if the community decides some changes are needed.
- We ask all of our community members and contributors to adhere to the [Ansible code of conduct](http://docs.ansible.com/ansible/latest/community/code_of_conduct.html). If you have questions, or need assistance, please reach out to our community team at [codeofconduct@ansible.com](mailto:codeofconduct@ansible.com)
## Setting up your development environment
@@ -114,7 +114,7 @@ Fixing bugs, adding translations, and updating the documentation are always appr
**NOTE**
> If you work in a part of the codebase that is going through active development, your changes may be rejected, or you may be asked to `rebase`. A good idea before starting work is to have a discussion with us in the `#ansible-awx` channel on webchat.freenode.net, or on the [mailing list](https://groups.google.com/forum/#!forum/awx-project).
> If you work in a part of the codebase that is going through active development, your changes may be rejected, or you may be asked to `rebase`. A good idea before starting work is to have a discussion with us in the `#ansible-awx` channel on irc.libera.chat, or on the [mailing list](https://groups.google.com/forum/#!forum/awx-project).
**NOTE**
@@ -136,7 +136,7 @@ Here are a few things you can do to help the visibility of your change, and incr
* Make the smallest change possible
* Write good commit messages. See [How to write a Git commit message](https://chris.beams.io/posts/git-commit/).
It's generally a good idea to discuss features with us first by engaging us in the `#ansible-awx` channel on webchat.freenode.net, or on the [mailing list](https://groups.google.com/forum/#!forum/awx-project).
It's generally a good idea to discuss features with us first by engaging us in the `#ansible-awx` channel on irc.libera.chat, or on the [mailing list](https://groups.google.com/forum/#!forum/awx-project).
We like to keep our commit history clean, and will require resubmission of pull requests that contain merge commits. Use `git pull --rebase`, rather than
`git pull`, and `git rebase`, rather than `git merge`.

View File

@@ -3,12 +3,6 @@ Table of Contents
* [Installing AWX](#installing-awx)
* [The AWX Operator](#the-awx-operator)
* [Quickstart with minikube](#quickstart-with-minikube)
* [Starting minikube](#starting-minikube)
* [Deploying the AWX Operator](#deploying-the-awx-operator)
* [Verifying the Operator Deployment](#verifying-the-operator-deployment)
* [Deploy AWX](#deploy-awx)
* [Accessing AWX](#accessing-awx)
* [Installing the AWX CLI](#installing-the-awx-cli)
* [Building the CLI Documentation](#building-the-cli-documentation)
@@ -22,103 +16,10 @@ If you're attempting to migrate an older Docker-based AWX installation, see: [Mi
## The AWX Operator
Starting in version 18.0, the [AWX Operator](https://github.com/ansible/awx-operator) is the preferred way to install AWX.
Starting in version 18.0, the [AWX Operator](https://github.com/ansible/awx-operator) is the preferred way to install AWX. Please refer to the [AWX Operator](https://github.com/ansible/awx-operator) documentation.
AWX can also alternatively be installed and [run in Docker](./tools/docker-compose/README.md), but this install path is only recommended for development/test-oriented deployments, and has no official published release.
### Quickstart with minikube
If you don't have an existing OpenShift or Kubernetes cluster, minikube is a fast and easy way to get up and running.
To install minikube, follow the steps in their [documentation](https://minikube.sigs.k8s.io/docs/start/).
#### Starting minikube
Once you have installed minikube, run the following command to start it. You may wish to customize these options.
```
$ minikube start --cpus=4 --memory=8g --addons=ingress
```
#### Deploying the AWX Operator
For a comprehensive overview of features, see [README.md](https://github.com/ansible/awx-operator/blob/devel/README.md) in the awx-operator repo. The following steps are the bare minimum to get AWX up and running.
```
$ minikube kubectl -- apply -f https://raw.githubusercontent.com/ansible/awx-operator/devel/deploy/awx-operator.yaml
```
##### Verifying the Operator Deployment
After a few seconds, the operator should be up and running. Verify it by running the following command:
```
$ minikube kubectl get pods
NAME READY STATUS RESTARTS AGE
awx-operator-7c78bfbfd-xb6th 1/1 Running 0 11s
```
#### Deploy AWX
Once the Operator is running, you can now deploy AWX by creating a simple YAML file:
```
$ cat myawx.yml
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
tower_ingress_type: Ingress
```
And then creating the AWX object in the Kubernetes API:
```
$ minikube kubectl apply -- -f myawx.yml
awx.awx.ansible.com/awx created
```
After creating the AWX object in the Kubernetes API, the operator will begin running its reconciliation loop.
To see what's going on, you can tail the logs of the operator pod (note that your pod name will be different):
```
$ minikube kubectl logs -- -f awx-operator-7c78bfbfd-xb6th
```
After a few seconds, you will see the database and application pods show up. On a fresh system, it may take a few minutes for the container images to download.
```
$ minikube kubectl get pods
NAME READY STATUS RESTARTS AGE
awx-5ffbfd489c-bvtvf 3/3 Running 0 2m54s
awx-operator-7c78bfbfd-xb6th 1/1 Running 0 6m42s
awx-postgres-0 1/1 Running 0 2m58s
```
##### Accessing AWX
To access the AWX UI, you'll need to grab the service url from minikube:
```
$ minikube service awx-service --url
http://192.168.59.2:31868
```
On fresh installs, you will see the "AWX is currently upgrading." page until database migrations finish.
Once you are redirected to the login screen, you can now log in by obtaining the generated admin password (note: do not copy the trailing `%`):
```
$ minikube kubectl -- get secret awx-admin-password -o jsonpath='{.data.password}' | base64 --decode
b6ChwVmqEiAsil2KSpH4xGaZPeZvWnWj%
```
Now you can log in at the URL above with the username "admin" and the password above. Happy Automating!
# Installing the AWX CLI
`awx` is the official command-line client for AWX. It:

View File

@@ -5,7 +5,7 @@
Use the GitHub [issue tracker](https://github.com/ansible/awx/issues) for filing bugs. In order to save time, and help us respond to issues quickly, make sure to fill out as much of the issue template
as possible. Version information, and an accurate reproducing scenario are critical to helping us identify the problem.
Please don't use the issue tracker as a way to ask how to do something. Instead, use the [mailing list](https://groups.google.com/forum/#!forum/awx-project) , and the `#ansible-awx` channel on irc.freenode.net to get help.
Please don't use the issue tracker as a way to ask how to do something. Instead, use the [mailing list](https://groups.google.com/forum/#!forum/awx-project) , and the `#ansible-awx` channel on irc.libera.chat to get help.
Before opening a new issue, please use the issue search feature to see if what you're experiencing has already been reported. If you have any extra detail to provide, please comment. Otherwise, rather than posting a "me too" comment, please consider giving it a ["thumbs up"](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comment) to give us an indication of the severity of the problem.

View File

@@ -13,7 +13,6 @@ MANAGEMENT_COMMAND ?= awx-manage
IMAGE_REPOSITORY_AUTH ?=
IMAGE_REPOSITORY_BASE ?= https://gcr.io
VERSION := $(shell cat VERSION)
PYCURL_SSL_LIBRARY ?= openssl
# NOTE: This defaults the container image version to the branch that's active
COMPOSE_TAG ?= $(GIT_BRANCH)
@@ -28,7 +27,7 @@ DEVEL_IMAGE_NAME ?= $(DEV_DOCKER_TAG_BASE)/awx_devel:$(COMPOSE_TAG)
# Python packages to install only from source (not from binary wheels)
# Comma separated list
SRC_ONLY_PKGS ?= cffi,pycparser,psycopg2,twilio,pycurl
SRC_ONLY_PKGS ?= cffi,pycparser,psycopg2,twilio
# These should be upgraded in the AWX and Ansible venv before attempting
# to install the actual requirements
VENV_BOOTSTRAP ?= pip==19.3.1 setuptools==41.6.0 wheel==0.36.2
@@ -65,7 +64,8 @@ I18N_FLAG_FILE = .i18n_built
receiver test test_unit test_coverage coverage_html \
dev_build release_build sdist \
ui-release ui-devel \
VERSION docker-compose-sources
VERSION docker-compose-sources \
.git/hooks/pre-commit
clean-tmp:
rm -rf tmp/
@@ -173,12 +173,7 @@ init:
. $(VENV_BASE)/awx/bin/activate; \
fi; \
$(MANAGEMENT_COMMAND) provision_instance --hostname=$(COMPOSE_HOST); \
$(MANAGEMENT_COMMAND) register_queue --queuename=tower --instance_percent=100;\
if [ "$(AWX_GROUP_QUEUES)" == "tower,thepentagon" ]; then \
$(MANAGEMENT_COMMAND) provision_instance --hostname=isolated; \
$(MANAGEMENT_COMMAND) register_queue --queuename='thepentagon' --hostnames=isolated --controller=tower; \
$(MANAGEMENT_COMMAND) generate_isolated_key > /awx_devel/awx/main/isolated/authorized_keys; \
fi;
$(MANAGEMENT_COMMAND) register_queue --queuename=controlplane --instance_percent=100;
# Refresh development environment after pulling new code.
refresh: clean requirements_dev version_file develop migrate
@@ -276,7 +271,9 @@ black: reports
@(set -o pipefail && $@ $(BLACK_ARGS) awx awxkit awx_collection | tee reports/$@.report)
.git/hooks/pre-commit:
@echo "[ -z \$$AWX_IGNORE_BLACK ] && (black --check \`git diff --cached --name-only --diff-filter=AM | grep -E '\.py$\'\` || (echo 'To fix this, run \`make black\` to auto-format your code prior to commit, or set AWX_IGNORE_BLACK=1' && exit 1))" > .git/hooks/pre-commit
@echo "if [ -x pre-commit.sh ]; then" > .git/hooks/pre-commit
@echo " ./pre-commit.sh;" >> .git/hooks/pre-commit
@echo "fi" >> .git/hooks/pre-commit
@chmod +x .git/hooks/pre-commit
genschema: reports
@@ -291,6 +288,11 @@ swagger: reports
check: black
api-lint:
BLACK_ARGS="--check" make black
flake8 awx
yamllint -s .
awx-link:
[ -d "/awx_devel/awx.egg-info" ] || $(PYTHON) /awx_devel/setup.py egg_info_dev
cp -f /tmp/awx.egg-link /var/lib/awx/venv/awx/lib/python$(PYTHON_VERSION)/site-packages/awx.egg-link
@@ -318,7 +320,7 @@ test_collection:
if [ "$(VENV_BASE)" ]; then \
. $(VENV_BASE)/awx/bin/activate; \
fi && \
pip install ansible && \
pip install ansible-core && \
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
@@ -391,7 +393,7 @@ clean-ui:
rm -rf $(UI_BUILD_FLAG_FILE)
awx/ui_next/node_modules:
$(NPM_BIN) --prefix awx/ui_next --loglevel warn --ignore-scripts install
NODE_OPTIONS=--max-old-space-size=4096 $(NPM_BIN) --prefix awx/ui_next --loglevel warn ci
$(UI_BUILD_FLAG_FILE):
$(NPM_BIN) --prefix awx/ui_next --loglevel warn run compile-strings
@@ -473,7 +475,7 @@ docker-compose-sources: .git/hooks/pre-commit
-e cluster_node_count=$(CLUSTER_NODE_COUNT)
docker-compose: docker-auth awx/projects docker-compose-sources
docker-compose -f tools/docker-compose/_sources/docker-compose.yml up $(COMPOSE_UP_OPTS)
docker-compose -f tools/docker-compose/_sources/docker-compose.yml $(COMPOSE_UP_OPTS) up
docker-compose-credential-plugins: docker-auth awx/projects docker-compose-sources
echo -e "\033[0;31mTo generate a CyberArk Conjur API key: docker exec -it tools_conjur_1 conjurctl account create quick-start\033[0m"
@@ -554,10 +556,13 @@ awx-kube-dev-build: Dockerfile.kube-dev
# Translation TASKS
# --------------------------------------
# generate UI .pot
# generate UI .pot file, an empty template of strings yet to be translated
pot: $(UI_BUILD_FLAG_FILE)
$(NPM_BIN) --prefix awx/ui_next --loglevel warn run extract-strings
$(NPM_BIN) --prefix awx/ui_next --loglevel warn run extract-template
$(NPM_BIN) --prefix awx/ui_next --loglevel warn run extract-template --clean
# generate UI .po files for each locale (will update translated strings for `en`)
po: $(UI_BUILD_FLAG_FILE)
$(NPM_BIN) --prefix awx/ui_next --loglevel warn run extract-strings -- --clean
# generate API django .pot .po
LANG = "en-us"

View File

@@ -1,9 +1,9 @@
[![Gated by Zuul](https://zuul-ci.org/gated.svg)](https://ansible.softwarefactory-project.io/zuul/status) [![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-Ansible-yellow.svg)](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) [![Apache v2 License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](https://github.com/ansible/awx/blob/devel/LICENSE.md) [![AWX Mailing List](https://img.shields.io/badge/mailing%20list-AWX-orange.svg)](https://groups.google.com/g/awx-project)
[![IRC Chat](https://img.shields.io/badge/IRC-%23ansible--awx-blueviolet.svg)](https://webchat.freenode.net/#ansible-awx)
[![IRC Chat - #ansible-awx](https://img.shields.io/badge/IRC-%23ansible--awx-blueviolet.svg)](https://libera.chat)
<img src="https://raw.githubusercontent.com/ansible/awx-logos/master/awx/ui/client/assets/logo-login.svg?sanitize=true" width=200 alt="AWX" />
AWX provides a web-based user interface, REST API, and task engine built on top of [Ansible](https://github.com/ansible/ansible). It is the upstream project for [Tower](https://www.ansible.com/tower), a commercial derivative of AWX.
AWX provides a web-based user interface, REST API, and task engine built on top of [Ansible](https://github.com/ansible/ansible). It is one of the upstream projects for [Red Hat Ansible Automation Platform](https://www.ansible.com/products/automation-platform).
To install AWX, please view the [Install guide](./INSTALL.md).
@@ -20,7 +20,7 @@ Contributing
- All code submissions are made through pull requests against the `devel` branch.
- All contributors must use git commit --signoff for any commit to be merged and agree that usage of --signoff constitutes agreement with the terms of [DCO 1.1](./DCO_1_1.md)
- Take care to make sure no merge commits are in the submission, and use `git rebase` vs. `git merge` for this reason.
- If submitting a large code change, it's a good idea to join the `#ansible-awx` channel on webchat.freenode.net and talk about what you would like to do or add first. This not only helps everyone know what's going on, but it also helps save time and effort if the community decides some changes are needed.
- If submitting a large code change, it's a good idea to join the `#ansible-awx` channel on web.libera.chat and talk about what you would like to do or add first. This not only helps everyone know what's going on, but it also helps save time and effort if the community decides some changes are needed.
Reporting Issues
----------------
@@ -37,5 +37,5 @@ Get Involved
We welcome your feedback and ideas. Here's how to reach us with feedback and questions:
- Join the `#ansible-awx` channel on webchat.freenode.net
- Join the `#ansible-awx` channel on irc.libera.chat
- Join the [mailing list](https://groups.google.com/forum/#!forum/awx-project)

View File

@@ -1 +1 @@
19.0.0
19.2.2

View File

@@ -34,6 +34,7 @@ else:
from django.db.backends.base import schema
from django.db.models import indexes
from django.db.backends.utils import names_digest
from django.db import connection
if HAS_DJANGO is True:
@@ -85,7 +86,7 @@ def oauth2_getattribute(self, attr):
# setting lookups for references to model classes (e.g.,
# oauth2_settings.REFRESH_TOKEN_MODEL)
# If we're doing an OAuth2 setting lookup *while running* a migration,
# don't do our usual "Configure Tower in Tower" database setting lookup
# don't do our usual database settings lookup
val = settings.OAUTH2_PROVIDER.get(attr)
if val is None:
val = object.__getattribute__(self, attr)
@@ -149,6 +150,12 @@ def manage():
from django.conf import settings
from django.core.management import execute_from_command_line
# enforce the postgres version is equal to 12. if not, then terminate program with exit code of 1
if not MODE == 'development':
if (connection.pg_version // 10000) < 12:
sys.stderr.write("Postgres version 12 is required\n")
sys.exit(1)
if len(sys.argv) >= 2 and sys.argv[1] in ('version', '--version'): # pragma: no cover
sys.stdout.write('%s\n' % __version__)
# If running as a user without permission to read settings, display an

View File

@@ -1,8 +1,12 @@
# Django
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
# Django REST Framework
from rest_framework import serializers
# AWX
from awx.conf import fields, register
from awx.conf import fields, register, register_validate
from awx.api.fields import OAuth2ProviderField
from oauth2_provider.settings import oauth2_settings
@@ -27,6 +31,17 @@ register(
category=_('Authentication'),
category_slug='authentication',
)
register(
'DISABLE_LOCAL_AUTH',
field_class=fields.BooleanField,
label=_('Disable the built-in authentication system'),
help_text=_(
"Controls whether users are prevented from using the built-in authentication system. "
"You probably want to do this if you are using an LDAP or SAML integration."
),
category=_('Authentication'),
category_slug='authentication',
)
register(
'AUTH_BASIC_ENABLED',
field_class=fields.BooleanField,
@@ -77,7 +92,27 @@ register(
required=False,
default='',
label=_('Login redirect override URL'),
help_text=_('URL to which unauthorized users will be redirected to log in. If blank, users will be sent to the Tower login page.'),
help_text=_('URL to which unauthorized users will be redirected to log in. If blank, users will be sent to the login page.'),
category=_('Authentication'),
category_slug='authentication',
)
def authentication_validate(serializer, attrs):
remote_auth_settings = [
'AUTH_LDAP_SERVER_URI',
'SOCIAL_AUTH_GOOGLE_OAUTH2_KEY',
'SOCIAL_AUTH_GITHUB_KEY',
'SOCIAL_AUTH_GITHUB_ORG_KEY',
'SOCIAL_AUTH_GITHUB_TEAM_KEY',
'SOCIAL_AUTH_SAML_ENABLED_IDPS',
'RADIUS_SERVER',
'TACACSPLUS_HOST',
]
if attrs.get('DISABLE_LOCAL_AUTH', False):
if not any(getattr(settings, s, None) for s in remote_auth_settings):
raise serializers.ValidationError(_("There are no remote authentication systems configured."))
return attrs
register_validate('authentication', authentication_validate)

View File

@@ -133,7 +133,7 @@ class FieldLookupBackend(BaseFilterBackend):
Filter using field lookups provided via query string parameters.
"""
RESERVED_NAMES = ('page', 'page_size', 'format', 'order', 'order_by', 'search', 'type', 'host_filter', 'count_disabled', 'no_truncate')
RESERVED_NAMES = ('page', 'page_size', 'format', 'order', 'order_by', 'search', 'type', 'host_filter', 'count_disabled', 'no_truncate', 'limit')
SUPPORTED_LOOKUPS = (
'exact',

View File

@@ -39,6 +39,7 @@ from awx.main.models import UnifiedJob, UnifiedJobTemplate, User, Role, Credenti
from awx.main.access import access_registry
from awx.main.utils import camelcase_to_underscore, get_search_fields, getattrd, get_object_or_400, decrypt_field, get_awx_version
from awx.main.utils.db import get_all_field_names
from awx.main.utils.licensing import server_product_name
from awx.main.views import ApiErrorView
from awx.api.serializers import ResourceAccessListElementSerializer, CopySerializer, UserSerializer
from awx.api.versioning import URLPathVersioning
@@ -184,9 +185,6 @@ class APIView(views.APIView):
"""
Log warning for 400 requests. Add header with elapsed time.
"""
from awx.main.utils import get_licenser
from awx.main.utils.licensing import OpenLicense
#
# If the URL was rewritten, and we get a 404, we should entirely
# replace the view in the request context with an ApiErrorView()
@@ -226,7 +224,7 @@ class APIView(views.APIView):
response = super(APIView, self).finalize_response(request, response, *args, **kwargs)
time_started = getattr(self, 'time_started', None)
response['X-API-Product-Version'] = get_awx_version()
response['X-API-Product-Name'] = 'AWX' if isinstance(get_licenser(), OpenLicense) else 'Red Hat Ansible Tower'
response['X-API-Product-Name'] = server_product_name()
response['X-API-Node'] = settings.CLUSTER_HOST_ID
if time_started:
@@ -789,7 +787,7 @@ class RetrieveUpdateAPIView(RetrieveAPIView, generics.RetrieveUpdateAPIView):
return super(RetrieveUpdateAPIView, self).partial_update(request, *args, **kwargs)
def update_filter(self, request, *args, **kwargs):
''' scrub any fields the user cannot/should not put/patch, based on user context. This runs after read-only serialization filtering '''
'''scrub any fields the user cannot/should not put/patch, based on user context. This runs after read-only serialization filtering'''
pass

View File

@@ -24,7 +24,10 @@ from rest_framework.request import clone_request
from awx.api.fields import ChoiceNullField
from awx.main.fields import JSONField, ImplicitRoleField
from awx.main.models import NotificationTemplate
from awx.main.tasks import AWXReceptorJob
from awx.main.utils.execution_environments import get_default_pod_spec
# Polymorphic
from polymorphic.models import PolymorphicModel
class Metadata(metadata.SimpleMetadata):
@@ -78,7 +81,9 @@ class Metadata(metadata.SimpleMetadata):
field_info['help_text'] = field_help_text[field.field_name].format(verbose_name)
if field.field_name == 'type':
field_info['filterable'] = True
# Only include model classes with `type` field.
if issubclass(serializer.Meta.model, PolymorphicModel):
field_info['filterable'] = True
else:
for model_field in serializer.Meta.model._meta.fields:
if field.field_name == model_field.name:
@@ -206,7 +211,7 @@ class Metadata(metadata.SimpleMetadata):
continue
if field == "pod_spec_override":
meta['default'] = AWXReceptorJob().pod_definition
meta['default'] = get_default_pod_spec()
# Add type choices if available from the serializer.
if field == 'type' and hasattr(serializer, 'get_type_choices'):

View File

@@ -1,12 +1,16 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.
from collections import OrderedDict
# Django REST Framework
from django.conf import settings
from django.core.paginator import Paginator as DjangoPaginator
from rest_framework import pagination
from rest_framework.response import Response
from rest_framework.utils.urls import replace_query_param
from rest_framework.settings import api_settings
from django.utils.translation import gettext_lazy as _
class DisabledPaginator(DjangoPaginator):
@@ -65,3 +69,65 @@ class Pagination(pagination.PageNumberPagination):
if self.count_disabled:
return Response({'results': data})
return super(Pagination, self).get_paginated_response(data)
class LimitPagination(pagination.BasePagination):
default_limit = api_settings.PAGE_SIZE
limit_query_param = 'limit'
limit_query_description = _('Number of results to return per page.')
max_page_size = settings.MAX_PAGE_SIZE
def paginate_queryset(self, queryset, request, view=None):
self.limit = self.get_limit(request)
self.request = request
return list(queryset[0 : self.limit])
def get_paginated_response(self, data):
return Response(OrderedDict([('results', data)]))
def get_paginated_response_schema(self, schema):
return {
'type': 'object',
'properties': {
'results': schema,
},
}
def get_limit(self, request):
try:
return pagination._positive_int(request.query_params[self.limit_query_param], strict=True)
except (KeyError, ValueError):
pass
return self.default_limit
class UnifiedJobEventPagination(Pagination):
"""
By default, use Pagination for all operations.
If `limit` query parameter specified use LimitPagination
"""
def __init__(self, *args, **kwargs):
self.use_limit_paginator = False
self.limit_pagination = LimitPagination()
return super().__init__(*args, **kwargs)
def paginate_queryset(self, queryset, request, view=None):
if 'limit' in request.query_params:
self.use_limit_paginator = True
if self.use_limit_paginator:
return self.limit_pagination.paginate_queryset(queryset, request, view=view)
return super().paginate_queryset(queryset, request, view=view)
def get_paginated_response(self, data):
if self.use_limit_paginator:
return self.limit_pagination.get_paginated_response(data)
return super().get_paginated_response(data)
def get_paginated_response_schema(self, schema):
if self.use_limit_paginator:
return self.limit_pagination.get_paginated_response_schema(schema)
return super().get_paginated_response_schema(schema)

View File

@@ -4,6 +4,8 @@
# Python
import logging
from django.conf import settings
# Django REST Framework
from rest_framework.exceptions import MethodNotAllowed, PermissionDenied
from rest_framework import permissions
@@ -245,7 +247,7 @@ class IsSuperUser(permissions.BasePermission):
class InstanceGroupTowerPermission(ModelAccessPermission):
def has_object_permission(self, request, view, obj):
if request.method == 'DELETE' and obj.name == "tower":
if request.method == 'DELETE' and obj.name in [settings.DEFAULT_EXECUTION_QUEUE_NAME, settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME]:
return False
return super(InstanceGroupTowerPermission, self).has_object_permission(request, view, obj)

View File

@@ -21,6 +21,7 @@ from jinja2.exceptions import TemplateSyntaxError, UndefinedError, SecurityError
from django.conf import settings
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.models import User
from django.contrib.auth.password_validation import validate_password as django_validate_password
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, ValidationError as DjangoValidationError
from django.db import models
@@ -43,7 +44,7 @@ from polymorphic.models import PolymorphicModel
# AWX
from awx.main.access import get_user_capabilities
from awx.main.constants import SCHEDULEABLE_PROVIDERS, ACTIVE_STATES, CENSOR_VALUE
from awx.main.constants import ACTIVE_STATES, CENSOR_VALUE
from awx.main.models import (
ActivityStream,
AdHocCommand,
@@ -51,7 +52,6 @@ from awx.main.models import (
Credential,
CredentialInputSource,
CredentialType,
CustomInventoryScript,
ExecutionEnvironment,
Group,
Host,
@@ -92,6 +92,7 @@ from awx.main.models import (
WorkflowJobTemplate,
WorkflowJobTemplateNode,
StdoutMaxBytesExceeded,
CLOUD_INVENTORY_SOURCES,
)
from awx.main.models.base import VERBOSITY_CHOICES, NEW_JOB_TYPE_CHOICES
from awx.main.models.rbac import get_roles_on_resource, role_summary_fields_generator
@@ -143,13 +144,12 @@ SUMMARIZABLE_FK_FIELDS = {
'inventory_sources_with_failures',
'organization_id',
'kind',
'insights_credential_id',
),
'host': DEFAULT_SUMMARY_FIELDS,
'group': DEFAULT_SUMMARY_FIELDS,
'default_environment': DEFAULT_SUMMARY_FIELDS + ('image',),
'execution_environment': DEFAULT_SUMMARY_FIELDS + ('image',),
'project': DEFAULT_SUMMARY_FIELDS + ('status', 'scm_type'),
'project': DEFAULT_SUMMARY_FIELDS + ('status', 'scm_type', 'allow_override'),
'source_project': DEFAULT_SUMMARY_FIELDS + ('status', 'scm_type'),
'project_update': DEFAULT_SUMMARY_FIELDS + ('status', 'failed'),
'credential': DEFAULT_SUMMARY_FIELDS + ('kind', 'cloud', 'kubernetes', 'credential_type_id'),
@@ -167,12 +167,9 @@ SUMMARIZABLE_FK_FIELDS = {
'current_update': DEFAULT_SUMMARY_FIELDS + ('status', 'failed', 'license_error'),
'current_job': DEFAULT_SUMMARY_FIELDS + ('status', 'failed', 'license_error'),
'inventory_source': ('id', 'name', 'source', 'last_updated', 'status'),
'custom_inventory_script': DEFAULT_SUMMARY_FIELDS,
'source_script': DEFAULT_SUMMARY_FIELDS,
'role': ('id', 'role_field'),
'notification_template': DEFAULT_SUMMARY_FIELDS,
'instance_group': ('id', 'name', 'controller_id', 'is_container_group'),
'insights_credential': DEFAULT_SUMMARY_FIELDS,
'instance_group': ('id', 'name', 'is_container_group'),
'source_credential': DEFAULT_SUMMARY_FIELDS + ('kind', 'cloud', 'credential_type_id'),
'target_credential': DEFAULT_SUMMARY_FIELDS + ('kind', 'cloud', 'credential_type_id'),
'webhook_credential': DEFAULT_SUMMARY_FIELDS + ('kind', 'cloud', 'credential_type_id'),
@@ -725,6 +722,20 @@ class UnifiedJobTemplateSerializer(BaseSerializer):
else:
return super(UnifiedJobTemplateSerializer, self).to_representation(obj)
def get_summary_fields(self, obj):
summary_fields = super().get_summary_fields(obj)
if self.is_detail_view:
resolved_ee = obj.resolve_execution_environment()
if resolved_ee is not None:
summary_fields['resolved_environment'] = {
field: getattr(resolved_ee, field, None)
for field in SUMMARIZABLE_FK_FIELDS['execution_environment']
if getattr(resolved_ee, field, None) is not None
}
return summary_fields
class UnifiedJobSerializer(BaseSerializer):
show_capabilities = ['start', 'delete']
@@ -755,6 +766,7 @@ class UnifiedJobSerializer(BaseSerializer):
'result_traceback',
'event_processing_finished',
'launched_by',
'work_unit_id',
)
extra_kwargs = {
@@ -963,6 +975,7 @@ class UserSerializer(BaseSerializer):
return ret
def validate_password(self, value):
django_validate_password(value)
if not self.instance and value in (None, ''):
raise serializers.ValidationError(_('Password required for new User.'))
return value
@@ -1350,6 +1363,7 @@ class ProjectOptionsSerializer(BaseSerializer):
'scm_branch',
'scm_refspec',
'scm_clean',
'scm_track_submodules',
'scm_delete_on_update',
'credential',
'timeout',
@@ -1384,6 +1398,8 @@ class ProjectOptionsSerializer(BaseSerializer):
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.')
if attrs.get('scm_track_submodules') and scm_type != 'git':
errors['scm_track_submodules'] = _('SCM track_submodules can only be used with git projects.')
if errors:
raise serializers.ValidationError(errors)
@@ -1393,11 +1409,11 @@ class ProjectOptionsSerializer(BaseSerializer):
class ExecutionEnvironmentSerializer(BaseSerializer):
show_capabilities = ['edit', 'delete', 'copy']
managed_by_tower = serializers.ReadOnlyField()
managed = serializers.ReadOnlyField()
class Meta:
model = ExecutionEnvironment
fields = ('*', 'organization', 'image', 'managed_by_tower', 'credential', 'pull')
fields = ('*', 'organization', 'image', 'managed', 'credential', 'pull')
def get_related(self, obj):
res = super(ExecutionEnvironmentSerializer, self).get_related(obj)
@@ -1412,6 +1428,19 @@ class ExecutionEnvironmentSerializer(BaseSerializer):
res['credential'] = self.reverse('api:credential_detail', kwargs={'pk': obj.credential.pk})
return res
def validate_credential(self, value):
if value and value.kind != 'registry':
raise serializers.ValidationError(_('Only Container Registry credentials can be associated with an Execution Environment'))
return value
def validate(self, attrs):
# prevent changing organization of ee. Unsetting (change to null) is allowed
if self.instance:
org = attrs.get('organization', None)
if org and org.pk != self.instance.organization_id:
raise serializers.ValidationError({"organization": _("Cannot change the organization of an execution environment")})
return super(ExecutionEnvironmentSerializer, self).validate(attrs)
class ProjectSerializer(UnifiedJobTemplateSerializer, ProjectOptionsSerializer):
@@ -1497,7 +1526,7 @@ class ProjectSerializer(UnifiedJobTemplateSerializer, ProjectOptionsSerializer):
)
if get_field_from_model_or_attrs('scm_type') == '':
for fd in ('scm_update_on_launch', 'scm_delete_on_update', 'scm_clean'):
for fd in ('scm_update_on_launch', 'scm_delete_on_update', 'scm_track_submodules', 'scm_clean'):
if get_field_from_model_or_attrs(fd):
raise serializers.ValidationError({fd: _('Update options must be set to false for manual projects.')})
return super(ProjectSerializer, self).validate(attrs)
@@ -1630,7 +1659,6 @@ class InventorySerializer(BaseSerializerWithVariables):
'has_inventory_sources',
'total_inventory_sources',
'inventory_sources_with_failures',
'insights_credential',
'pending_deletion',
)
@@ -1655,8 +1683,6 @@ class InventorySerializer(BaseSerializerWithVariables):
copy=self.reverse('api:inventory_copy', kwargs={'pk': obj.pk}),
)
)
if obj.insights_credential:
res['insights_credential'] = self.reverse('api:credential_detail', kwargs={'pk': obj.insights_credential.pk})
if obj.organization:
res['organization'] = self.reverse('api:organization_detail', kwargs={'pk': obj.organization.pk})
return res
@@ -1724,10 +1750,9 @@ class HostSerializer(BaseSerializerWithVariables):
'has_inventory_sources',
'last_job',
'last_job_host_summary',
'insights_system_id',
'ansible_facts_modified',
)
read_only_fields = ('last_job', 'last_job_host_summary', 'insights_system_id', 'ansible_facts_modified')
read_only_fields = ('last_job', 'last_job_host_summary', 'ansible_facts_modified')
def build_relational_field(self, field_name, relation_info):
field_class, field_kwargs = super(HostSerializer, self).build_relational_field(field_name, relation_info)
@@ -1751,7 +1776,6 @@ class HostSerializer(BaseSerializerWithVariables):
smart_inventories=self.reverse('api:host_smart_inventories_list', kwargs={'pk': obj.pk}),
ad_hoc_commands=self.reverse('api:host_ad_hoc_commands_list', kwargs={'pk': obj.pk}),
ad_hoc_command_events=self.reverse('api:host_ad_hoc_command_events_list', kwargs={'pk': obj.pk}),
insights=self.reverse('api:host_insights', kwargs={'pk': obj.pk}),
ansible_facts=self.reverse('api:host_ansible_facts_detail', kwargs={'pk': obj.pk}),
)
)
@@ -1968,49 +1992,6 @@ class GroupVariableDataSerializer(BaseVariableDataSerializer):
model = Group
class CustomInventoryScriptSerializer(BaseSerializer):
script = serializers.CharField(trim_whitespace=False)
show_capabilities = ['edit', 'delete', 'copy']
capabilities_prefetch = [{'edit': 'admin'}]
class Meta:
model = CustomInventoryScript
fields = ('*', "script", "organization")
def validate_script(self, value):
if not value.startswith("#!"):
raise serializers.ValidationError(_('Script must begin with a hashbang sequence: i.e.... #!/usr/bin/env python'))
return value
def to_representation(self, obj):
ret = super(CustomInventoryScriptSerializer, self).to_representation(obj)
if obj is None:
return ret
request = self.context.get('request', None)
if (
request.user not in obj.admin_role
and not request.user.is_superuser
and not request.user.is_system_auditor
and not (obj.organization is not None and request.user in obj.organization.auditor_role)
):
ret['script'] = None
return ret
def get_related(self, obj):
res = super(CustomInventoryScriptSerializer, self).get_related(obj)
res.update(
dict(
object_roles=self.reverse('api:inventory_script_object_roles_list', kwargs={'pk': obj.pk}),
copy=self.reverse('api:inventory_script_copy', kwargs={'pk': obj.pk}),
)
)
if obj.organization:
res['organization'] = self.reverse('api:organization_detail', kwargs={'pk': obj.organization.pk})
return res
class InventorySourceOptionsSerializer(BaseSerializer):
credential = DeprecatedCredentialField(help_text=_('Cloud credential to use for inventory updates.'))
@@ -2019,7 +2000,6 @@ class InventorySourceOptionsSerializer(BaseSerializer):
'*',
'source',
'source_path',
'source_script',
'source_vars',
'credential',
'enabled_var',
@@ -2037,8 +2017,6 @@ class InventorySourceOptionsSerializer(BaseSerializer):
res = super(InventorySourceOptionsSerializer, self).get_related(obj)
if obj.credential: # TODO: remove when 'credential' field is removed
res['credential'] = self.reverse('api:credential_detail', kwargs={'pk': obj.credential})
if obj.source_script:
res['source_script'] = self.reverse('api:inventory_script_detail', kwargs={'pk': obj.source_script.pk})
return res
def validate_source_vars(self, value):
@@ -2048,34 +2026,6 @@ class InventorySourceOptionsSerializer(BaseSerializer):
raise serializers.ValidationError(_("`{}` is a prohibited environment variable".format(env_k)))
return ret
def validate(self, attrs):
# TODO: Validate source
errors = {}
source = attrs.get('source', self.instance and self.instance.source or '')
source_script = attrs.get('source_script', self.instance and self.instance.source_script or '')
if source == 'custom':
if source_script is None or source_script == '':
errors['source_script'] = _("If 'source' is 'custom', 'source_script' must be provided.")
else:
try:
if not self.instance:
dest_inventory = attrs.get('inventory', None)
if not dest_inventory:
errors['inventory'] = _("Must provide an inventory.")
else:
dest_inventory = self.instance.inventory
if dest_inventory and source_script.organization != dest_inventory.organization:
errors['source_script'] = _("The 'source_script' does not belong to the same organization as the inventory.")
except Exception:
errors['source_script'] = _("'source_script' doesn't exist.")
logger.exception('Problem processing source_script validation.')
if errors:
raise serializers.ValidationError(errors)
return super(InventorySourceOptionsSerializer, self).validate(attrs)
# TODO: remove when old 'credential' fields are removed
def get_summary_fields(self, obj):
summary_fields = super(InventorySourceOptionsSerializer, self).get_summary_fields(obj)
@@ -2265,6 +2215,7 @@ class InventoryUpdateSerializer(UnifiedJobSerializer, InventorySourceOptionsSeri
'org_host_limit_error',
'source_project_update',
'custom_virtualenv',
'instance_group',
'-controller_node',
)
@@ -2530,14 +2481,14 @@ class ResourceAccessListElementSerializer(UserSerializer):
class CredentialTypeSerializer(BaseSerializer):
show_capabilities = ['edit', 'delete']
managed_by_tower = serializers.ReadOnlyField()
managed = serializers.ReadOnlyField()
class Meta:
model = CredentialType
fields = ('*', 'kind', 'namespace', 'name', 'managed_by_tower', 'inputs', 'injectors')
fields = ('*', 'kind', 'namespace', 'name', 'managed', 'inputs', 'injectors')
def validate(self, attrs):
if self.instance and self.instance.managed_by_tower:
if self.instance and self.instance.managed:
raise PermissionDenied(detail=_("Modifications not allowed for managed credential types"))
old_inputs = {}
@@ -2569,8 +2520,8 @@ class CredentialTypeSerializer(BaseSerializer):
def to_representation(self, data):
value = super(CredentialTypeSerializer, self).to_representation(data)
# translate labels and help_text for credential fields "managed by Tower"
if value.get('managed_by_tower'):
# translate labels and help_text for credential fields "managed"
if value.get('managed'):
value['name'] = _(value['name'])
for field in value.get('inputs', {}).get('fields', []):
field['label'] = _(field['label'])
@@ -2589,11 +2540,11 @@ class CredentialTypeSerializer(BaseSerializer):
class CredentialSerializer(BaseSerializer):
show_capabilities = ['edit', 'delete', 'copy', 'use']
capabilities_prefetch = ['admin', 'use']
managed_by_tower = serializers.ReadOnlyField()
managed = serializers.ReadOnlyField()
class Meta:
model = Credential
fields = ('*', 'organization', 'credential_type', 'managed_by_tower', 'inputs', 'kind', 'cloud', 'kubernetes')
fields = ('*', 'organization', 'credential_type', 'managed', 'inputs', 'kind', 'cloud', 'kubernetes')
extra_kwargs = {'credential_type': {'label': _('Credential Type')}}
def to_representation(self, data):
@@ -2660,7 +2611,7 @@ class CredentialSerializer(BaseSerializer):
return summary_dict
def validate(self, attrs):
if self.instance and self.instance.managed_by_tower:
if self.instance and self.instance.managed:
raise PermissionDenied(detail=_("Modifications not allowed for managed credentials"))
return super(CredentialSerializer, self).validate(attrs)
@@ -2672,7 +2623,7 @@ class CredentialSerializer(BaseSerializer):
return ret
def validate_organization(self, org):
if self.instance and self.instance.credential_type.kind == 'galaxy' and org is None:
if self.instance and (not self.instance.managed) and self.instance.credential_type.kind == 'galaxy' and org is None:
raise serializers.ValidationError(_("Galaxy credentials must be owned by an Organization."))
return org
@@ -2680,7 +2631,6 @@ class CredentialSerializer(BaseSerializer):
if self.instance and credential_type.pk != self.instance.credential_type.pk:
for related_objects in (
'ad_hoc_commands',
'insights_inventories',
'unifiedjobs',
'unifiedjobtemplates',
'projects',
@@ -3088,7 +3038,7 @@ class JobSerializer(UnifiedJobSerializer, JobOptionsSerializer):
res = super(JobSerializer, self).get_related(obj)
res.update(
dict(
job_events=self.reverse('api:job_job_events_list', kwargs={'pk': obj.pk}),
job_events=self.reverse('api:job_job_events_list', kwargs={'pk': obj.pk}), # TODO: consider adding job_created
job_host_summaries=self.reverse('api:job_job_host_summaries_list', kwargs={'pk': obj.pk}),
activity_stream=self.reverse('api:job_activity_stream_list', kwargs={'pk': obj.pk}),
notifications=self.reverse('api:job_notifications_list', kwargs={'pk': obj.pk}),
@@ -3155,8 +3105,8 @@ class JobDetailSerializer(JobSerializer):
fields = ('*', 'host_status_counts', 'playbook_counts', 'custom_virtualenv')
def get_playbook_counts(self, obj):
task_count = obj.job_events.filter(event='playbook_on_task_start').count()
play_count = obj.job_events.filter(event='playbook_on_play_start').count()
task_count = obj.get_event_queryset().filter(event='playbook_on_task_start').count()
play_count = obj.get_event_queryset().filter(event='playbook_on_play_start').count()
data = {'play_count': play_count, 'task_count': task_count}
@@ -3164,7 +3114,7 @@ class JobDetailSerializer(JobSerializer):
def get_host_status_counts(self, obj):
try:
counts = obj.job_events.only('event_data').get(event='playbook_on_stats').get_host_status_counts()
counts = obj.get_event_queryset().only('event_data').get(event='playbook_on_stats').get_host_status_counts()
except JobEvent.DoesNotExist:
counts = {}
@@ -3471,6 +3421,7 @@ class WorkflowJobTemplateSerializer(JobTemplateMixin, LabelsListMixin, UnifiedJo
'ask_limit_on_launch',
'webhook_service',
'webhook_credential',
'-execution_environment',
)
def get_related(self, obj):
@@ -3497,6 +3448,7 @@ class WorkflowJobTemplateSerializer(JobTemplateMixin, LabelsListMixin, UnifiedJo
survey_spec=self.reverse('api:workflow_job_template_survey_spec', kwargs={'pk': obj.pk}),
copy=self.reverse('api:workflow_job_template_copy', kwargs={'pk': obj.pk}),
)
res.pop('execution_environment', None) # EEs aren't meaningful for workflows
if obj.organization:
res['organization'] = self.reverse('api:organization_detail', kwargs={'pk': obj.organization.pk})
if obj.webhook_credential_id:
@@ -3548,6 +3500,7 @@ class WorkflowJobSerializer(LabelsListMixin, UnifiedJobSerializer):
'allow_simultaneous',
'job_template',
'is_sliced_job',
'-execution_environment',
'-execution_node',
'-event_processing_finished',
'-controller_node',
@@ -3561,6 +3514,7 @@ class WorkflowJobSerializer(LabelsListMixin, UnifiedJobSerializer):
def get_related(self, obj):
res = super(WorkflowJobSerializer, self).get_related(obj)
res.pop('execution_environment', None) # EEs aren't meaningful for workflows
if obj.workflow_job_template:
res['workflow_job_template'] = self.reverse('api:workflow_job_template_detail', kwargs={'pk': obj.workflow_job_template.pk})
res['notifications'] = self.reverse('api:workflow_job_notifications_list', kwargs={'pk': obj.pk})
@@ -3585,7 +3539,7 @@ class WorkflowJobSerializer(LabelsListMixin, UnifiedJobSerializer):
class WorkflowJobListSerializer(WorkflowJobSerializer, UnifiedJobListSerializer):
class Meta:
fields = ('*', '-execution_node', '-controller_node')
fields = ('*', '-execution_environment', '-execution_node', '-controller_node')
class WorkflowJobCancelSerializer(WorkflowJobSerializer):
@@ -4235,7 +4189,7 @@ class JobLaunchSerializer(BaseSerializer):
elif field_name == 'credentials':
for cred in obj.credentials.all():
cred_dict = dict(id=cred.id, name=cred.name, credential_type=cred.credential_type.pk, passwords_needed=cred.passwords_needed)
if cred.credential_type.managed_by_tower and 'vault_id' in cred.credential_type.defined_fields:
if cred.credential_type.managed and 'vault_id' in cred.credential_type.defined_fields:
cred_dict['vault_id'] = cred.get_input('vault_id', default=None)
defaults_dict.setdefault(field_name, []).append(cred_dict)
else:
@@ -4432,7 +4386,7 @@ class NotificationTemplateSerializer(BaseSerializer):
return res
def _recent_notifications(self, obj):
return [{'id': x.id, 'status': x.status, 'created': x.created} for x in obj.notifications.all().order_by('-created')[:5]]
return [{'id': x.id, 'status': x.status, 'created': x.created, 'error': x.error} for x in obj.notifications.all().order_by('-created')[:5]]
def get_summary_fields(self, obj):
d = super(NotificationTemplateSerializer, self).get_summary_fields(obj)
@@ -4792,7 +4746,7 @@ class ScheduleSerializer(LaunchConfigurationBaseSerializer, SchedulePreviewSeria
return summary_fields
def validate_unified_job_template(self, value):
if type(value) == InventorySource and value.source not in SCHEDULEABLE_PROVIDERS:
if type(value) == InventorySource and value.source not in CLOUD_INVENTORY_SOURCES:
raise serializers.ValidationError(_('Inventory Source must be a cloud resource.'))
elif type(value) == Project and value.scm_type == '':
raise serializers.ValidationError(_('Manual Project cannot have a schedule set.'))
@@ -4805,6 +4759,14 @@ class ScheduleSerializer(LaunchConfigurationBaseSerializer, SchedulePreviewSeria
)
return value
def validate(self, attrs):
# if the schedule is being disabled, there's no need
# validate the related UnifiedJobTemplate
# see: https://github.com/ansible/awx/issues/8641
if self.context['request'].method == 'PATCH' and attrs == {'enabled': False}:
return attrs
return super(ScheduleSerializer, self).validate(attrs)
class InstanceSerializer(BaseSerializer):
@@ -4868,10 +4830,6 @@ class InstanceGroupSerializer(BaseSerializer):
)
jobs_total = serializers.IntegerField(help_text=_('Count of all jobs that target this instance group'), read_only=True)
instances = serializers.SerializerMethodField()
is_controller = serializers.BooleanField(help_text=_('Indicates whether instance group controls any other group'), read_only=True)
is_isolated = serializers.BooleanField(
help_text=_('Indicates whether instances in this group are isolated.' 'Isolated groups have a designated controller group.'), read_only=True
)
is_container_group = serializers.BooleanField(
required=False,
help_text=_('Indicates whether instances in this group are containerized.' 'Containerized groups have a designated Openshift or Kubernetes cluster.'),
@@ -4919,9 +4877,6 @@ class InstanceGroupSerializer(BaseSerializer):
"jobs_running",
"jobs_total",
"instances",
"controller",
"is_controller",
"is_isolated",
"is_container_group",
"credential",
"policy_instance_percentage",
@@ -4935,8 +4890,6 @@ class InstanceGroupSerializer(BaseSerializer):
res = super(InstanceGroupSerializer, self).get_related(obj)
res['jobs'] = self.reverse('api:instance_group_unified_jobs_list', kwargs={'pk': obj.pk})
res['instances'] = self.reverse('api:instance_group_instance_list', kwargs={'pk': obj.pk})
if obj.controller_id:
res['controller'] = self.reverse('api:instance_group_detail', kwargs={'pk': obj.controller_id})
if obj.credential:
res['credential'] = self.reverse('api:credential_detail', kwargs={'pk': obj.credential_id})
@@ -4948,10 +4901,6 @@ class InstanceGroupSerializer(BaseSerializer):
raise serializers.ValidationError(_('Duplicate entry {}.').format(instance_name))
if not Instance.objects.filter(hostname=instance_name).exists():
raise serializers.ValidationError(_('{} is not a valid hostname of an existing instance.').format(instance_name))
if Instance.objects.get(hostname=instance_name).is_isolated():
raise serializers.ValidationError(_('Isolated instances may not be added or removed from instances groups via the API.'))
if self.instance and self.instance.controller_id is not None:
raise serializers.ValidationError(_('Isolated instance group membership may not be managed via the API.'))
if value and self.instance and self.instance.is_container_group:
raise serializers.ValidationError(_('Containerized instances may not be managed via the API'))
return value
@@ -4967,8 +4916,12 @@ class InstanceGroupSerializer(BaseSerializer):
return value
def validate_name(self, value):
if self.instance and self.instance.name == 'tower' and value != 'tower':
raise serializers.ValidationError(_('tower instance group name may not be changed.'))
if self.instance and self.instance.name == settings.DEFAULT_EXECUTION_QUEUE_NAME and value != settings.DEFAULT_EXECUTION_QUEUE_NAME:
raise serializers.ValidationError(_('%s instance group name may not be changed.' % settings.DEFAULT_EXECUTION_QUEUE_NAME))
if self.instance and self.instance.name == settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME and value != settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME:
raise serializers.ValidationError(_('%s instance group name may not be changed.' % settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME))
return value
def validate_credential(self, value):
@@ -5035,7 +4988,7 @@ class ActivityStreamSerializer(BaseSerializer):
('notification', ('id', 'status', 'notification_type', 'notification_template_id')),
('o_auth2_access_token', ('id', 'user_id', 'description', 'application_id', 'scope')),
('o_auth2_application', ('id', 'name', 'description')),
('credential_type', ('id', 'name', 'description', 'kind', 'managed_by_tower')),
('credential_type', ('id', 'name', 'description', 'kind', 'managed')),
('ad_hoc_command', ('id', 'name', 'status', 'limit')),
('workflow_approval', ('id', 'name', 'unified_job_id')),
]

View File

@@ -62,7 +62,7 @@ class SwaggerSchemaView(APIView):
renderer_classes = [CoreJSONRenderer, renderers.OpenAPIRenderer, renderers.SwaggerUIRenderer]
def get(self, request):
generator = SuperUserSchemaGenerator(title='Ansible Tower API', patterns=None, urlconf=None)
generator = SuperUserSchemaGenerator(title='Ansible Automation Platform controller API', patterns=None, urlconf=None)
schema = generator.get_schema(request=request)
# python core-api doesn't support the deprecation yet, so track it
# ourselves and return it in a response header

View File

@@ -0,0 +1 @@
{% include "api/job_job_events_list.md" %}

View File

@@ -0,0 +1 @@
{% include "api/job_job_events_list.md" %}

View File

@@ -0,0 +1,21 @@
{% include "api/sub_list_api_view.md" %}
{% ifmeth GET %}
## Special limit feature for event list views
Use the `limit` query string parameter to opt out of the pagination keys.
Doing this can improve response times for jobs that produce a large volume
of outputs.
?limit=25
This will set the page size to 25 and the `previous` and `next` keys will be
omitted from the response data. The data structure will look like this.
{
"results": [
...
]
}
{% endifmeth %}

View File

@@ -1,25 +0,0 @@
Make a GET request to retrieve the list of aggregated play data associated with a job
## Filtering
This endpoints supports a limited filtering subset:
?event_id__in=1,2,3
Will show only the given ids.
?event_id__gt=1
Will show ids greater than the given one.
?event_id__lt=3
Will show ids less than the given one.
?failed=true
Will show only failed plays. Alternatively `false` may be used.
?play__icontains=test
Will filter plays matching the substring `test`

View File

@@ -1,27 +0,0 @@
Make a GET request to retrieve the list of aggregated task data associated with the play given by event_id.
`event_id` is a required query parameter and must match the job event id of the parent play in order to receive the list of tasks associated with the play
## Filtering
This endpoints supports a limited filtering subset:
?event_id__in=1,2,3
Will show only the given task ids under the play given by `event_id`.
?event_id__gt=1
Will show ids greater than the given one.
?event_id__lt=3
Will show ids less than the given one.
?failed=true
Will show only failed plays. Alternatively `false` may be used.
?task__icontains=test
Will filter tasks matching the substring `test`

View File

@@ -0,0 +1 @@
{% include "api/job_job_events_list.md" %}

View File

@@ -0,0 +1 @@
{% include "api/job_job_events_list.md" %}

View File

@@ -16,7 +16,6 @@ from awx.api.views import (
HostSmartInventoriesList,
HostAdHocCommandsList,
HostAdHocCommandEventsList,
HostInsights,
)
@@ -33,7 +32,6 @@ urls = [
url(r'^(?P<pk>[0-9]+)/smart_inventories/$', HostSmartInventoriesList.as_view(), name='host_smart_inventories_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', HostAdHocCommandsList.as_view(), name='host_ad_hoc_commands_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_command_events/$', HostAdHocCommandEventsList.as_view(), name='host_ad_hoc_command_events_list'),
url(r'^(?P<pk>[0-9]+)/insights/$', HostInsights.as_view(), name='host_insights'),
]
__all__ = ['urls']

View File

@@ -1,16 +0,0 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from awx.api.views import InventoryScriptList, InventoryScriptDetail, InventoryScriptObjectRolesList, InventoryScriptCopy
urls = [
url(r'^$', InventoryScriptList.as_view(), name='inventory_script_list'),
url(r'^(?P<pk>[0-9]+)/$', InventoryScriptDetail.as_view(), name='inventory_script_detail'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', InventoryScriptObjectRolesList.as_view(), name='inventory_script_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/copy/$', InventoryScriptCopy.as_view(), name='inventory_script_copy'),
]
__all__ = ['urls']

View File

@@ -3,14 +3,11 @@
from django.conf.urls import url
from awx.api.views import JobEventList, JobEventDetail, JobEventChildrenList, JobEventHostsList
from awx.api.views import JobEventDetail, JobEventChildrenList
urls = [
url(r'^$', JobEventList.as_view(), name='job_event_list'),
url(r'^(?P<pk>[0-9]+)/$', JobEventDetail.as_view(), name='job_event_detail'),
url(r'^(?P<pk>[0-9]+)/children/$', JobEventChildrenList.as_view(), name='job_event_children_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', JobEventHostsList.as_view(), name='job_event_hosts_list'),
]
__all__ = ['urls']

View File

@@ -43,7 +43,6 @@ from .host import urls as host_urls
from .group import urls as group_urls
from .inventory_source import urls as inventory_source_urls
from .inventory_update import urls as inventory_update_urls
from .inventory_script import urls as inventory_script_urls
from .credential_type import urls as credential_type_urls
from .credential import urls as credential_urls
from .credential_input_source import urls as credential_input_source_urls
@@ -111,7 +110,6 @@ v2_urls = [
url(r'^groups/', include(group_urls)),
url(r'^inventory_sources/', include(inventory_source_urls)),
url(r'^inventory_updates/', include(inventory_update_urls)),
url(r'^inventory_scripts/', include(inventory_script_urls)),
url(r'^credentials/', include(credential_urls)),
url(r'^roles/', include(role_urls)),
url(r'^job_templates/', include(job_template_urls)),

View File

@@ -21,7 +21,7 @@ from urllib3.exceptions import ConnectTimeoutError
from django.conf import settings
from django.core.exceptions import FieldError, ObjectDoesNotExist
from django.db.models import Q, Sum
from django.db import IntegrityError, transaction, connection
from django.db import IntegrityError, ProgrammingError, transaction, connection
from django.shortcuts import get_object_or_404
from django.utils.safestring import mark_safe
from django.utils.timezone import now
@@ -90,17 +90,14 @@ from awx.main import models
from awx.main.utils import (
camelcase_to_underscore,
extract_ansible_vars,
get_awx_http_client_headers,
get_object_or_400,
getattrd,
get_pk_from_dict,
schedule_task_manager,
ignore_inventory_computed_fields,
set_environ,
)
from awx.main.utils.encryption import encrypt_value
from awx.main.utils.filters import SmartFilter
from awx.main.utils.insights import filter_insights_api_response
from awx.main.redact import UriCleaner
from awx.api.permissions import (
JobTemplateCallbackPermission,
@@ -152,10 +149,6 @@ from awx.api.views.inventory import ( # noqa
InventoryList,
InventoryDetail,
InventoryUpdateEventsList,
InventoryScriptList,
InventoryScriptDetail,
InventoryScriptObjectRolesList,
InventoryScriptCopy,
InventoryList,
InventoryDetail,
InventoryActivityStreamList,
@@ -176,11 +169,21 @@ from awx.api.views.root import ( # noqa
ApiV2AttachView,
)
from awx.api.views.webhooks import WebhookKeyView, GithubWebhookReceiver, GitlabWebhookReceiver # noqa
from awx.api.pagination import UnifiedJobEventPagination
logger = logging.getLogger('awx.api.views')
def unpartitioned_event_horizon(cls):
with connection.cursor() as cursor:
try:
cursor.execute(f'SELECT MAX(id) FROM _unpartitioned_{cls._meta.db_table}')
return cursor.fetchone()[0] or -1
except ProgrammingError:
return 0
def api_exception_handler(exc, context):
"""
Override default API exception handler to catch IntegrityError exceptions.
@@ -211,7 +214,7 @@ class DashboardView(APIView):
swagger_topic = 'Dashboard'
def get(self, request, format=None):
''' Show Dashboard Details '''
'''Show Dashboard Details'''
data = OrderedDict()
data['related'] = {'jobs_graph': reverse('api:dashboard_jobs_graph_view', request=request)}
user_inventory = get_user_queryset(request.user, models.Inventory)
@@ -422,14 +425,6 @@ class InstanceGroupDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAP
data.pop('policy_instance_list', None)
return super(InstanceGroupDetail, self).update_raw_data(data)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.controller is not None:
raise PermissionDenied(detail=_("Isolated Groups can not be removed from the API"))
if instance.controlled_groups.count():
raise PermissionDenied(detail=_("Instance Groups acting as a controller for an Isolated Group can not be removed from the API"))
return super(InstanceGroupDetail, self).destroy(request, *args, **kwargs)
class InstanceGroupUnifiedJobsList(SubListAPIView):
@@ -546,7 +541,7 @@ class ScheduleUnifiedJobsList(SubListAPIView):
class AuthView(APIView):
''' List enabled single-sign-on endpoints '''
'''List enabled single-sign-on endpoints'''
authentication_classes = []
permission_classes = (AllowAny,)
@@ -710,6 +705,21 @@ class ExecutionEnvironmentDetail(RetrieveUpdateDestroyAPIView):
serializer_class = serializers.ExecutionEnvironmentSerializer
swagger_topic = "Execution Environments"
def update(self, request, *args, **kwargs):
instance = self.get_object()
fields_to_check = ['name', 'description', 'organization', 'image', 'credential']
if instance.managed and request.user.can_access(models.ExecutionEnvironment, 'change', instance):
for field in fields_to_check:
if kwargs.get('partial') and field not in request.data:
continue
left = getattr(instance, field, None)
if hasattr(left, 'id'):
left = left.id
right = request.data.get(field)
if left != right:
raise PermissionDenied(_("Only the 'pull' field can be edited for managed execution environments."))
return super().update(request, *args, **kwargs)
class ExecutionEnvironmentJobTemplateList(SubListAPIView):
@@ -892,11 +902,17 @@ class ProjectUpdateEventsList(SubListAPIView):
relationship = 'project_update_events'
name = _('Project Update Events List')
search_fields = ('stdout',)
pagination_class = UnifiedJobEventPagination
def finalize_response(self, request, response, *args, **kwargs):
response['X-UI-Max-Events'] = settings.MAX_UI_JOB_EVENTS
return super(ProjectUpdateEventsList, self).finalize_response(request, response, *args, **kwargs)
def get_queryset(self):
pu = self.get_parent_object()
self.check_parent_access(pu)
return pu.get_event_queryset()
class SystemJobEventsList(SubListAPIView):
@@ -906,11 +922,17 @@ class SystemJobEventsList(SubListAPIView):
relationship = 'system_job_events'
name = _('System Job Events List')
search_fields = ('stdout',)
pagination_class = UnifiedJobEventPagination
def finalize_response(self, request, response, *args, **kwargs):
response['X-UI-Max-Events'] = settings.MAX_UI_JOB_EVENTS
return super(SystemJobEventsList, self).finalize_response(request, response, *args, **kwargs)
def get_queryset(self):
job = self.get_parent_object()
self.check_parent_access(job)
return job.get_event_queryset()
class ProjectUpdateCancel(RetrieveAPIView):
@@ -1237,7 +1259,7 @@ class UserDetail(RetrieveUpdateDestroyAPIView):
serializer_class = serializers.UserSerializer
def update_filter(self, request, *args, **kwargs):
''' make sure non-read-only fields that can only be edited by admins, are only edited by admins '''
'''make sure non-read-only fields that can only be edited by admins, are only edited by admins'''
obj = self.get_object()
can_change = request.user.can_access(models.User, 'change', obj, request.data)
can_admin = request.user.can_access(models.User, 'admin', obj, request.data)
@@ -1288,7 +1310,7 @@ class CredentialTypeDetail(RetrieveUpdateDestroyAPIView):
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.managed_by_tower:
if instance.managed:
raise PermissionDenied(detail=_("Deletion not allowed for managed credential types"))
if instance.credentials.exists():
raise PermissionDenied(detail=_("Credential types that are in use cannot be deleted"))
@@ -1403,7 +1425,7 @@ class CredentialDetail(RetrieveUpdateDestroyAPIView):
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.managed_by_tower:
if instance.managed:
raise PermissionDenied(detail=_("Deletion not allowed for managed credentials"))
return super(CredentialDetail, self).destroy(request, *args, **kwargs)
@@ -1600,7 +1622,7 @@ class InventoryHostsList(HostRelatedSearchMixin, SubListCreateAttachDetachAPIVie
class HostGroupsList(ControlledByScmMixin, SubListCreateAttachDetachAPIView):
''' the list of groups a host is directly a member of '''
'''the list of groups a host is directly a member of'''
model = models.Group
serializer_class = serializers.GroupSerializer
@@ -1622,7 +1644,7 @@ class HostGroupsList(ControlledByScmMixin, SubListCreateAttachDetachAPIView):
class HostAllGroupsList(SubListAPIView):
''' the list of all groups of which the host is directly or indirectly a member '''
'''the list of all groups of which the host is directly or indirectly a member'''
model = models.Group
serializer_class = serializers.GroupSerializer
@@ -1679,106 +1701,6 @@ class GatewayTimeout(APIException):
default_code = 'gateway_timeout'
class HostInsights(GenericAPIView):
model = models.Host
serializer_class = serializers.EmptySerializer
def _call_insights_api(self, url, session, headers):
try:
with set_environ(**settings.AWX_TASK_ENV):
res = session.get(url, headers=headers, timeout=120)
except requests.exceptions.SSLError:
raise BadGateway(_('SSLError while trying to connect to {}').format(url))
except requests.exceptions.Timeout:
raise GatewayTimeout(_('Request to {} timed out.').format(url))
except requests.exceptions.RequestException as e:
raise BadGateway(_('Unknown exception {} while trying to GET {}').format(e, url))
if res.status_code == 401:
raise BadGateway(_('Unauthorized access. Please check your Insights Credential username and password.'))
elif res.status_code != 200:
raise BadGateway(
_('Failed to access the Insights API at URL {}.' ' Server responded with {} status code and message {}').format(
url, res.status_code, res.content
)
)
try:
return res.json()
except ValueError:
raise BadGateway(_('Expected JSON response from Insights at URL {}' ' but instead got {}').format(url, res.content))
def _get_session(self, username, password):
session = requests.Session()
session.auth = requests.auth.HTTPBasicAuth(username, password)
return session
def _get_platform_info(self, host, session, headers):
url = '{}/api/inventory/v1/hosts?insights_id={}'.format(settings.INSIGHTS_URL_BASE, host.insights_system_id)
res = self._call_insights_api(url, session, headers)
try:
res['results'][0]['id']
except (IndexError, KeyError):
raise NotFound(_('Could not translate Insights system ID {}' ' into an Insights platform ID.').format(host.insights_system_id))
return res['results'][0]
def _get_reports(self, platform_id, session, headers):
url = '{}/api/insights/v1/system/{}/reports/'.format(settings.INSIGHTS_URL_BASE, platform_id)
return self._call_insights_api(url, session, headers)
def _get_remediations(self, platform_id, session, headers):
url = '{}/api/remediations/v1/remediations?system={}'.format(settings.INSIGHTS_URL_BASE, platform_id)
remediations = []
# Iterate over all of the pages of content.
while url:
data = self._call_insights_api(url, session, headers)
remediations.extend(data['data'])
url = data['links']['next'] # Will be `None` if this is the last page.
return remediations
def _get_insights(self, host, session, headers):
platform_info = self._get_platform_info(host, session, headers)
platform_id = platform_info['id']
reports = self._get_reports(platform_id, session, headers)
remediations = self._get_remediations(platform_id, session, headers)
return {'insights_content': filter_insights_api_response(platform_info, reports, remediations)}
def get(self, request, *args, **kwargs):
host = self.get_object()
cred = None
if host.insights_system_id is None:
return Response(dict(error=_('This host is not recognized as an Insights host.')), status=status.HTTP_404_NOT_FOUND)
if host.inventory and host.inventory.insights_credential:
cred = host.inventory.insights_credential
else:
return Response(dict(error=_('The Insights Credential for "{}" was not found.').format(host.inventory.name)), status=status.HTTP_404_NOT_FOUND)
username = cred.get_input('username', default='')
password = cred.get_input('password', default='')
session = self._get_session(username, password)
headers = get_awx_http_client_headers()
data = self._get_insights(host, session, headers)
return Response(data, status=status.HTTP_200_OK)
def handle_exception(self, exc):
# Continue supporting the slightly different way we have handled error responses on this view.
response = super().handle_exception(exc)
response.data['error'] = response.data.pop('detail')
return response
class GroupList(ListCreateAPIView):
model = models.Group
@@ -1862,7 +1784,7 @@ class GroupPotentialChildrenList(SubListAPIView):
class GroupHostsList(HostRelatedSearchMixin, ControlledByScmMixin, SubListCreateAttachDetachAPIView):
''' the list of hosts directly below a group '''
'''the list of hosts directly below a group'''
model = models.Host
serializer_class = serializers.HostSerializer
@@ -1887,7 +1809,7 @@ class GroupHostsList(HostRelatedSearchMixin, ControlledByScmMixin, SubListCreate
class GroupAllHostsList(HostRelatedSearchMixin, SubListAPIView):
''' the list of all hosts below a group, even including subgroups '''
'''the list of all hosts below a group, even including subgroups'''
model = models.Host
serializer_class = serializers.HostSerializer
@@ -3616,7 +3538,7 @@ class JobRelaunch(RetrieveAPIView):
status=status.HTTP_400_BAD_REQUEST,
)
host_qs = obj.retry_qs(retry_hosts)
if not obj.job_events.filter(event='playbook_on_stats').exists():
if not obj.get_event_queryset().filter(event='playbook_on_stats').exists():
return Response(
{'hosts': _('Cannot retry on {status_value} hosts, playbook stats not available.').format(status_value=retry_hosts)},
status=status.HTTP_400_BAD_REQUEST,
@@ -3743,18 +3665,22 @@ class JobHostSummaryDetail(RetrieveAPIView):
serializer_class = serializers.JobHostSummarySerializer
class JobEventList(NoTruncateMixin, ListAPIView):
model = models.JobEvent
serializer_class = serializers.JobEventSerializer
search_fields = ('stdout',)
class JobEventDetail(RetrieveAPIView):
model = models.JobEvent
serializer_class = serializers.JobEventSerializer
@property
def is_partitioned(self):
if 'pk' not in self.kwargs:
return True
return int(self.kwargs['pk']) > unpartitioned_event_horizon(models.JobEvent)
@property
def model(self):
if self.is_partitioned:
return models.JobEvent
return models.UnpartitionedJobEvent
def get_serializer_context(self):
context = super().get_serializer_context()
context.update(no_truncate=True)
@@ -3763,33 +3689,31 @@ class JobEventDetail(RetrieveAPIView):
class JobEventChildrenList(NoTruncateMixin, SubListAPIView):
model = models.JobEvent
serializer_class = serializers.JobEventSerializer
parent_model = models.JobEvent
relationship = 'children'
name = _('Job Event Children List')
search_fields = ('stdout',)
def get_queryset(self):
parent_event = self.get_parent_object()
self.check_parent_access(parent_event)
qs = self.request.user.get_queryset(self.model).filter(parent_uuid=parent_event.uuid)
return qs
@property
def is_partitioned(self):
if 'pk' not in self.kwargs:
return True
return int(self.kwargs['pk']) > unpartitioned_event_horizon(models.JobEvent)
@property
def model(self):
if self.is_partitioned:
return models.JobEvent
return models.UnpartitionedJobEvent
class JobEventHostsList(HostRelatedSearchMixin, SubListAPIView):
model = models.Host
serializer_class = serializers.HostSerializer
parent_model = models.JobEvent
relationship = 'hosts'
name = _('Job Event Hosts List')
@property
def parent_model(self):
return self.model
def get_queryset(self):
parent_event = self.get_parent_object()
self.check_parent_access(parent_event)
qs = self.request.user.get_queryset(self.model).filter(job_events_as_primary_host=parent_event)
return qs
return parent_event.job.get_event_queryset().filter(parent_uuid=parent_event.uuid)
class BaseJobEventsList(NoTruncateMixin, SubListAPIView):
@@ -3825,12 +3749,12 @@ class GroupJobEventsList(BaseJobEventsList):
class JobJobEventsList(BaseJobEventsList):
parent_model = models.Job
pagination_class = UnifiedJobEventPagination
def get_queryset(self):
job = self.get_parent_object()
self.check_parent_access(job)
qs = job.job_events.select_related('host').order_by('start_line')
return qs.all()
return job.get_event_queryset().select_related('host').order_by('start_line')
class AdHocCommandList(ListCreateAPIView):
@@ -3988,6 +3912,11 @@ class AdHocCommandEventList(NoTruncateMixin, ListAPIView):
serializer_class = serializers.AdHocCommandEventSerializer
search_fields = ('stdout',)
def get_queryset(self):
adhoc = self.get_parent_object()
self.check_parent_access(adhoc)
return adhoc.get_event_queryset()
class AdHocCommandEventDetail(RetrieveAPIView):
@@ -4008,12 +3937,21 @@ class BaseAdHocCommandEventsList(NoTruncateMixin, SubListAPIView):
relationship = 'ad_hoc_command_events'
name = _('Ad Hoc Command Events List')
search_fields = ('stdout',)
pagination_class = UnifiedJobEventPagination
def get_queryset(self):
parent = self.get_parent_object()
self.check_parent_access(parent)
return parent.get_event_queryset()
class HostAdHocCommandEventsList(BaseAdHocCommandEventsList):
parent_model = models.Host
def get_queryset(self):
return super(BaseAdHocCommandEventsList, self).get_queryset()
# class GroupJobEventsList(BaseJobEventsList):
# parent_model = Group
@@ -4262,13 +4200,13 @@ class NotificationTemplateTest(GenericAPIView):
def post(self, request, *args, **kwargs):
obj = self.get_object()
msg = "Tower Notification Test {} {}".format(obj.id, settings.TOWER_URL_BASE)
msg = "Notification Test {} {}".format(obj.id, settings.TOWER_URL_BASE)
if obj.notification_type in ('email', 'pagerduty'):
body = "Ansible Tower Test Notification {} {}".format(obj.id, settings.TOWER_URL_BASE)
body = "Test Notification {} {}".format(obj.id, settings.TOWER_URL_BASE)
elif obj.notification_type in ('webhook', 'grafana'):
body = '{{"body": "Ansible Tower Test Notification {} {}"}}'.format(obj.id, settings.TOWER_URL_BASE)
body = '{{"body": "Test Notification {} {}"}}'.format(obj.id, settings.TOWER_URL_BASE)
else:
body = {"body": "Ansible Tower Test Notification {} {}".format(obj.id, settings.TOWER_URL_BASE)}
body = {"body": "Test Notification {} {}".format(obj.id, settings.TOWER_URL_BASE)}
notification = obj.generate_notification(msg, body)
if not notification:

View File

@@ -25,8 +25,6 @@ from awx.main.models import (
InstanceGroup,
InventoryUpdateEvent,
InventoryUpdate,
InventorySource,
CustomInventoryScript,
)
from awx.api.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView, SubListAPIView, SubListAttachDetachAPIView, ResourceAccessList, CopyAPIView
@@ -36,11 +34,13 @@ from awx.api.serializers import (
RoleSerializer,
InstanceGroupSerializer,
InventoryUpdateEventSerializer,
CustomInventoryScriptSerializer,
JobTemplateSerializer,
)
from awx.api.views.mixin import RelatedJobsPreventDeleteMixin, ControlledByScmMixin
from awx.api.pagination import UnifiedJobEventPagination
logger = logging.getLogger('awx.api.views.organization')
@@ -52,61 +52,18 @@ class InventoryUpdateEventsList(SubListAPIView):
relationship = 'inventory_update_events'
name = _('Inventory Update Events List')
search_fields = ('stdout',)
pagination_class = UnifiedJobEventPagination
def get_queryset(self):
iu = self.get_parent_object()
self.check_parent_access(iu)
return iu.get_event_queryset()
def finalize_response(self, request, response, *args, **kwargs):
response['X-UI-Max-Events'] = settings.MAX_UI_JOB_EVENTS
return super(InventoryUpdateEventsList, self).finalize_response(request, response, *args, **kwargs)
class InventoryScriptList(ListCreateAPIView):
deprecated = True
model = CustomInventoryScript
serializer_class = CustomInventoryScriptSerializer
class InventoryScriptDetail(RetrieveUpdateDestroyAPIView):
deprecated = True
model = CustomInventoryScript
serializer_class = CustomInventoryScriptSerializer
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
can_delete = request.user.can_access(self.model, 'delete', instance)
if not can_delete:
raise PermissionDenied(_("Cannot delete inventory script."))
for inv_src in InventorySource.objects.filter(source_script=instance):
inv_src.source_script = None
inv_src.save()
return super(InventoryScriptDetail, self).destroy(request, *args, **kwargs)
class InventoryScriptObjectRolesList(SubListAPIView):
deprecated = True
model = Role
serializer_class = RoleSerializer
parent_model = CustomInventoryScript
search_fields = ('role_field', 'content_type__model')
def get_queryset(self):
po = self.get_parent_object()
content_type = ContentType.objects.get_for_model(self.parent_model)
return Role.objects.filter(content_type=content_type, object_id=po.pk)
class InventoryScriptCopy(CopyAPIView):
deprecated = True
model = CustomInventoryScript
copy_return_serializer_class = CustomInventoryScriptSerializer
class InventoryList(ListCreateAPIView):
model = Inventory

View File

@@ -32,7 +32,7 @@ class MetricsView(APIView):
renderer_classes = [renderers.PlainTextRenderer, renderers.PrometheusJSONRenderer, renderers.BrowsableAPIRenderer]
def get(self, request):
''' Show Metrics Details '''
'''Show Metrics Details'''
if request.user.is_superuser or request.user.is_system_auditor:
metrics_to_show = ''
if not request.query_params.get('subsystemonly', "0") == "1":

View File

@@ -52,6 +52,11 @@ class UnifiedJobDeletionMixin(object):
else:
# if it has been > 1 minute, events are probably lost
logger.warning('Allowing deletion of {} through the API without all events ' 'processed.'.format(obj.log_format))
# Manually cascade delete events if unpartitioned job
if obj.has_unpartitioned_events:
obj.get_event_queryset().delete()
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@@ -85,15 +90,6 @@ class InstanceGroupMembershipMixin(object):
ig_obj.save(update_fields=['policy_instance_list'])
return response
def is_valid_relation(self, parent, sub, created=False):
if sub.is_isolated():
return {'error': _('Isolated instances may not be added or removed from instances groups via the API.')}
if self.parent_model is InstanceGroup:
ig_obj = self.get_parent_object()
if ig_obj.controller_id is not None:
return {'error': _('Isolated instance group membership may not be managed via the API.')}
return None
def unattach_validate(self, request):
(sub_id, res) = super(InstanceGroupMembershipMixin, self).unattach_validate(request)
if res:

View File

@@ -24,12 +24,13 @@ 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, get_custom_venv_choices, to_python_boolean
from awx.main.utils import get_awx_version, get_custom_venv_choices
from awx.main.utils.licensing import validate_entitlement_manifest
from awx.api.versioning import reverse, drf_reverse
from awx.main.constants import PRIVILEGE_ESCALATION_METHODS
from awx.main.models import Project, Organization, Instance, InstanceGroup, JobTemplate
from awx.main.utils import set_environ
from awx.main.utils.licensing import get_licenser
logger = logging.getLogger('awx.api.views.root')
@@ -43,7 +44,7 @@ class ApiRootView(APIView):
@method_decorator(ensure_csrf_cookie)
def get(self, request, format=None):
''' List supported API versions '''
'''List supported API versions'''
v2 = reverse('api:api_v2_root_view', kwargs={'version': 'v2'})
data = OrderedDict()
@@ -78,7 +79,7 @@ class ApiVersionRootView(APIView):
swagger_topic = 'Versioning'
def get(self, request, format=None):
''' List top level resources '''
'''List top level resources'''
data = OrderedDict()
data['ping'] = reverse('api:api_v2_ping_view', request=request)
data['instances'] = reverse('api:instance_list', request=request)
@@ -100,14 +101,12 @@ class ApiVersionRootView(APIView):
data['tokens'] = reverse('api:o_auth2_token_list', request=request)
data['metrics'] = reverse('api:metrics_view', request=request)
data['inventory'] = reverse('api:inventory_list', request=request)
data['inventory_scripts'] = reverse('api:inventory_script_list', request=request)
data['inventory_sources'] = reverse('api:inventory_source_list', request=request)
data['inventory_updates'] = reverse('api:inventory_update_list', request=request)
data['groups'] = reverse('api:group_list', request=request)
data['hosts'] = reverse('api:host_list', request=request)
data['job_templates'] = reverse('api:job_template_list', request=request)
data['jobs'] = reverse('api:job_list', request=request)
data['job_events'] = reverse('api:job_event_list', request=request)
data['ad_hoc_commands'] = reverse('api:ad_hoc_command_list', request=request)
data['system_job_templates'] = reverse('api:system_job_template_list', request=request)
data['system_jobs'] = reverse('api:system_job_list', request=request)
@@ -175,8 +174,6 @@ class ApiV2SubscriptionView(APIView):
self.permission_denied(request) # Raises PermissionDenied exception.
def post(self, request):
from awx.main.utils.common import get_licenser
data = request.data.copy()
if data.get('subscriptions_password') == '$encrypted$':
data['subscriptions_password'] = settings.SUBSCRIPTIONS_PASSWORD
@@ -224,7 +221,6 @@ class ApiV2AttachView(APIView):
user = getattr(settings, 'SUBSCRIPTIONS_USERNAME', None)
pw = getattr(settings, 'SUBSCRIPTIONS_PASSWORD', None)
if pool_id and user and pw:
from awx.main.utils.common import get_licenser
data = request.data.copy()
try:
@@ -266,8 +262,6 @@ class ApiV2ConfigView(APIView):
def get(self, request, format=None):
'''Return various sitewide configuration settings'''
from awx.main.utils.common import get_licenser
license_data = get_licenser().validate()
if not license_data.get('valid_key', False):
@@ -303,7 +297,9 @@ class ApiV2ConfigView(APIView):
):
data.update(
dict(
project_base_dir=settings.PROJECTS_ROOT, project_local_paths=Project.get_local_path_choices(), custom_virtualenvs=get_custom_venv_choices()
project_base_dir=settings.PROJECTS_ROOT,
project_local_paths=Project.get_local_path_choices(),
custom_virtualenvs=get_custom_venv_choices(),
)
)
elif JobTemplate.accessible_objects(request.user, 'admin_role').exists():
@@ -314,24 +310,12 @@ class ApiV2ConfigView(APIView):
def post(self, request):
if not isinstance(request.data, dict):
return Response({"error": _("Invalid subscription data")}, status=status.HTTP_400_BAD_REQUEST)
if "eula_accepted" not in request.data:
return Response({"error": _("Missing 'eula_accepted' property")}, status=status.HTTP_400_BAD_REQUEST)
try:
eula_accepted = to_python_boolean(request.data["eula_accepted"])
except ValueError:
return Response({"error": _("'eula_accepted' value is invalid")}, status=status.HTTP_400_BAD_REQUEST)
if not eula_accepted:
return Response({"error": _("'eula_accepted' must be True")}, status=status.HTTP_400_BAD_REQUEST)
request.data.pop("eula_accepted")
try:
data_actual = json.dumps(request.data)
except Exception:
logger.info(smart_text(u"Invalid JSON submitted for license."), extra=dict(actor=request.user.username))
return Response({"error": _("Invalid JSON")}, status=status.HTTP_400_BAD_REQUEST)
from awx.main.utils.common import get_licenser
license_data = json.loads(data_actual)
if 'license_key' in license_data:
return Response({"error": _('Legacy license submitted. A subscription manifest is now required.')}, status=status.HTTP_400_BAD_REQUEST)

View File

@@ -30,8 +30,8 @@ if MODE == 'production':
except FileNotFoundError:
pass
except ValueError as e:
logger.error("Missing or incorrect metadata for Tower version. Ensure Tower was installed using the setup playbook.")
raise Exception("Missing or incorrect metadata for Tower version. Ensure Tower was installed using the setup playbook.") from e
logger.error("Missing or incorrect metadata for controller version. Ensure controller was installed using the setup playbook.")
raise Exception("Missing or incorrect metadata for controller version. Ensure controller was installed using the setup playbook.") from e
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "awx.settings")

View File

@@ -4,7 +4,7 @@
# Django
from django.utils.module_loading import autodiscover_modules
# Tower
# AWX
from .registry import settings_registry
default_app_config = 'awx.conf.apps.ConfConfig'

View File

@@ -4,7 +4,7 @@
# Django
from django.db.models import Q
# Tower
# AWX
from awx.main.access import BaseAccess, register_access
from awx.conf.models import Setting

View File

@@ -2,7 +2,7 @@
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
# Tower
# AWX
from awx.conf import fields, register
from awx.conf import settings_registry

View File

@@ -11,5 +11,5 @@ def _get_validated_license_data():
def get_license():
"""Return a dictionary representing the active license on this Tower instance."""
"""Return a dictionary representing the active license on this instance."""
return _get_validated_license_data()

View File

@@ -7,7 +7,7 @@ import json
# Django
from django.db import models
# Tower
# AWX
from awx.main.models.base import CreatedModifiedModel, prevent_search
from awx.main.fields import JSONField
from awx.main.utils import encrypt_field

View File

@@ -92,11 +92,7 @@ class SettingsRegistry(object):
continue
if kwargs.get('category_slug', None) in slugs_to_ignore:
continue
if (
read_only in {True, False}
and kwargs.get('read_only', False) != read_only
and setting not in ('INSTALL_UUID', 'AWX_ISOLATED_PRIVATE_KEY', 'AWX_ISOLATED_PUBLIC_KEY')
):
if read_only in {True, False} and kwargs.get('read_only', False) != read_only and setting != 'INSTALL_UUID':
# Note: Doesn't catch fields that set read_only via __init__;
# read-only field kwargs should always include read_only=True.
continue

View File

@@ -1,7 +1,7 @@
# Django REST Framework
from rest_framework import serializers
# Tower
# AWX
from awx.api.fields import VerbatimField
from awx.api.serializers import BaseSerializer
from awx.conf.models import Setting
@@ -28,7 +28,7 @@ class SettingSerializer(BaseSerializer):
class SettingCategorySerializer(serializers.Serializer):
"""Serialize setting category """
"""Serialize setting category"""
url = serializers.CharField(read_only=True)
slug = serializers.CharField(read_only=True)
@@ -81,10 +81,8 @@ class SettingSingletonSerializer(serializers.Serializer):
if self.instance and not hasattr(self.instance, key):
continue
extra_kwargs = {}
# Make LICENSE and AWX_ISOLATED_KEY_GENERATION read-only here;
# LICENSE is only updated via /api/v2/config/
# AWX_ISOLATED_KEY_GENERATION is only set/unset via the setup playbook
if key in ('LICENSE', 'AWX_ISOLATED_KEY_GENERATION'):
# Make LICENSE read-only here; LICENSE is only updated via /api/v2/config/
if key == 'LICENSE':
extra_kwargs['read_only'] = True
field = settings_registry.get_setting_field(key, mixin_class=SettingFieldMixin, for_user=bool(category_slug == 'user'), **extra_kwargs)
fields[key] = field

View File

@@ -20,9 +20,10 @@ from rest_framework.fields import empty, SkipField
import cachetools
# Tower
# AWX
from awx.main.utils import encrypt_field, decrypt_field
from awx.conf import settings_registry
from awx.conf.fields import PrimaryKeyRelatedField
from awx.conf.models import Setting
from awx.conf.migrations._reencrypt import decrypt_field as old_decrypt_field
@@ -350,13 +351,8 @@ class SettingsWrapper(UserSettingsHolder):
if value is empty:
setting = None
setting_id = None
if not field.read_only or name in (
# these values are read-only - however - we *do* want
# to fetch their value from the database
'INSTALL_UUID',
'AWX_ISOLATED_PRIVATE_KEY',
'AWX_ISOLATED_PUBLIC_KEY',
):
# this value is read-only, however we *do* want to fetch its value from the database
if not field.read_only or name == 'INSTALL_UUID':
setting = Setting.objects.filter(key=name, user__isnull=True).order_by('pk').first()
if setting:
if getattr(field, 'encrypted', False):
@@ -425,9 +421,9 @@ class SettingsWrapper(UserSettingsHolder):
raise ImproperlyConfigured('Setting "{}" is read only.'.format(name))
try:
data = field.to_representation(value)
data = None if value is None and isinstance(field, PrimaryKeyRelatedField) else field.to_representation(value)
setting_value = field.run_validation(data)
db_value = field.to_representation(setting_value)
db_value = None if setting_value is None and isinstance(field, PrimaryKeyRelatedField) else field.to_representation(setting_value)
except Exception as e:
logger.exception('Unable to assign value "%r" to setting "%s".', value, name, exc_info=True)
raise e

View File

@@ -3,12 +3,12 @@ import logging
# Django
from django.conf import settings
from django.core.cache import cache
from django.core.signals import setting_changed
from django.db.models.signals import post_save, pre_delete, post_delete
from django.core.cache import cache
from django.dispatch import receiver
# Tower
# AWX
from awx.conf import settings_registry
from awx.conf.models import Setting
@@ -25,7 +25,7 @@ def handle_setting_change(key, for_delete=False):
# Note: Doesn't handle multiple levels of dependencies!
setting_keys.append(dependent_key)
# NOTE: This block is probably duplicated.
cache_keys = set([Setting.get_cache_key(k) for k in setting_keys])
cache_keys = {Setting.get_cache_key(k) for k in setting_keys}
cache.delete_many(cache_keys)
# Send setting_changed signal with new value for each setting.
@@ -58,3 +58,18 @@ def on_post_delete_setting(sender, **kwargs):
key = getattr(instance, '_saved_key_', None)
if key:
handle_setting_change(key, True)
@receiver(setting_changed)
def disable_local_auth(**kwargs):
if (kwargs['setting'], kwargs['value']) == ('DISABLE_LOCAL_AUTH', True):
from django.contrib.auth.models import User
from oauth2_provider.models import RefreshToken
from awx.main.models.oauth import OAuth2AccessToken
from awx.main.management.commands.revoke_oauth2_tokens import revoke_tokens
logger.warning("Triggering token invalidation for local users.")
qs = User.objects.filter(profile__ldap_dn='', enterprise_auth__isnull=True, social_auth__isnull=True)
revoke_tokens(RefreshToken.objects.filter(revoked=None, user__in=qs))
revoke_tokens(OAuth2AccessToken.objects.filter(user__in=qs))

View File

@@ -21,7 +21,7 @@ from rest_framework.response import Response
from rest_framework import serializers
from rest_framework import status
# Tower
# AWX
from awx.api.generics import APIView, GenericAPIView, ListAPIView, RetrieveUpdateDestroyAPIView
from awx.api.permissions import IsSuperUser
from awx.api.versioning import reverse

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

@@ -34,7 +34,6 @@ from awx.main.models import (
Credential,
CredentialType,
CredentialInputSource,
CustomInventoryScript,
ExecutionEnvironment,
Group,
Host,
@@ -46,6 +45,7 @@ from awx.main.models import (
InventoryUpdateEvent,
Job,
JobEvent,
UnpartitionedJobEvent,
JobHostSummary,
JobLaunchConfig,
JobTemplate,
@@ -465,7 +465,7 @@ class BaseAccess(object):
if display_method == 'schedule':
user_capabilities['schedule'] = user_capabilities['start']
continue
elif display_method == 'delete' and not isinstance(obj, (User, UnifiedJob, CustomInventoryScript, CredentialInputSource)):
elif display_method == 'delete' and not isinstance(obj, (User, UnifiedJob, CredentialInputSource, ExecutionEnvironment)):
user_capabilities['delete'] = user_capabilities['edit']
continue
elif display_method == 'copy' and isinstance(obj, (Group, Host)):
@@ -867,13 +867,11 @@ class InventoryAccess(BaseAccess):
# If no data is specified, just checking for generic add permission?
if not data:
return Organization.accessible_objects(self.user, 'inventory_admin_role').exists()
return self.check_related('organization', Organization, data, role_field='inventory_admin_role') and self.check_related(
'insights_credential', Credential, data, role_field='use_role'
)
return self.check_related('organization', Organization, data, role_field='inventory_admin_role')
@check_superuser
def can_change(self, obj, data):
return self.can_admin(obj, data) and self.check_related('insights_credential', Credential, data, obj=obj, role_field='use_role')
return self.can_admin(obj, data)
@check_superuser
def can_admin(self, obj, data):
@@ -1031,14 +1029,14 @@ class InventorySourceAccess(NotificationAttachMixin, BaseAccess):
model = InventorySource
select_related = ('created_by', 'modified_by', 'inventory')
prefetch_related = ('credentials__credential_type', 'last_job', 'source_script', 'source_project')
prefetch_related = ('credentials__credential_type', 'last_job', 'source_project')
def filtered_queryset(self):
return self.model.objects.filter(inventory__in=Inventory.accessible_pk_qs(self.user, 'read_role'))
def can_add(self, data):
if not data or 'inventory' not in data:
return Organization.accessible_objects(self.user, 'admin_role').exists()
return Inventory.accessible_objects(self.user, 'admin_role').exists()
if not self.check_related('source_project', Project, data, role_field='use_role'):
return False
@@ -1093,7 +1091,7 @@ class InventoryUpdateAccess(BaseAccess):
'modified_by',
'inventory_source',
)
prefetch_related = ('unified_job_template', 'instance_group', 'credentials__credential_type', 'inventory', 'source_script')
prefetch_related = ('unified_job_template', 'instance_group', 'credentials__credential_type', 'inventory')
def filtered_queryset(self):
return self.model.objects.filter(inventory_source__inventory__in=Inventory.accessible_pk_qs(self.user, 'read_role'))
@@ -1121,7 +1119,7 @@ class CredentialTypeAccess(BaseAccess):
I can create when:
- I'm a superuser:
I can change when:
- I'm a superuser and the type is not "managed by Tower"
- I'm a superuser and the type is not "managed"
"""
model = CredentialType
@@ -1207,7 +1205,7 @@ 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:
if getattr(obj, 'managed', False) is True:
user_capabilities['edit'] = user_capabilities['delete'] = False
return user_capabilities
@@ -1357,11 +1355,8 @@ class ExecutionEnvironmentAccess(BaseAccess):
return Organization.accessible_objects(self.user, 'execution_environment_admin_role').exists()
return self.check_related('organization', Organization, data, mandatory=True, role_field='execution_environment_admin_role')
@check_superuser
def can_change(self, obj, data):
if obj.managed_by_tower:
raise PermissionDenied
if self.user.is_superuser:
return True
if obj and obj.organization_id is None:
raise PermissionDenied
if self.user not in obj.organization.execution_environment_admin_role:
@@ -1373,6 +1368,8 @@ class ExecutionEnvironmentAccess(BaseAccess):
return self.check_related('organization', Organization, data, obj=obj, mandatory=True, role_field='execution_environment_admin_role')
def can_delete(self, obj):
if obj.managed:
raise PermissionDenied
return self.can_change(obj, None)
@@ -2356,6 +2353,11 @@ class JobEventAccess(BaseAccess):
return False
class UnpartitionedJobEventAccess(JobEventAccess):
model = UnpartitionedJobEvent
class ProjectUpdateEventAccess(BaseAccess):
"""
I can see project update event records whenever I can access the project update
@@ -2627,7 +2629,7 @@ class LabelAccess(BaseAccess):
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'))
)
).distinct()
@check_superuser
def can_add(self, data):
@@ -2671,7 +2673,6 @@ class ActivityStreamAccess(BaseAccess):
'role',
'actor',
'schedule',
'custom_inventory_script',
'unified_job_template',
'workflow_job_template_node',
)
@@ -2755,33 +2756,6 @@ class ActivityStreamAccess(BaseAccess):
return False
class CustomInventoryScriptAccess(BaseAccess):
model = CustomInventoryScript
prefetch_related = ('created_by', 'modified_by', 'organization')
def filtered_queryset(self):
return self.model.accessible_objects(self.user, 'read_role').all()
@check_superuser
def can_add(self, data):
if not data: # So the browseable API will work
return Organization.accessible_objects(self.user, 'admin_role').exists()
return self.check_related('organization', Organization, data, mandatory=True)
@check_superuser
def can_admin(self, obj, data=None):
return self.check_related('organization', Organization, data, obj=obj) and self.user in obj.admin_role
@check_superuser
def can_change(self, obj, data):
return self.can_admin(obj, data=data)
@check_superuser
def can_delete(self, obj):
return self.can_admin(obj)
class RoleAccess(BaseAccess):
"""
- I can see roles when
@@ -2927,3 +2901,4 @@ class WorkflowApprovalTemplateAccess(BaseAccess):
for cls in BaseAccess.__subclasses__():
access_registry[cls.model] = cls
access_registry[UnpartitionedJobEvent] = UnpartitionedJobEventAccess

View File

@@ -6,7 +6,7 @@ import platform
import distro
from django.db import connection
from django.db.models import Count, Max, Min
from django.db.models import Count
from django.conf import settings
from django.contrib.sessions.models import Session
from django.utils.timezone import now, timedelta
@@ -15,7 +15,7 @@ from django.utils.translation import ugettext_lazy as _
from psycopg2.errors import UntranslatableCharacter
from awx.conf.license import get_license
from awx.main.utils import get_awx_version, get_custom_venv_choices, camelcase_to_underscore, datetime_hook
from awx.main.utils import get_awx_version, camelcase_to_underscore, datetime_hook
from awx.main import models
from awx.main.analytics import register
@@ -36,7 +36,7 @@ data _since_ the last report date - i.e., new data in the last 24 hours)
"""
def trivial_slicing(key, since, until):
def trivial_slicing(key, since, until, last_gather):
if since is not None:
return [(since, until)]
@@ -45,11 +45,11 @@ def trivial_slicing(key, since, until):
horizon = until - timedelta(weeks=4)
last_entries = Setting.objects.filter(key='AUTOMATION_ANALYTICS_LAST_ENTRIES').first()
last_entries = json.loads((last_entries.value if last_entries is not None else '') or '{}', object_hook=datetime_hook)
last_entry = max(last_entries.get(key) or settings.AUTOMATION_ANALYTICS_LAST_GATHER or horizon, horizon)
last_entry = max(last_entries.get(key) or last_gather, horizon)
return [(last_entry, until)]
def four_hour_slicing(key, since, until):
def four_hour_slicing(key, since, until, last_gather):
if since is not None:
last_entry = since
else:
@@ -58,7 +58,10 @@ def four_hour_slicing(key, since, until):
horizon = until - timedelta(weeks=4)
last_entries = Setting.objects.filter(key='AUTOMATION_ANALYTICS_LAST_ENTRIES').first()
last_entries = json.loads((last_entries.value if last_entries is not None else '') or '{}', object_hook=datetime_hook)
last_entry = max(last_entries.get(key) or settings.AUTOMATION_ANALYTICS_LAST_GATHER or horizon, horizon)
try:
last_entry = max(last_entries.get(key) or last_gather, horizon)
except TypeError: # last_entries has a stale non-datetime entry for this collector
last_entry = max(last_gather, horizon)
start, end = last_entry, None
while start < until:
@@ -67,27 +70,18 @@ def four_hour_slicing(key, since, until):
start = end
def events_slicing(key, since, until):
def _identify_lower(key, since, until, last_gather):
from awx.conf.models import Setting
last_gather = settings.AUTOMATION_ANALYTICS_LAST_GATHER
last_entries = Setting.objects.filter(key='AUTOMATION_ANALYTICS_LAST_ENTRIES').first()
last_entries = json.loads((last_entries.value if last_entries is not None else '') or '{}', object_hook=datetime_hook)
horizon = until - timedelta(weeks=4)
lower = since or last_gather or horizon
lower = since or last_gather
if not since and last_entries.get(key):
lower = horizon
pk_values = models.JobEvent.objects.filter(created__gte=lower, created__lte=until).aggregate(Min('pk'), Max('pk'))
previous_pk = pk_values['pk__min'] - 1 if pk_values['pk__min'] is not None else 0
if not since and last_entries.get(key):
previous_pk = max(last_entries[key], previous_pk)
final_pk = pk_values['pk__max'] or 0
step = 100000
for start in range(previous_pk, final_pk + 1, step):
yield (start, min(start + step, final_pk))
return lower, last_entries
@register('config', '1.3', description=_('General platform configuration.'))
@@ -121,7 +115,7 @@ def config(since, **kwargs):
}
@register('counts', '1.0', description=_('Counts of objects such as organizations, inventories, and projects'))
@register('counts', '1.1', description=_('Counts of objects such as organizations, inventories, and projects'))
def counts(since, **kwargs):
counts = {}
for cls in (
@@ -135,14 +129,10 @@ def counts(since, **kwargs):
models.WorkflowJobTemplate,
models.Host,
models.Schedule,
models.CustomInventoryScript,
models.NotificationTemplate,
):
counts[camelcase_to_underscore(cls.__name__)] = cls.objects.count()
venvs = get_custom_venv_choices()
counts['custom_virtualenvs'] = len([v for v in venvs if os.path.basename(v.rstrip('/')) != 'ansible'])
inv_counts = dict(models.Inventory.objects.order_by().values_list('kind').annotate(Count('kind')))
inv_counts['normal'] = inv_counts.get('', 0)
inv_counts.pop('', None)
@@ -185,12 +175,12 @@ def org_counts(since, **kwargs):
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'
'name', 'id', 'managed', 'num_credentials'
):
counts[cred_type['id']] = {
'name': cred_type['name'],
'credential_count': cred_type['num_credentials'],
'managed_by_tower': cred_type['managed_by_tower'],
'managed': cred_type['managed'],
}
return counts
@@ -221,17 +211,11 @@ def projects_by_scm_type(since, **kwargs):
return counts
def _get_isolated_datetime(last_check):
if last_check:
return last_check.isoformat()
return last_check
@register('instance_info', '1.0', description=_('Cluster topology and capacity'))
@register('instance_info', '1.1', 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'
'uuid', 'version', 'capacity', 'cpu', 'memory', 'managed_by_policy', 'hostname', 'enabled'
)
for instance in instances:
consumed_capacity = sum(x.task_impact for x in models.UnifiedJob.objects.filter(execution_node=instance['hostname'], status__in=('running', 'waiting')))
@@ -242,7 +226,6 @@ def instance_info(since, include_hostnames=False, **kwargs):
'cpu': instance['cpu'],
'memory': instance['memory'],
'managed_by_policy': instance['managed_by_policy'],
'last_isolated_check': _get_isolated_datetime(instance['last_isolated_check']),
'enabled': instance['enabled'],
'consumed_capacity': consumed_capacity,
'remaining_capacity': instance['capacity'] - consumed_capacity,
@@ -344,39 +327,49 @@ def _copy_table(table, query, path):
return file.file_list()
@register('events_table', '1.2', format='csv', description=_('Automation task records'), expensive=events_slicing)
def events_table(since, full_path, until, **kwargs):
def _events_table(since, full_path, until, tbl, where_column, project_job_created=False, **kwargs):
def query(event_data):
return f'''COPY (SELECT main_jobevent.id,
main_jobevent.created,
main_jobevent.modified,
main_jobevent.uuid,
main_jobevent.parent_uuid,
main_jobevent.event,
{event_data}->'task_action' AS task_action,
(CASE WHEN event = 'playbook_on_stats' THEN event_data END) as playbook_on_stats,
main_jobevent.failed,
main_jobevent.changed,
main_jobevent.playbook,
main_jobevent.play,
main_jobevent.task,
main_jobevent.role,
main_jobevent.job_id,
main_jobevent.host_id,
main_jobevent.host_name,
CAST({event_data}->>'start' AS TIMESTAMP WITH TIME ZONE) AS start,
CAST({event_data}->>'end' AS TIMESTAMP WITH TIME ZONE) AS end,
{event_data}->'duration' AS duration,
{event_data}->'res'->'warnings' AS warnings,
{event_data}->'res'->'deprecations' AS deprecations
FROM main_jobevent
WHERE (main_jobevent.id > {since} AND main_jobevent.id <= {until})
ORDER BY main_jobevent.id ASC) TO STDOUT WITH CSV HEADER'''
query = f'''COPY (SELECT {tbl}.id,
{tbl}.created,
{tbl}.modified,
{tbl + '.job_created' if project_job_created else 'NULL'} as job_created,
{tbl}.uuid,
{tbl}.parent_uuid,
{tbl}.event,
task_action,
(CASE WHEN event = 'playbook_on_stats' THEN event_data END) as playbook_on_stats,
{tbl}.failed,
{tbl}.changed,
{tbl}.playbook,
{tbl}.play,
{tbl}.task,
{tbl}.role,
{tbl}.job_id,
{tbl}.host_id,
{tbl}.host_name,
CAST(x.start AS TIMESTAMP WITH TIME ZONE) AS start,
CAST(x.end AS TIMESTAMP WITH TIME ZONE) AS end,
x.duration AS duration,
x.res->'warnings' AS warnings,
x.res->'deprecations' AS deprecations
FROM {tbl}, json_to_record({event_data}) AS x("res" json, "duration" text, "task_action" text, "start" text, "end" text)
WHERE ({tbl}.{where_column} > '{since.isoformat()}' AND {tbl}.{where_column} <= '{until.isoformat()}')) TO STDOUT WITH CSV HEADER'''
return query
try:
return _copy_table(table='events', query=query("main_jobevent.event_data::json"), path=full_path)
except UntranslatableCharacter as exc:
return _copy_table(table='events', query=query("replace(main_jobevent.event_data::text, '\\u0000', '')::json"), path=full_path)
return _copy_table(table='events', query=query(f"{tbl}.event_data::json"), path=full_path)
except UntranslatableCharacter:
return _copy_table(table='events', query=query(f"replace({tbl}.event_data::text, '\\u0000', '')::json"), path=full_path)
@register('events_table', '1.3', format='csv', description=_('Automation task records'), expensive=four_hour_slicing)
def events_table_unpartitioned(since, full_path, until, **kwargs):
return _events_table(since, full_path, until, '_unpartitioned_main_jobevent', 'created', **kwargs)
@register('events_table', '1.3', format='csv', description=_('Automation task records'), expensive=four_hour_slicing)
def events_table_partitioned_modified(since, full_path, until, **kwargs):
return _events_table(since, full_path, until, 'main_jobevent', 'modified', project_job_created=True, **kwargs)
@register('unified_jobs_table', '1.2', format='csv', description=_('Data on jobs run'), expensive=four_hour_slicing)
@@ -386,22 +379,22 @@ def unified_jobs_table(since, full_path, until, **kwargs):
django_content_type.model,
main_unifiedjob.organization_id,
main_organization.name as organization_name,
main_job.inventory_id,
main_job.inventory_id,
main_inventory.name as inventory_name,
main_unifiedjob.created,
main_unifiedjob.name,
main_unifiedjob.unified_job_template_id,
main_unifiedjob.launch_type,
main_unifiedjob.schedule_id,
main_unifiedjob.execution_node,
main_unifiedjob.controller_node,
main_unifiedjob.cancel_flag,
main_unifiedjob.status,
main_unifiedjob.failed,
main_unifiedjob.started,
main_unifiedjob.finished,
main_unifiedjob.elapsed,
main_unifiedjob.job_explanation,
main_unifiedjob.created,
main_unifiedjob.name,
main_unifiedjob.unified_job_template_id,
main_unifiedjob.launch_type,
main_unifiedjob.schedule_id,
main_unifiedjob.execution_node,
main_unifiedjob.controller_node,
main_unifiedjob.cancel_flag,
main_unifiedjob.status,
main_unifiedjob.failed,
main_unifiedjob.started,
main_unifiedjob.finished,
main_unifiedjob.elapsed,
main_unifiedjob.job_explanation,
main_unifiedjob.instance_group_id,
main_unifiedjob.installed_collections,
main_unifiedjob.ansible_version
@@ -422,21 +415,21 @@ def unified_jobs_table(since, full_path, until, **kwargs):
@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,
unified_job_template_query = '''COPY (SELECT main_unifiedjobtemplate.id,
main_unifiedjobtemplate.polymorphic_ctype_id,
django_content_type.model,
main_unifiedjobtemplate.created,
main_unifiedjobtemplate.modified,
main_unifiedjobtemplate.created_by_id,
main_unifiedjobtemplate.modified_by_id,
main_unifiedjobtemplate.name,
main_unifiedjobtemplate.current_job_id,
main_unifiedjobtemplate.last_job_id,
main_unifiedjobtemplate.last_job_failed,
main_unifiedjobtemplate.last_job_run,
main_unifiedjobtemplate.next_job_run,
main_unifiedjobtemplate.next_schedule_id,
main_unifiedjobtemplate.status
main_unifiedjobtemplate.created,
main_unifiedjobtemplate.modified,
main_unifiedjobtemplate.created_by_id,
main_unifiedjobtemplate.modified_by_id,
main_unifiedjobtemplate.name,
main_unifiedjobtemplate.current_job_id,
main_unifiedjobtemplate.last_job_id,
main_unifiedjobtemplate.last_job_failed,
main_unifiedjobtemplate.last_job_run,
main_unifiedjobtemplate.next_job_run,
main_unifiedjobtemplate.next_schedule_id,
main_unifiedjobtemplate.status
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'''
@@ -447,15 +440,15 @@ def unified_job_template_table(since, full_path, **kwargs):
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,
main_workflowjobnode.job_id,
main_workflowjobnode.unified_job_template_id,
main_workflowjobnode.workflow_job_id,
main_workflowjobnode.inventory_id,
main_workflowjobnode.modified,
main_workflowjobnode.job_id,
main_workflowjobnode.unified_job_template_id,
main_workflowjobnode.workflow_job_id,
main_workflowjobnode.inventory_id,
success_nodes.nodes AS success_nodes,
failure_nodes.nodes AS failure_nodes,
always_nodes.nodes AS always_nodes,
main_workflowjobnode.do_not_run,
main_workflowjobnode.do_not_run,
main_workflowjobnode.all_parents_must_converge
FROM main_workflowjobnode
LEFT JOIN (
@@ -483,12 +476,12 @@ def workflow_job_node_table(since, full_path, until, **kwargs):
@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,
workflow_job_template_node_query = '''COPY (SELECT main_workflowjobtemplatenode.id,
main_workflowjobtemplatenode.created,
main_workflowjobtemplatenode.modified,
main_workflowjobtemplatenode.unified_job_template_id,
main_workflowjobtemplatenode.workflow_job_template_id,
main_workflowjobtemplatenode.inventory_id,
main_workflowjobtemplatenode.modified,
main_workflowjobtemplatenode.unified_job_template_id,
main_workflowjobtemplatenode.workflow_job_template_id,
main_workflowjobtemplatenode.inventory_id,
success_nodes.nodes AS success_nodes,
failure_nodes.nodes AS failure_nodes,
always_nodes.nodes AS always_nodes,

View File

@@ -116,6 +116,51 @@ def package(target, data, timestamp):
return None
def calculate_collection_interval(since, until):
_now = now()
# Make sure that the endpoints are not in the future.
if until is not None and until > _now:
until = _now
logger.warning(f"End of the collection interval is in the future, setting to {_now}.")
if since is not None and since > _now:
since = _now
logger.warning(f"Start of the collection interval is in the future, setting to {_now}.")
# The value of `until` needs to be concrete, so resolve it. If it wasn't passed in,
# set it to `now`, but only if that isn't more than 4 weeks ahead of a passed-in
# `since` parameter.
if since is not None:
if until is not None:
if until > since + timedelta(weeks=4):
until = since + timedelta(weeks=4)
logger.warning(f"End of the collection interval is greater than 4 weeks from start, setting end to {until}.")
else: # until is None
until = min(since + timedelta(weeks=4), _now)
elif until is None:
until = _now
if since and since >= until:
logger.warning("Start of the collection interval is later than the end, ignoring request.")
raise ValueError
# The ultimate beginning of the interval needs to be compared to 4 weeks prior to
# `until`, but we want to keep `since` empty if it wasn't passed in because we use that
# case to know whether to use the bookkeeping settings variables to decide the start of
# the interval.
horizon = until - timedelta(weeks=4)
if since is not None and since < horizon:
since = horizon
logger.warning(f"Start of the collection interval is more than 4 weeks prior to {until}, setting to {horizon}.")
last_gather = settings.AUTOMATION_ANALYTICS_LAST_GATHER or horizon
if last_gather < horizon:
last_gather = horizon
logger.warning(f"Last analytics run was more than 4 weeks prior to {until}, using {horizon} instead.")
return since, until, last_gather
def gather(dest=None, module=None, subset=None, since=None, until=None, collection_type='scheduled'):
"""
Gather all defined metrics and write them as JSON files in a .tgz
@@ -132,7 +177,7 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti
if collection_type != 'dry-run':
if not settings.INSIGHTS_TRACKING_STATE:
logger.log(log_level, "Automation Analytics not enabled. Use --dry-run to gather locally without sending.")
logger.log(log_level, "Insights for Ansible Automation Platform not enabled. Use --dry-run to gather locally without sending.")
return None
if not (settings.AUTOMATION_ANALYTICS_URL and settings.REDHAT_USERNAME and settings.REDHAT_PASSWORD):
@@ -148,30 +193,12 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti
from awx.main.analytics import collectors
from awx.main.signals import disable_activity_stream
_now = now()
# Make sure that the endpoints are not in the future.
until = None if until is None else min(until, _now)
since = None if since is None else min(since, _now)
if since and not until:
# If `since` is explicit but not `until`, `since` should be used to calculate the 4-week limit
until = min(since + timedelta(weeks=4), _now)
else:
until = _now if until is None else until
horizon = until - timedelta(weeks=4)
if since is not None:
# Make sure the start isn't more than 4 weeks prior to `until`.
since = max(since, horizon)
if since and since >= until:
logger.warning("Start of the collection interval is later than the end, ignoring request.")
return None
logger.debug("Last analytics run was: {}".format(settings.AUTOMATION_ANALYTICS_LAST_GATHER))
# LAST_GATHER time should always get truncated to less than 4 weeks back.
last_gather = max(settings.AUTOMATION_ANALYTICS_LAST_GATHER or horizon, horizon)
try:
since, until, last_gather = calculate_collection_interval(since, until)
except ValueError:
return None
last_entries = Setting.objects.filter(key='AUTOMATION_ANALYTICS_LAST_ENTRIES').first()
last_entries = json.loads((last_entries.value if last_entries is not None else '') or '{}', object_hook=datetime_hook)
@@ -201,7 +228,7 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti
key = func.__awx_analytics_key__
filename = f'{key}.json'
try:
last_entry = max(last_entries.get(key) or last_gather, horizon)
last_entry = max(last_entries.get(key) or last_gather, until - timedelta(weeks=4))
results = (func(since or last_entry, collection_type=collection_type, until=until), func.__awx_analytics_version__)
json.dumps(results) # throwaway check to see if the data is json-serializable
data[filename] = results
@@ -233,9 +260,9 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti
# allowed to be None, and will fall back to LAST_ENTRIES[key] or to
# LAST_GATHER (truncated appropriately to match the 4-week limit).
if func.__awx_expensive__:
slices = func.__awx_expensive__(key, since, until)
slices = func.__awx_expensive__(key, since, until, last_gather)
else:
slices = collectors.trivial_slicing(key, since, until)
slices = collectors.trivial_slicing(key, since, until, last_gather)
for start, end in slices:
files = func(start, full_path=gather_dir, until=end)
@@ -243,7 +270,8 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti
if not files:
if collection_type != 'dry-run':
with disable_activity_stream():
last_entries[key] = max(last_entries[key], end) if last_entries.get(key) else end
entry = last_entries.get(key)
last_entries[key] = max(entry, end) if entry and type(entry) == type(end) else end
settings.AUTOMATION_ANALYTICS_LAST_ENTRIES = json.dumps(last_entries, cls=DjangoJSONEncoder)
continue
@@ -259,13 +287,15 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti
tgzfile = package(dest.parent, payload, until)
if tgzfile is not None:
tarfiles.append(tgzfile)
if not ship(tgzfile):
slice_succeeded, succeeded = False, False
break
if collection_type != 'dry-run':
if not ship(tgzfile):
slice_succeeded, succeeded = False, False
break
if slice_succeeded and collection_type != 'dry-run':
with disable_activity_stream():
last_entries[key] = max(last_entries[key], end) if last_entries.get(key) else end
entry = last_entries.get(key)
last_entries[key] = max(entry, end) if entry and type(entry) == type(end) else end
settings.AUTOMATION_ANALYTICS_LAST_ENTRIES = json.dumps(last_entries, cls=DjangoJSONEncoder)
except Exception:
succeeded = False
@@ -278,6 +308,14 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti
os.remove(fpath)
with disable_activity_stream():
if not settings.AUTOMATION_ANALYTICS_LAST_GATHER or until > settings.AUTOMATION_ANALYTICS_LAST_GATHER:
# `AUTOMATION_ANALYTICS_LAST_GATHER` is set whether collection succeeds or fails;
# if collection fails because of a persistent, underlying issue and we do not set last_gather,
# we risk the collectors hitting an increasingly greater workload while the underlying issue
# remains unresolved. Put simply, if collection fails, we just move on.
# All that said, `AUTOMATION_ANALYTICS_LAST_GATHER` plays a much smaller role in determining
# what is actually collected than it used to; collectors now mostly rely on their respective entry
# under `last_entries` to determine what should be collected.
settings.AUTOMATION_ANALYTICS_LAST_GATHER = until
shutil.rmtree(dest, ignore_errors=True) # clean up individual artifact files
@@ -294,10 +332,10 @@ def ship(path):
Ship gathered metrics to the Insights API
"""
if not path:
logger.error('Automation Analytics TAR not found')
logger.error('Insights for Ansible Automation Platform TAR not found')
return False
if not os.path.exists(path):
logger.error('Automation Analytics TAR {} not found'.format(path))
logger.error('Insights for Ansible Automation Platform TAR {} not found'.format(path))
return False
if "Error:" in str(path):
return False

View File

@@ -1,5 +1,5 @@
from django.conf import settings
from prometheus_client import PROCESS_COLLECTOR, PLATFORM_COLLECTOR, GC_COLLECTOR, CollectorRegistry, Gauge, Info, generate_latest
from prometheus_client import CollectorRegistry, Gauge, Info, generate_latest
from awx.conf.license import get_license
from awx.main.utils import get_awx_version
@@ -31,7 +31,6 @@ def metrics():
registry=REGISTRY,
)
SCHEDULE_COUNT = Gauge('awx_schedules_total', 'Number of schedules', registry=REGISTRY)
INV_SCRIPT_COUNT = Gauge('awx_inventory_scripts_total', 'Number of invetory scripts', registry=REGISTRY)
USER_SESSIONS = Gauge(
'awx_sessions_total',
'Number of sessions',
@@ -40,9 +39,8 @@ def metrics():
],
registry=REGISTRY,
)
CUSTOM_VENVS = Gauge('awx_custom_virtualenvs_total', 'Number of virtualenvs', registry=REGISTRY)
RUNNING_JOBS = Gauge('awx_running_jobs_total', 'Number of running jobs on the Tower system', registry=REGISTRY)
PENDING_JOBS = Gauge('awx_pending_jobs_total', 'Number of pending jobs on the Tower system', registry=REGISTRY)
RUNNING_JOBS = Gauge('awx_running_jobs_total', 'Number of running jobs on the system', registry=REGISTRY)
PENDING_JOBS = Gauge('awx_pending_jobs_total', 'Number of pending jobs on the system', registry=REGISTRY)
STATUS = Gauge(
'awx_status_total',
'Status of Job launched',
@@ -54,7 +52,7 @@ def metrics():
INSTANCE_CAPACITY = Gauge(
'awx_instance_capacity',
'Capacity of each node in a Tower system',
'Capacity of each node in the system',
[
'hostname',
'instance_uuid',
@@ -63,7 +61,7 @@ def metrics():
)
INSTANCE_CPU = Gauge(
'awx_instance_cpu',
'CPU cores on each node in a Tower system',
'CPU cores on each node in the system',
[
'hostname',
'instance_uuid',
@@ -72,7 +70,7 @@ def metrics():
)
INSTANCE_MEMORY = Gauge(
'awx_instance_memory',
'RAM (Kb) on each node in a Tower system',
'RAM (Kb) on each node in the system',
[
'hostname',
'instance_uuid',
@@ -81,7 +79,7 @@ def metrics():
)
INSTANCE_INFO = Info(
'awx_instance',
'Info about each node in a Tower system',
'Info about each node in the system',
[
'hostname',
'instance_uuid',
@@ -108,7 +106,7 @@ def metrics():
)
INSTANCE_CONSUMED_CAPACITY = Gauge(
'awx_instance_consumed_capacity',
'Consumed capacity of each node in a Tower system',
'Consumed capacity of each node in the system',
[
'hostname',
'instance_uuid',
@@ -117,7 +115,7 @@ def metrics():
)
INSTANCE_REMAINING_CAPACITY = Gauge(
'awx_instance_remaining_capacity',
'Remaining capacity of each node in a Tower system',
'Remaining capacity of each node in the system',
[
'hostname',
'instance_uuid',
@@ -160,8 +158,6 @@ def metrics():
HOST_COUNT.labels(type='active').set(current_counts['active_host_count'])
SCHEDULE_COUNT.set(current_counts['schedule'])
INV_SCRIPT_COUNT.set(current_counts['custom_inventory_script'])
CUSTOM_VENVS.set(current_counts['custom_virtualenvs'])
USER_SESSIONS.labels(type='all').set(current_counts['active_sessions'])
USER_SESSIONS.labels(type='user').set(current_counts['active_user_sessions'])
@@ -186,7 +182,6 @@ def metrics():
INSTANCE_INFO.labels(hostname=hostname, instance_uuid=uuid).info(
{
'enabled': str(instance_data[uuid]['enabled']),
'last_isolated_check': getattr(instance_data[uuid], 'last_isolated_check', 'None'),
'managed_by_policy': str(instance_data[uuid]['managed_by_policy']),
'version': instance_data[uuid]['version'],
}

14
awx/main/backends.py Normal file
View File

@@ -0,0 +1,14 @@
import logging
from django.conf import settings
from django.contrib.auth.backends import ModelBackend
logger = logging.getLogger('awx.main.backends')
class AWXModelBackend(ModelBackend):
def authenticate(self, request, **kwargs):
if settings.DISABLE_LOCAL_AUTH:
logger.warning(f"User '{kwargs['username']}' attempted login through the disabled local authentication system.")
return
return super().authenticate(request, **kwargs)

View File

@@ -6,9 +6,8 @@ from django.utils.translation import ugettext_lazy as _
# Django REST Framework
from rest_framework import serializers
from rest_framework.fields import FloatField
# Tower
# AWX
from awx.conf import fields, register, register_validate
from awx.main.models import ExecutionEnvironment
@@ -37,7 +36,7 @@ register(
'ORG_ADMINS_CAN_SEE_ALL_USERS',
field_class=fields.BooleanField,
label=_('All Users Visible to Organization Admins'),
help_text=_('Controls whether any Organization Admin can view all users and teams, ' 'even those not associated with their Organization.'),
help_text=_('Controls whether any Organization Admin can view all users and teams, even those not associated with their Organization.'),
category=_('System'),
category_slug='system',
)
@@ -59,8 +58,8 @@ register(
field_class=fields.URLField,
schemes=('http', 'https'),
allow_plain_hostname=True, # Allow hostname only without TLD.
label=_('Base URL of the Tower host'),
help_text=_('This setting is used by services like notifications to render ' 'a valid url to the Tower host.'),
label=_('Base URL of the service'),
help_text=_('This setting is used by services like notifications to render a valid url to the service.'),
category=_('System'),
category_slug='system',
)
@@ -85,8 +84,8 @@ register(
field_class=fields.StringListField,
label=_('Proxy IP Allowed List'),
help_text=_(
"If Tower is behind a reverse proxy/load balancer, use this setting "
"to configure the proxy IP addresses from which Tower should trust "
"If the service is behind a reverse proxy/load balancer, use this setting "
"to configure the proxy IP addresses from which the service 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')"
@@ -95,13 +94,12 @@ register(
category_slug='system',
)
register(
'LICENSE',
field_class=fields.DictField,
default=lambda: {},
label=_('License'),
help_text=_('The license controls which features and functionality are ' 'enabled. Use /api/v2/config/ to update or change ' 'the license.'),
help_text=_('The license controls which features and functionality are enabled. Use /api/v2/config/ to update or change the license.'),
category=_('System'),
category_slug='system',
)
@@ -114,7 +112,7 @@ register(
encrypted=False,
read_only=False,
label=_('Red Hat customer username'),
help_text=_('This username is used to send data to Automation Analytics'),
help_text=_('This username is used to send data to Insights for Ansible Automation Platform'),
category=_('System'),
category_slug='system',
)
@@ -127,7 +125,7 @@ register(
encrypted=True,
read_only=False,
label=_('Red Hat customer password'),
help_text=_('This password is used to send data to Automation Analytics'),
help_text=_('This password is used to send data to Insights for Ansible Automation Platform'),
category=_('System'),
category_slug='system',
)
@@ -164,8 +162,8 @@ register(
default='https://example.com',
schemes=('http', 'https'),
allow_plain_hostname=True, # Allow hostname only without TLD.
label=_('Automation Analytics upload URL'),
help_text=_('This setting is used to to configure data collection for the Automation Analytics dashboard'),
label=_('Insights for Ansible Automation Platform upload URL'),
help_text=_('This setting is used to to configure the upload URL for data collection for Red Hat Insights.'),
category=_('System'),
category_slug='system',
)
@@ -173,7 +171,25 @@ register(
register(
'INSTALL_UUID',
field_class=fields.CharField,
label=_('Unique identifier for an AWX/Tower installation'),
label=_('Unique identifier for an installation'),
category=_('System'),
category_slug='system',
read_only=True,
)
register(
'DEFAULT_CONTROL_PLANE_QUEUE_NAME',
field_class=fields.CharField,
label=_('The instance group where control plane tasks run'),
category=_('System'),
category_slug='system',
read_only=True,
)
register(
'DEFAULT_EXECUTION_QUEUE_NAME',
field_class=fields.CharField,
label=_('The instance group where user jobs run (currently only on non-VM installs)'),
category=_('System'),
category_slug='system',
read_only=True,
@@ -195,7 +211,7 @@ register(
'CUSTOM_VENV_PATHS',
field_class=fields.StringListPathField,
label=_('Custom virtual environment paths'),
help_text=_('Paths where Tower will look for custom virtual environments ' '(in addition to /var/lib/awx/venv/). Enter one path per line.'),
help_text=_('Paths where Tower will look for custom virtual environments (in addition to /var/lib/awx/venv/). Enter one path per line.'),
category=_('System'),
category_slug='system',
default=[],
@@ -224,7 +240,7 @@ register(
help_text=_(
'Ansible allows variable substitution via the Jinja2 templating '
'language for --extra-vars. This poses a potential security '
'risk where Tower users with the ability to specify extra vars at job '
'risk where users with the ability to specify extra vars at job '
'launch time can use Jinja2 templates to run arbitrary Python. It is '
'recommended that this value be set to "template" or "never".'
),
@@ -236,11 +252,7 @@ register(
'AWX_ISOLATION_BASE_PATH',
field_class=fields.CharField,
label=_('Job execution path'),
help_text=_(
'The directory in which Tower will create new temporary '
'directories for job execution and isolation '
'(such as credential files and custom inventory scripts).'
),
help_text=_('The directory in which the service will create new temporary directories for job execution and isolation (such as credential files).'),
category=_('Jobs'),
category_slug='jobs',
)
@@ -255,138 +267,6 @@ register(
category_slug='jobs',
)
register(
'AWX_ISOLATED_CHECK_INTERVAL',
field_class=fields.IntegerField,
min_value=0,
label=_('Isolated status check interval'),
help_text=_('The number of seconds to sleep between status checks for jobs running on isolated instances.'),
category=_('Jobs'),
category_slug='jobs',
unit=_('seconds'),
)
register(
'AWX_ISOLATED_LAUNCH_TIMEOUT',
field_class=fields.IntegerField,
min_value=0,
label=_('Isolated launch timeout'),
help_text=_(
'The timeout (in seconds) for launching jobs on isolated instances. '
'This includes the time needed to copy source control files (playbooks) to the isolated instance.'
),
category=_('Jobs'),
category_slug='jobs',
unit=_('seconds'),
)
register(
'AWX_ISOLATED_CONNECTION_TIMEOUT',
field_class=fields.IntegerField,
min_value=0,
default=10,
label=_('Isolated connection timeout'),
help_text=_(
'Ansible SSH connection timeout (in seconds) to use when communicating with isolated instances. '
'Value should be substantially greater than expected network latency.'
),
category=_('Jobs'),
category_slug='jobs',
unit=_('seconds'),
)
register(
'AWX_ISOLATED_HOST_KEY_CHECKING',
field_class=fields.BooleanField,
label=_('Isolated host key checking'),
help_text=_('When set to True, AWX will enforce strict host key checking for communication with isolated nodes.'),
category=_('Jobs'),
category_slug='jobs',
default=False,
)
register(
'AWX_ISOLATED_KEY_GENERATION',
field_class=fields.BooleanField,
default=True,
label=_('Generate RSA keys for isolated instances'),
help_text=_(
'If set, a random RSA key will be generated and distributed to '
'isolated instances. To disable this behavior and manage authentication '
'for isolated instances outside of Tower, disable this setting.'
), # noqa
category=_('Jobs'),
category_slug='jobs',
)
register(
'AWX_ISOLATED_PRIVATE_KEY',
field_class=fields.CharField,
default='',
allow_blank=True,
encrypted=True,
read_only=True,
label=_('The RSA private key for SSH traffic to isolated instances'),
help_text=_('The RSA private key for SSH traffic to isolated instances'), # noqa
category=_('Jobs'),
category_slug='jobs',
)
register(
'AWX_ISOLATED_PUBLIC_KEY',
field_class=fields.CharField,
default='',
allow_blank=True,
read_only=True,
label=_('The RSA public key for SSH traffic to isolated instances'),
help_text=_('The RSA public key for SSH traffic to isolated instances'), # noqa
category=_('Jobs'),
category_slug='jobs',
)
register(
'AWX_RESOURCE_PROFILING_ENABLED',
field_class=fields.BooleanField,
default=False,
label=_('Enable detailed resource profiling on all playbook runs'),
help_text=_('If set, detailed resource profiling data will be collected on all jobs. ' 'This data can be gathered with `sosreport`.'), # noqa
category=_('Jobs'),
category_slug='jobs',
)
register(
'AWX_RESOURCE_PROFILING_CPU_POLL_INTERVAL',
field_class=FloatField,
default='0.25',
label=_('Interval (in seconds) between polls for cpu usage.'),
help_text=_('Interval (in seconds) between polls for cpu usage. ' 'Setting this lower than the default will affect playbook performance.'),
category=_('Jobs'),
category_slug='jobs',
required=False,
)
register(
'AWX_RESOURCE_PROFILING_MEMORY_POLL_INTERVAL',
field_class=FloatField,
default='0.25',
label=_('Interval (in seconds) between polls for memory usage.'),
help_text=_('Interval (in seconds) between polls for memory usage. ' 'Setting this lower than the default will affect playbook performance.'),
category=_('Jobs'),
category_slug='jobs',
required=False,
)
register(
'AWX_RESOURCE_PROFILING_PID_POLL_INTERVAL',
field_class=FloatField,
default='0.25',
label=_('Interval (in seconds) between polls for PID count.'),
help_text=_('Interval (in seconds) between polls for PID count. ' 'Setting this lower than the default will affect playbook performance.'),
category=_('Jobs'),
category_slug='jobs',
required=False,
)
register(
'AWX_TASK_ENV',
field_class=fields.KeyValueField,
@@ -402,8 +282,8 @@ register(
'INSIGHTS_TRACKING_STATE',
field_class=fields.BooleanField,
default=False,
label=_('Gather data for Automation Analytics'),
help_text=_('Enables Tower to gather data on automation and send it to Red Hat.'),
label=_('Gather data for Insights for Ansible Automation Platform'),
help_text=_('Enables the service to gather data on automation and send it to Red Hat Insights.'),
category=_('System'),
category_slug='system',
)
@@ -455,7 +335,7 @@ register(
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 ' 'installing content from any Galaxy server.'),
help_text=_('If set to true, certificate validation will not be done when installing content from any Galaxy server.'),
category=_('Jobs'),
category_slug='jobs',
)
@@ -482,6 +362,17 @@ register(
category_slug='jobs',
)
register(
'MAX_WEBSOCKET_EVENT_RATE',
field_class=fields.IntegerField,
min_value=0,
default=30,
label=_('Job Event Maximum Websocket Messages Per Second'),
help_text=_('Maximum number of messages to update the UI live job output with per second. Value of 0 means no limit.'),
category=_('Jobs'),
category_slug='jobs',
)
register(
'SCHEDULE_MAX_JOBS',
field_class=fields.IntegerField,
@@ -570,7 +461,7 @@ register(
allow_null=False,
default=200,
label=_('Maximum number of forks per job'),
help_text=_('Saving a Job Template with more than this number of forks will result in an error. ' 'When set to 0, no limit is applied.'),
help_text=_('Saving a Job Template with more than this number of forks will result in an error. When set to 0, no limit is applied.'),
category=_('Jobs'),
category_slug='jobs',
)
@@ -591,7 +482,7 @@ register(
allow_null=True,
default=None,
label=_('Logging Aggregator Port'),
help_text=_('Port on Logging Aggregator to send logs to (if required and not' ' provided in Logging Aggregator).'),
help_text=_('Port on Logging Aggregator to send logs to (if required and not provided in Logging Aggregator).'),
category=_('Logging'),
category_slug='logging',
required=False,
@@ -674,8 +565,8 @@ register(
field_class=fields.CharField,
allow_blank=True,
default='',
label=_('Cluster-wide Tower unique identifier.'),
help_text=_('Useful to uniquely identify Tower instances.'),
label=_('Cluster-wide unique identifier.'),
help_text=_('Useful to uniquely identify instances.'),
category=_('Logging'),
category_slug='logging',
)
@@ -698,7 +589,7 @@ register(
field_class=fields.IntegerField,
default=5,
label=_('TCP Connection Timeout'),
help_text=_('Number of seconds for a TCP connection to external log ' 'aggregator to timeout. Applies to HTTPS and TCP log ' 'aggregator protocols.'),
help_text=_('Number of seconds for a TCP connection to external log aggregator to timeout. Applies to HTTPS and TCP log aggregator protocols.'),
category=_('Logging'),
category_slug='logging',
unit=_('seconds'),
@@ -710,7 +601,7 @@ register(
label=_('Enable/disable HTTPS certificate verification'),
help_text=_(
'Flag to control enable/disable of certificate verification'
' when LOG_AGGREGATOR_PROTOCOL is "https". If enabled, Tower\'s'
' when LOG_AGGREGATOR_PROTOCOL is "https". If enabled, the'
' log handler will verify certificate sent by external log aggregator'
' before establishing connection.'
),
@@ -764,7 +655,7 @@ register(
field_class=fields.BooleanField,
default=False,
label=_('Enable rsyslogd debugging'),
help_text=_('Enabled high verbosity debugging for rsyslogd. ' 'Useful for debugging connection issues for external log aggregation.'),
help_text=_('Enabled high verbosity debugging for rsyslogd. Useful for debugging connection issues for external log aggregation.'),
category=_('Logging'),
category_slug='logging',
)
@@ -773,7 +664,7 @@ register(
register(
'AUTOMATION_ANALYTICS_LAST_GATHER',
field_class=fields.DateTimeField,
label=_('Last gather date for Automation Analytics.'),
label=_('Last gather date for Insights for Ansible Automation Platform.'),
allow_null=True,
category=_('System'),
category_slug='system',
@@ -781,7 +672,7 @@ register(
register(
'AUTOMATION_ANALYTICS_LAST_ENTRIES',
field_class=fields.CharField,
label=_('Last gathered entries for expensive Automation Analytics collectors.'),
label=_('Last gathered entries for expensive collectors for Insights for Ansible Automation Platform.'),
default='',
allow_blank=True,
category=_('System'),
@@ -792,7 +683,7 @@ register(
register(
'AUTOMATION_ANALYTICS_GATHER_INTERVAL',
field_class=fields.IntegerField,
label=_('Automation Analytics Gather Interval'),
label=_('Insights for Ansible Automation Platform Gather Interval'),
help_text=_('Interval (in seconds) between data gathering.'),
default=14400, # every 4 hours
min_value=1800, # every 30 minutes
@@ -801,6 +692,15 @@ register(
unit=_('seconds'),
)
register(
'IS_K8S',
field_class=fields.BooleanField,
read_only=True,
category=_('System'),
category_slug='system',
help_text=_('Indicates whether the instance is part of a kubernetes-based deployment.'),
)
def logging_validate(serializer, attrs):
if not serializer.instance or not hasattr(serializer.instance, 'LOG_AGGREGATOR_HOST') or not hasattr(serializer.instance, 'LOG_AGGREGATOR_TYPE'):

View File

@@ -7,7 +7,6 @@ from django.utils.translation import ugettext_lazy as _
__all__ = [
'CLOUD_PROVIDERS',
'SCHEDULEABLE_PROVIDERS',
'PRIVILEGE_ESCALATION_METHODS',
'ANSI_SGR_PATTERN',
'CAN_CANCEL',
@@ -15,11 +14,7 @@ __all__ = [
'STANDARD_INVENTORY_UPDATE_ENV',
]
CLOUD_PROVIDERS = ('azure_rm', 'ec2', 'gce', 'vmware', 'openstack', 'rhv', 'satellite6', 'tower')
SCHEDULEABLE_PROVIDERS = CLOUD_PROVIDERS + (
'custom',
'scm',
)
CLOUD_PROVIDERS = ('azure_rm', 'ec2', 'gce', 'vmware', 'openstack', 'rhv', 'satellite6', 'controller', 'insights')
PRIVILEGE_ESCALATION_METHODS = [
('sudo', _('Sudo')),
('su', _('Su')),
@@ -46,6 +41,7 @@ STANDARD_INVENTORY_UPDATE_ENV = {
}
CAN_CANCEL = ('new', 'pending', 'waiting', 'running')
ACTIVE_STATES = CAN_CANCEL
MINIMAL_EVENTS = set(['playbook_on_play_start', 'playbook_on_task_start', 'playbook_on_stats', 'EOF'])
CENSOR_VALUE = '************'
ENV_BLOCKLIST = frozenset(
(

View File

@@ -0,0 +1,56 @@
from .plugin import CredentialPlugin
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from thycotic.secrets.vault import SecretsVault
dsv_inputs = {
'fields': [
{
'id': 'tenant',
'label': _('Tenant'),
'help_text': _('The tenant e.g. "ex" when the URL is https://ex.secretservercloud.com'),
'type': 'string',
},
{
'id': 'tld',
'label': _('Top-level Domain (TLD)'),
'help_text': _('The TLD of the tenant e.g. "com" when the URL is https://ex.secretservercloud.com'),
'choices': ['ca', 'com', 'com.au', 'com.sg', 'eu'],
'default': 'com',
},
{'id': 'client_id', 'label': _('Client ID'), 'type': 'string'},
{
'id': 'client_secret',
'label': _('Client Secret'),
'type': 'string',
'secret': True,
},
],
'metadata': [
{
'id': 'path',
'label': _('Secret Path'),
'type': 'string',
'help_text': _('The secret path e.g. /test/secret1'),
},
],
'required': ['tenant', 'client_id', 'client_secret', 'path'],
}
if settings.DEBUG:
dsv_inputs['fields'].append(
{
'id': 'url_template',
'label': _('URL template'),
'type': 'string',
'default': 'https://{}.secretsvaultcloud.{}/v1',
}
)
dsv_plugin = CredentialPlugin(
'Thycotic DevOps Secrets Vault',
dsv_inputs,
lambda **kwargs: SecretsVault(**{k: v for (k, v) in kwargs.items() if k in [field['id'] for field in dsv_inputs['fields']]}).get_secret(kwargs['path']),
)

View File

@@ -63,7 +63,15 @@ base_inputs = {
'id': 'secret_path',
'label': _('Path to Secret'),
'type': 'string',
'help_text': _('The path to the secret stored in the secret backend e.g, /some/secret/'),
'help_text': _(
(
'The path to the secret stored in the secret backend e.g, /some/secret/. It is recommended'
' that you use the secret backend field to identify the storage backend and to use this field'
' for locating a specific secret within that store. However, if you prefer to fully identify'
' both the secret backend and one of its secrets using only this field, join their locations'
' into a single path without any additional separators, e.g, /location/of/backend/some/secret.'
)
),
},
{
'id': 'auth_path',

View File

@@ -18,7 +18,7 @@ def reap_job(j, status):
j.start_args = '' # blank field to remove encrypted passwords
j.job_explanation += ' '.join(
(
'Task was marked as running in Tower but was not present in',
'Task was marked as running but was not present in',
'the job queue, so it has been marked as failed.',
)
)
@@ -37,7 +37,7 @@ def reap(instance=None, status='failed', excluded_uuids=[]):
if me is None:
(changed, me) = Instance.objects.get_or_register()
if changed:
logger.info("Registered tower node '{}'".format(me.hostname))
logger.info("Registered node '{}'".format(me.hostname))
now = tz_now()
workflow_ctype_id = ContentType.objects.get_for_model(WorkflowJob).id
jobs = UnifiedJob.objects.filter(

View File

@@ -142,7 +142,8 @@ class CallbackBrokerWorker(BaseWorker):
logger.exception('Database Error Saving Job Event')
duration_to_save = time.perf_counter() - duration_to_save
for e in events:
emit_event_detail(e)
if not getattr(e, '_skip_websocket_message', False):
emit_event_detail(e)
self.buff = {}
self.last_flush = time.time()
# only update metrics if we saved events
@@ -207,7 +208,13 @@ class CallbackBrokerWorker(BaseWorker):
GuidMiddleware.set_guid('')
return
skip_websocket_message = body.pop('skip_websocket_message', False)
event = cls.create_from_data(**body)
if skip_websocket_message:
event._skip_websocket_message = True
self.buff.setdefault(cls, []).append(event)
retries = 0

View File

@@ -642,7 +642,7 @@ class CredentialInputField(JSONSchemaField):
# `ssh_key_unlock` requirements are very specific and can't be
# represented without complicated JSON schema
if model_instance.credential_type.managed_by_tower is True and 'ssh_key_unlock' in defined_fields:
if model_instance.credential_type.managed is True and 'ssh_key_unlock' in defined_fields:
# in order to properly test the necessity of `ssh_key_unlock`, we
# need to know the real value of `ssh_key_data`; for a payload like:
@@ -711,7 +711,7 @@ class CredentialTypeInputField(JSONSchemaField):
}
def validate(self, value, model_instance):
if isinstance(value, dict) and 'dependencies' in value and not model_instance.managed_by_tower:
if isinstance(value, dict) and 'dependencies' in value and not model_instance.managed:
raise django_exceptions.ValidationError(
_("'dependencies' is not supported for custom credentials."),
code='invalid',

View File

@@ -1 +0,0 @@
authorized_keys

View File

@@ -1,365 +0,0 @@
import fnmatch
import json
import os
import shutil
import stat
import tempfile
import time
import logging
import datetime
from django.conf import settings
import ansible_runner
import awx
from awx.main.utils import get_system_task_capacity
logger = logging.getLogger('awx.isolated.manager')
playbook_logger = logging.getLogger('awx.isolated.manager.playbooks')
def set_pythonpath(venv_libdir, env):
env.pop('PYTHONPATH', None) # default to none if no python_ver matches
for version in os.listdir(venv_libdir):
if fnmatch.fnmatch(version, 'python[23].*'):
if os.path.isdir(os.path.join(venv_libdir, version)):
env['PYTHONPATH'] = os.path.join(venv_libdir, version, "site-packages") + ":"
break
class IsolatedManager(object):
def __init__(self, event_handler, canceled_callback=None, check_callback=None):
"""
:param event_handler: a callable used to persist event data from isolated nodes
:param canceled_callback: a callable - which returns `True` or `False`
- signifying if the job has been prematurely
canceled
"""
self.event_handler = event_handler
self.canceled_callback = canceled_callback
self.check_callback = check_callback
self.started_at = None
self.captured_command_artifact = False
self.instance = None
def build_inventory(self, hosts):
inventory = '\n'.join(['{} ansible_ssh_user={}'.format(host, settings.AWX_ISOLATED_USERNAME) for host in hosts])
return inventory
def build_runner_params(self, hosts, verbosity=1):
env = dict(os.environ.items())
env['ANSIBLE_RETRY_FILES_ENABLED'] = 'False'
env['ANSIBLE_HOST_KEY_CHECKING'] = str(settings.AWX_ISOLATED_HOST_KEY_CHECKING)
env['ANSIBLE_LIBRARY'] = os.path.join(os.path.dirname(awx.__file__), 'plugins', 'isolated')
env['ANSIBLE_COLLECTIONS_PATHS'] = settings.AWX_ANSIBLE_COLLECTIONS_PATHS
set_pythonpath(os.path.join(settings.ANSIBLE_VENV_PATH, 'lib'), env)
def finished_callback(runner_obj):
if runner_obj.status == 'failed' and runner_obj.config.playbook != 'check_isolated.yml':
# failed for clean_isolated.yml just means the playbook hasn't
# exited on the isolated host
stdout = runner_obj.stdout.read()
playbook_logger.error(stdout)
elif runner_obj.status == 'timeout':
# this means that the default idle timeout of
# (2 * AWX_ISOLATED_CONNECTION_TIMEOUT) was exceeded
# (meaning, we tried to sync with an isolated node, and we got
# no new output for 2 * AWX_ISOLATED_CONNECTION_TIMEOUT seconds)
# this _usually_ means SSH key auth from the controller ->
# isolated didn't work, and ssh is hung waiting on interactive
# input e.g.,
#
# awx@isolated's password:
stdout = runner_obj.stdout.read()
playbook_logger.error(stdout)
else:
playbook_logger.info(runner_obj.stdout.read())
return {
'project_dir': os.path.abspath(os.path.join(os.path.dirname(awx.__file__), 'playbooks')),
'inventory': self.build_inventory(hosts),
'envvars': env,
'finished_callback': finished_callback,
'verbosity': verbosity,
'cancel_callback': self.canceled_callback,
'settings': {
'job_timeout': settings.AWX_ISOLATED_LAUNCH_TIMEOUT,
'suppress_ansible_output': True,
},
}
def path_to(self, *args):
return os.path.join(self.private_data_dir, *args)
def run_management_playbook(self, playbook, private_data_dir, idle_timeout=None, **kw):
iso_dir = tempfile.mkdtemp(prefix=playbook, dir=private_data_dir)
params = self.runner_params.copy()
params.get('envvars', dict())['ANSIBLE_CALLBACK_WHITELIST'] = 'profile_tasks'
params['playbook'] = playbook
params['private_data_dir'] = iso_dir
if idle_timeout:
params['settings']['idle_timeout'] = idle_timeout
else:
params['settings'].pop('idle_timeout', None)
params.update(**kw)
if all([getattr(settings, 'AWX_ISOLATED_KEY_GENERATION', False) is True, getattr(settings, 'AWX_ISOLATED_PRIVATE_KEY', None)]):
params['ssh_key'] = settings.AWX_ISOLATED_PRIVATE_KEY
return ansible_runner.interface.run(**params)
def dispatch(self, playbook=None, module=None, module_args=None):
"""
Ship the runner payload to a remote host for isolated execution.
"""
self.handled_events = set()
self.started_at = time.time()
# exclude certain files from the rsync
rsync_exclude = [
# don't rsync source control metadata (it can be huge!)
'- /project/.git',
'- /project/.svn',
# don't rsync job events that are in the process of being written
'- /artifacts/job_events/*-partial.json.tmp',
# don't rsync the ssh_key FIFO
'- /env/ssh_key',
# don't rsync kube config files
'- .kubeconfig*',
]
for filename, data in (['.rsync-filter', '\n'.join(rsync_exclude)],):
path = self.path_to(filename)
with open(path, 'w') as f:
f.write(data)
os.chmod(path, stat.S_IRUSR)
extravars = {
'src': self.private_data_dir,
'dest': settings.AWX_ISOLATION_BASE_PATH,
'ident': self.ident,
'job_id': self.instance.id,
}
if playbook:
extravars['playbook'] = playbook
if module and module_args:
extravars['module'] = module
extravars['module_args'] = module_args
logger.debug('Starting job {} on isolated host with `run_isolated.yml` playbook.'.format(self.instance.id))
runner_obj = self.run_management_playbook(
'run_isolated.yml', self.private_data_dir, idle_timeout=max(60, 2 * settings.AWX_ISOLATED_CONNECTION_TIMEOUT), extravars=extravars
)
if runner_obj.status == 'failed':
self.instance.result_traceback = runner_obj.stdout.read()
self.instance.save(update_fields=['result_traceback'])
return 'error', runner_obj.rc
return runner_obj.status, runner_obj.rc
def check(self, interval=None):
"""
Repeatedly poll the isolated node to determine if the job has run.
On success, copy job artifacts to the controlling node.
On failure, continue to poll the isolated node (until the job timeout
is exceeded).
For a completed job run, this function returns (status, rc),
representing the status and return code of the isolated
`ansible-playbook` run.
:param interval: an interval (in seconds) to wait between status polls
"""
interval = interval if interval is not None else settings.AWX_ISOLATED_CHECK_INTERVAL
extravars = {'src': self.private_data_dir, 'job_id': self.instance.id}
status = 'failed'
rc = None
last_check = time.time()
while status == 'failed':
canceled = self.canceled_callback() if self.canceled_callback else False
if not canceled and time.time() - last_check < interval:
# If the job isn't canceled, but we haven't waited `interval` seconds, wait longer
time.sleep(1)
continue
if canceled:
logger.warning('Isolated job {} was manually canceled.'.format(self.instance.id))
logger.debug('Checking on isolated job {} with `check_isolated.yml`.'.format(self.instance.id))
time_start = datetime.datetime.now()
runner_obj = self.run_management_playbook('check_isolated.yml', self.private_data_dir, extravars=extravars)
time_end = datetime.datetime.now()
time_diff = time_end - time_start
logger.debug('Finished checking on isolated job {} with `check_isolated.yml` took {} seconds.'.format(self.instance.id, time_diff.total_seconds()))
status, rc = runner_obj.status, runner_obj.rc
if self.check_callback is not None and not self.captured_command_artifact:
command_path = self.path_to('artifacts', self.ident, 'command')
# If the configuration artifact has been synced back, update the model
if os.path.exists(command_path):
try:
with open(command_path, 'r') as f:
data = json.load(f)
self.check_callback(data)
self.captured_command_artifact = True
except json.decoder.JSONDecodeError: # Just in case it's not fully here yet.
pass
self.consume_events()
last_check = time.time()
if status == 'successful':
status_path = self.path_to('artifacts', self.ident, 'status')
rc_path = self.path_to('artifacts', self.ident, 'rc')
if os.path.exists(status_path):
with open(status_path, 'r') as f:
status = f.readline()
with open(rc_path, 'r') as f:
rc = int(f.readline())
else:
# if there's no status file, it means that runner _probably_
# exited with a traceback (which should be logged to
# daemon.log) Record it so we can see how runner failed.
daemon_path = self.path_to('daemon.log')
if os.path.exists(daemon_path):
with open(daemon_path, 'r') as f:
self.instance.result_traceback = f.read()
self.instance.save(update_fields=['result_traceback'])
else:
logger.error('Failed to rsync daemon.log (is ansible-runner installed on the isolated host?)')
status = 'failed'
rc = 1
# consume events one last time just to be sure we didn't miss anything
# in the final sync
self.consume_events()
return status, rc
def consume_events(self):
# discover new events and ingest them
events_path = self.path_to('artifacts', self.ident, 'job_events')
# it's possible that `events_path` doesn't exist *yet*, because runner
# hasn't actually written any events yet (if you ran e.g., a sleep 30)
# only attempt to consume events if any were rsynced back
if os.path.exists(events_path):
for event in set(os.listdir(events_path)) - self.handled_events:
path = os.path.join(events_path, event)
if os.path.exists(path) and os.path.isfile(path):
try:
event_data = json.load(open(os.path.join(events_path, event), 'r'))
except json.decoder.JSONDecodeError:
# This means the event we got back isn't valid JSON
# that can happen if runner is still partially
# writing an event file while it's rsyncing
# these event writes are _supposed_ to be atomic
# but it doesn't look like they actually are in
# practice
# in this scenario, just ignore this event and try it
# again on the next sync
continue
self.event_handler(event_data)
self.handled_events.add(event)
def cleanup(self):
extravars = {
'private_data_dir': self.private_data_dir,
'cleanup_dirs': [
self.private_data_dir,
],
}
logger.debug('Cleaning up job {} on isolated host with `clean_isolated.yml` playbook.'.format(self.instance.id))
self.run_management_playbook('clean_isolated.yml', self.private_data_dir, extravars=extravars)
@classmethod
def update_capacity(cls, instance, task_result):
instance.version = 'ansible-runner-{}'.format(task_result['version'])
if instance.capacity == 0 and task_result['capacity_cpu']:
logger.warning('Isolated instance {} has re-joined.'.format(instance.hostname))
instance.cpu = int(task_result['cpu'])
instance.memory = int(task_result['mem'])
instance.cpu_capacity = int(task_result['capacity_cpu'])
instance.mem_capacity = int(task_result['capacity_mem'])
instance.capacity = get_system_task_capacity(
scale=instance.capacity_adjustment, cpu_capacity=int(task_result['capacity_cpu']), mem_capacity=int(task_result['capacity_mem'])
)
instance.save(update_fields=['cpu', 'memory', 'cpu_capacity', 'mem_capacity', 'capacity', 'version', 'modified'])
def health_check(self, instance_qs):
"""
:param instance_qs: List of Django objects representing the
isolated instances to manage
Runs playbook that will
- determine if instance is reachable
- find the instance capacity
- clean up orphaned private files
Performs save on each instance to update its capacity.
"""
instance_qs = [i for i in instance_qs if i.enabled]
if not len(instance_qs):
return
try:
private_data_dir = tempfile.mkdtemp(prefix='awx_iso_heartbeat_', dir=settings.AWX_ISOLATION_BASE_PATH)
self.runner_params = self.build_runner_params([instance.hostname for instance in instance_qs])
self.runner_params['private_data_dir'] = private_data_dir
self.runner_params['forks'] = len(instance_qs)
runner_obj = self.run_management_playbook('heartbeat_isolated.yml', private_data_dir)
for instance in instance_qs:
task_result = {}
try:
task_result = runner_obj.get_fact_cache(instance.hostname)
except Exception:
logger.exception('Failed to read status from isolated instances')
if 'awx_capacity_cpu' in task_result and 'awx_capacity_mem' in task_result:
task_result = {
'cpu': task_result['awx_cpu'],
'mem': task_result['awx_mem'],
'capacity_cpu': task_result['awx_capacity_cpu'],
'capacity_mem': task_result['awx_capacity_mem'],
'version': task_result['awx_capacity_version'],
}
IsolatedManager.update_capacity(instance, task_result)
logger.debug('Isolated instance {} successful heartbeat'.format(instance.hostname))
elif instance.capacity == 0:
logger.debug('Isolated instance {} previously marked as lost, could not re-join.'.format(instance.hostname))
else:
logger.warning('Could not update status of isolated instance {}'.format(instance.hostname))
if instance.is_lost(isolated=True):
instance.capacity = 0
instance.save(update_fields=['capacity'])
logger.error('Isolated instance {} last checked in at {}, marked as lost.'.format(instance.hostname, instance.modified))
finally:
if os.path.exists(private_data_dir):
shutil.rmtree(private_data_dir)
def run(self, instance, private_data_dir, playbook, module, module_args, ident=None):
"""
Run a job on an isolated host.
:param instance: a `model.Job` instance
:param private_data_dir: an absolute path on the local file system
where job-specific data should be written
(i.e., `/tmp/awx_N_xyz/`)
:param playbook: the playbook to run
:param module: the module to run
:param module_args: the module args to use
For a completed job run, this function returns (status, rc),
representing the status and return code of the isolated
`ansible-playbook` run.
"""
self.ident = ident
self.instance = instance
self.private_data_dir = private_data_dir
self.runner_params = self.build_runner_params([instance.execution_node], verbosity=min(5, self.instance.verbosity))
status, rc = self.dispatch(playbook, module, module_args)
if status == 'successful':
status, rc = self.check()
return status, rc

View File

@@ -1,13 +1,5 @@
from django.db import connections
from django.db.backends.sqlite3.base import DatabaseWrapper
from django.core.management.commands.makemigrations import Command as MakeMigrations
class Command(MakeMigrations):
def execute(self, *args, **options):
settings = connections['default'].settings_dict.copy()
settings['ENGINE'] = 'sqlite3'
if 'application_name' in settings['OPTIONS']:
del settings['OPTIONS']['application_name']
connections['default'] = DatabaseWrapper(settings)
return MakeMigrations().execute(*args, **options)
pass

View File

@@ -4,11 +4,13 @@
# Python
import datetime
import logging
import pytz
import re
# Django
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.db import transaction, connection
from django.utils.timezone import now
# AWX
@@ -18,6 +20,132 @@ from awx.main.signals import disable_activity_stream, disable_computed_fields
from awx.main.utils.deletion import AWXCollector, pre_delete
def unified_job_class_to_event_table_name(job_class):
return f'main_{job_class().event_class.__name__.lower()}'
def partition_table_name(job_class, dt):
suffix = dt.replace(microsecond=0, second=0, minute=0).strftime('%Y%m%d_%H')
event_tbl_name = unified_job_class_to_event_table_name(job_class)
event_tbl_name += f'_{suffix}'
return event_tbl_name
def partition_name_dt(part_name):
"""
part_name examples:
main_jobevent_20210318_09
main_projectupdateevent_20210318_11
main_inventoryupdateevent_20210318_03
"""
if '_unpartitioned' in part_name:
return None
p = re.compile('([a-z]+)_([a-z]+)_([0-9]+)_([0-9][0-9])')
m = p.match(part_name)
if not m:
return m
dt_str = f"{m.group(3)}_{m.group(4)}"
dt = datetime.datetime.strptime(dt_str, '%Y%m%d_%H').replace(tzinfo=pytz.UTC)
return dt
def dt_to_partition_name(tbl_name, dt):
return f"{tbl_name}_{dt.strftime('%Y%m%d_%H')}"
class DeleteMeta:
def __init__(self, logger, job_class, cutoff, dry_run):
self.logger = logger
self.job_class = job_class
self.cutoff = cutoff
self.dry_run = dry_run
self.jobs_qs = None # Set in by find_jobs_to_delete()
self.parts_no_drop = set() # Set in identify_excluded_partitions()
self.parts_to_drop = set() # Set in find_partitions_to_drop()
self.jobs_pk_list = [] # Set in find_jobs_to_delete()
self.jobs_to_delete_count = 0 # Set in find_jobs_to_delete()
self.jobs_no_delete_count = 0 # Set in find_jobs_to_delete()
def find_jobs_to_delete(self):
self.jobs_qs = self.job_class.objects.filter(created__lt=self.cutoff).values_list('pk', 'status', 'created')
for pk, status, created in self.jobs_qs:
if status not in ['pending', 'waiting', 'running']:
self.jobs_to_delete_count += 1
self.jobs_pk_list.append(pk)
self.jobs_no_delete_count = (
self.job_class.objects.filter(created__gte=self.cutoff) | self.job_class.objects.filter(status__in=['pending', 'waiting', 'running'])
).count()
def identify_excluded_partitions(self):
part_drop = {}
for pk, status, created in self.jobs_qs:
part_key = partition_table_name(self.job_class, created)
if status in ['pending', 'waiting', 'running']:
part_drop[part_key] = False
else:
part_drop.setdefault(part_key, True)
# Note that parts_no_drop _may_ contain the names of partitions that don't exist
# This can happen when the cleanup of _unpartitioned_* logic leaves behind jobs with status pending, waiting, running. The find_jobs_to_delete() will
# pick these jobs up.
self.parts_no_drop = set([k for k, v in part_drop.items() if v is False])
def delete_jobs(self):
if not self.dry_run:
self.job_class.objects.filter(pk__in=self.jobs_pk_list).delete()
def find_partitions_to_drop(self):
tbl_name = unified_job_class_to_event_table_name(self.job_class)
with connection.cursor() as cursor:
query = "SELECT inhrelid::regclass::text AS child FROM pg_catalog.pg_inherits"
query += f" WHERE inhparent = 'public.{tbl_name}'::regclass"
query += f" AND TO_TIMESTAMP(LTRIM(inhrelid::regclass::text, '{tbl_name}_'), 'YYYYMMDD_HH24') < '{self.cutoff}'"
query += " ORDER BY inhrelid::regclass::text"
cursor.execute(query)
partitions_from_db = [r[0] for r in cursor.fetchall()]
partitions_dt = [partition_name_dt(p) for p in partitions_from_db if not None]
partitions_dt = [p for p in partitions_dt if not None]
# convert datetime partition back to string partition
partitions_maybe_drop = set([dt_to_partition_name(tbl_name, dt) for dt in partitions_dt])
# Do not drop partition if there is a job that will not be deleted pointing at it
self.parts_to_drop = partitions_maybe_drop - self.parts_no_drop
def drop_partitions(self):
if len(self.parts_to_drop) > 0:
parts_to_drop = list(self.parts_to_drop)
parts_to_drop.sort() # sort it to make reading it easier for humans
parts_to_drop_str = ','.join(parts_to_drop)
if self.dry_run:
self.logger.debug(f"Would drop event partition(s) {parts_to_drop_str}")
else:
self.logger.debug(f"Dropping event partition(s) {parts_to_drop_str}")
if not self.dry_run:
with connection.cursor() as cursor:
cursor.execute(f"DROP TABLE {parts_to_drop_str}")
else:
self.logger.debug("No event partitions to drop")
def delete(self):
self.find_jobs_to_delete()
self.identify_excluded_partitions()
self.find_partitions_to_drop()
self.drop_partitions()
self.delete_jobs()
return (self.jobs_no_delete_count, self.jobs_to_delete_count)
class Command(BaseCommand):
"""
Management command to cleanup old jobs and project updates.
@@ -36,6 +164,43 @@ class Command(BaseCommand):
parser.add_argument('--notifications', dest='only_notifications', action='store_true', default=False, help='Remove notifications')
parser.add_argument('--workflow-jobs', default=False, action='store_true', dest='only_workflow_jobs', help='Remove workflow jobs')
def cleanup(self, job_class):
delete_meta = DeleteMeta(self.logger, job_class, self.cutoff, self.dry_run)
skipped, deleted = delete_meta.delete()
return (delete_meta.jobs_no_delete_count, delete_meta.jobs_to_delete_count)
def cleanup_jobs_partition(self):
return self.cleanup(Job)
def cleanup_ad_hoc_commands_partition(self):
return self.cleanup(AdHocCommand)
def cleanup_project_updates_partition(self):
return self.cleanup(ProjectUpdate)
def cleanup_inventory_updates_partition(self):
return self.cleanup(InventoryUpdate)
def cleanup_management_jobs_partition(self):
return self.cleanup(SystemJob)
def cleanup_workflow_jobs_partition(self):
delete_meta = DeleteMeta(self.logger, WorkflowJob, self.cutoff, self.dry_run)
delete_meta.find_jobs_to_delete()
delete_meta.delete_jobs()
return (delete_meta.jobs_no_delete_count, delete_meta.jobs_to_delete_count)
def _cascade_delete_job_events(self, model, pk_list):
if len(pk_list) > 0:
with connection.cursor() as cursor:
tblname = unified_job_class_to_event_table_name(model)
pk_list_csv = ','.join(map(str, pk_list))
rel_name = model().event_parent_key
cursor.execute(f"DELETE FROM _unpartitioned_{tblname} WHERE {rel_name} IN ({pk_list_csv})")
def cleanup_jobs(self):
skipped, deleted = 0, 0
@@ -45,12 +210,14 @@ class Command(BaseCommand):
# get queryset for available jobs to remove
qs = Job.objects.filter(created__lt=self.cutoff).exclude(status__in=['pending', 'waiting', 'running'])
# get pk list for the first N (batch_size) objects
pk_list = qs[0:batch_size].values_list('pk')
pk_list = qs[0:batch_size].values_list('pk', flat=True)
# You cannot delete queries with sql LIMIT set, so we must
# create a new query from this pk_list
qs_batch = Job.objects.filter(pk__in=pk_list)
just_deleted = 0
if not self.dry_run:
self._cascade_delete_job_events(Job, pk_list)
del_query = pre_delete(qs_batch)
collector = AWXCollector(del_query.db)
collector.collect(del_query)
@@ -71,6 +238,7 @@ class Command(BaseCommand):
def cleanup_ad_hoc_commands(self):
skipped, deleted = 0, 0
ad_hoc_commands = AdHocCommand.objects.filter(created__lt=self.cutoff)
pk_list = []
for ad_hoc_command in ad_hoc_commands.iterator():
ad_hoc_command_display = '"%s" (%d events)' % (str(ad_hoc_command), ad_hoc_command.ad_hoc_command_events.count())
if ad_hoc_command.status in ('pending', 'waiting', 'running'):
@@ -81,15 +249,20 @@ class Command(BaseCommand):
action_text = 'would delete' if self.dry_run else 'deleting'
self.logger.info('%s %s', action_text, ad_hoc_command_display)
if not self.dry_run:
pk_list.append(ad_hoc_command.pk)
ad_hoc_command.delete()
deleted += 1
if not self.dry_run:
self._cascade_delete_job_events(AdHocCommand, pk_list)
skipped += AdHocCommand.objects.filter(created__gte=self.cutoff).count()
return skipped, deleted
def cleanup_project_updates(self):
skipped, deleted = 0, 0
project_updates = ProjectUpdate.objects.filter(created__lt=self.cutoff)
pk_list = []
for pu in project_updates.iterator():
pu_display = '"%s" (type %s)' % (str(pu), str(pu.launch_type))
if pu.status in ('pending', 'waiting', 'running'):
@@ -104,15 +277,20 @@ class Command(BaseCommand):
action_text = 'would delete' if self.dry_run else 'deleting'
self.logger.info('%s %s', action_text, pu_display)
if not self.dry_run:
pk_list.append(pu.pk)
pu.delete()
deleted += 1
if not self.dry_run:
self._cascade_delete_job_events(ProjectUpdate, pk_list)
skipped += ProjectUpdate.objects.filter(created__gte=self.cutoff).count()
return skipped, deleted
def cleanup_inventory_updates(self):
skipped, deleted = 0, 0
inventory_updates = InventoryUpdate.objects.filter(created__lt=self.cutoff)
pk_list = []
for iu in inventory_updates.iterator():
iu_display = '"%s" (source %s)' % (str(iu), str(iu.source))
if iu.status in ('pending', 'waiting', 'running'):
@@ -127,15 +305,20 @@ class Command(BaseCommand):
action_text = 'would delete' if self.dry_run else 'deleting'
self.logger.info('%s %s', action_text, iu_display)
if not self.dry_run:
pk_list.append(iu.pk)
iu.delete()
deleted += 1
if not self.dry_run:
self._cascade_delete_job_events(InventoryUpdate, pk_list)
skipped += InventoryUpdate.objects.filter(created__gte=self.cutoff).count()
return skipped, deleted
def cleanup_management_jobs(self):
skipped, deleted = 0, 0
system_jobs = SystemJob.objects.filter(created__lt=self.cutoff)
pk_list = []
for sj in system_jobs.iterator():
sj_display = '"%s" (type %s)' % (str(sj), str(sj.job_type))
if sj.status in ('pending', 'waiting', 'running'):
@@ -146,9 +329,13 @@ class Command(BaseCommand):
action_text = 'would delete' if self.dry_run else 'deleting'
self.logger.info('%s %s', action_text, sj_display)
if not self.dry_run:
pk_list.append(sj.pk)
sj.delete()
deleted += 1
if not self.dry_run:
self._cascade_delete_job_events(SystemJob, pk_list)
skipped += SystemJob.objects.filter(created__gte=self.cutoff).count()
return skipped, deleted
@@ -222,6 +409,13 @@ class Command(BaseCommand):
for m in model_names:
if m in models_to_cleanup:
skipped, deleted = getattr(self, 'cleanup_%s' % m)()
func = getattr(self, 'cleanup_%s_partition' % m, None)
if func:
skipped_partition, deleted_partition = func()
skipped += skipped_partition
deleted += deleted_partition
if self.dry_run:
self.logger.log(99, '%s: %d would be deleted, %d would be skipped.', m.replace('_', ' '), deleted, skipped)
else:

View File

@@ -2,9 +2,8 @@
# All Rights Reserved
from django.core.management.base import BaseCommand
from django.conf import settings
from crum import impersonate
from awx.main.models import User, Organization, Project, Inventory, CredentialType, Credential, Host, JobTemplate, ExecutionEnvironment
from awx.main.models import User, Organization, Project, Inventory, CredentialType, Credential, Host, JobTemplate
from awx.main.signals import disable_computed_fields
@@ -45,7 +44,7 @@ class Command(BaseCommand):
public_galaxy_credential = Credential(
name='Ansible Galaxy',
managed_by_tower=True,
managed=True,
credential_type=CredentialType.objects.get(kind='galaxy'),
inputs={'url': 'https://galaxy.ansible.com/'},
)
@@ -68,13 +67,6 @@ class Command(BaseCommand):
print('Demo Credential, Inventory, and Job Template added.')
changed = True
for ee in reversed(settings.DEFAULT_EXECUTION_ENVIRONMENTS):
_, created = ExecutionEnvironment.objects.get_or_create(name=ee['name'], defaults={'image': ee['image'], 'managed_by_tower': True})
if created:
changed = True
print('Default Execution Environment(s) registered.')
if changed:
print('(changed: True)')
else:

View File

@@ -0,0 +1,59 @@
# Copyright (c) 2021 Ansible, Inc.
# All Rights Reserved
from django.core.management.base import BaseCommand
from awx.main.utils.common import get_custom_venv_choices
from awx.main.models import Organization, InventorySource, JobTemplate, Project
import yaml
class Command(BaseCommand):
"""Returns the pip freeze from the path passed in the argument"""
def add_arguments(self, parser):
parser.add_argument(
'path',
type=str,
nargs=1,
default='',
help='run this with a path to a virtual environment as an argument to see the associated Job Templates, Organizations, Projects, and Inventory Sources.',
)
parser.add_argument('-q', action='store_true', help='run with -q to output only the results of the query.')
def handle(self, *args, **options):
# look organiztions and unified job templates (which include JTs, workflows, and Inventory updates)
super(Command, self).__init__()
results = {}
path = options.get('path')
if path:
all_venvs = get_custom_venv_choices()
if path[0] in all_venvs: # verify this is a valid path
path = path[0]
orgs = [{"name": org.name, "id": org.id} for org in Organization.objects.filter(custom_virtualenv=path)]
jts = [{"name": jt.name, "id": jt.id} for jt in JobTemplate.objects.filter(custom_virtualenv=path)]
proj = [{"name": proj.name, "id": proj.id} for proj in Project.objects.filter(custom_virtualenv=path)]
invsrc = [{"name": inv.name, "id": inv.id} for inv in InventorySource.objects.filter(custom_virtualenv=path)]
results["organizations"] = orgs
results["job_templates"] = jts
results["projects"] = proj
results["inventory_sources"] = invsrc
if not options.get('q'):
msg = [
'# Virtual Environments Associations:',
yaml.dump(results),
'- To list all (now deprecated) custom virtual environments run:',
'awx-manage list_custom_venvs',
'',
'- To export the contents of a (deprecated) virtual environment, ' 'run the following command while supplying the path as an argument:',
'awx-manage export_custom_venv /path/to/venv',
'',
'- Run these commands with `-q` to remove tool tips.',
'',
]
print('\n'.join(msg))
else:
print(yaml.dump(results))
else:
print('\n', '# Incorrect path, verify your path is from the following list:')
print('\n'.join(all_venvs), '\n')

View File

@@ -10,7 +10,7 @@ from awx.main.utils.pglock import advisory_lock
class Command(BaseCommand):
"""
Deprovision a Tower cluster node
Deprovision a cluster node
"""
help = 'Remove instance from the database. ' 'Specify `--hostname` to use this command.'

View File

@@ -31,6 +31,7 @@ class Command(BaseCommand):
for session in sessions:
user_id = session.get_decoded().get('_auth_user_id')
if (user is None) or (user_id and user.id == int(user_id)):
# The Session model instance doesn't have .flush(), we need a SessionStore instance.
session = import_module(settings.SESSION_ENGINE).SessionStore(session.session_key)
# Log out the session, but without the need for a request object.
session.flush()

View File

@@ -0,0 +1,36 @@
import tempfile
import tarfile
import stat
import os
from awx.main.models.inventory import CustomInventoryScript
from django.core.management.base import BaseCommand
from django.utils.text import slugify
class Command(BaseCommand):
help = 'Export custom inventory scripts into a tarfile.'
def add_arguments(self, parser):
parser.add_argument('--filename', dest='filename', type=str, default='custom_scripts.tar', help='Filename of the output tar file')
def handle(self, **options):
tar_filename = options.get('filename')
with tempfile.TemporaryDirectory() as tmpdirname:
with tarfile.open(tar_filename, "w") as tar:
for cis in CustomInventoryScript.objects.all():
# naming convention similar to project paths
slug_name = slugify(str(cis.name)).replace(u'-', u'_')
script_filename = u'_%d__%s' % (int(cis.pk), slug_name)
script_path = os.path.join(tmpdirname, script_filename)
with open(script_path, 'w') as f:
f.write(cis.script)
os.chmod(script_path, stat.S_IRWXU)
tar.add(script_path, arcname=script_filename)
print('Dump of old custom inventory scripts at {}'.format(tar_filename))

View File

@@ -0,0 +1,48 @@
# Copyright (c) 2021 Ansible, Inc.
# All Rights Reserved
from awx.main.utils.common import get_custom_venv_pip_freeze, get_custom_venv_choices
from django.core.management.base import BaseCommand
class Command(BaseCommand):
"""Returns the pip freeze from the path passed in the argument"""
def add_arguments(self, parser):
parser.add_argument(
'path',
type=str,
nargs=1,
default='',
help='run this with a path to a virtual environment as an argument to see the pip freeze data',
)
parser.add_argument('-q', action='store_true', help='run with -q to output only the results of the query.')
def handle(self, *args, **options):
super(Command, self).__init__()
if options.get('path'):
path = options.get('path')
all_venvs = get_custom_venv_choices()
if path[0] in all_venvs:
pip_data = get_custom_venv_pip_freeze(options.get('path')[0])
if pip_data:
if not options.get('q'):
msg = [
'# Virtual environment contents:',
pip_data,
'- To list all (now deprecated) custom virtual environments run:',
'awx-manage list_custom_venvs',
'',
'- To view the connections a (deprecated) virtual environment had in the database, run the following command while supplying the path as an argument:',
'awx-manage custom_venv_associations /path/to/venv',
'',
'- Run these commands with `-q` to remove tool tips.',
'',
]
print('\n'.join(msg))
else:
print(pip_data)
else:
print('\n', '# Incorrect path, verify your path is from the following list:')
print('\n'.join(all_venvs))

View File

@@ -1,38 +0,0 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved
import datetime
from django.utils.encoding import smart_str
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from django.conf import settings
from django.core.management.base import BaseCommand
from awx.conf.models import Setting
class Command(BaseCommand):
"""Generate and store a randomized RSA key for SSH traffic to isolated instances"""
help = 'Generates and stores a randomized RSA key for SSH traffic to isolated instances'
def handle(self, *args, **kwargs):
if getattr(settings, 'AWX_ISOLATED_PRIVATE_KEY', False):
print(settings.AWX_ISOLATED_PUBLIC_KEY)
return
key = rsa.generate_private_key(public_exponent=65537, key_size=4096, backend=default_backend())
Setting.objects.create(
key='AWX_ISOLATED_PRIVATE_KEY',
value=key.private_bytes(
encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()
),
).save()
pemfile = Setting.objects.create(
key='AWX_ISOLATED_PUBLIC_KEY',
value=smart_str(key.public_key().public_bytes(encoding=serialization.Encoding.OpenSSH, format=serialization.PublicFormat.OpenSSH))
+ " generated-by-awx@%s" % datetime.datetime.utcnow().isoformat(),
)
pemfile.save()
print(pemfile.value)

View File

@@ -0,0 +1,54 @@
from django.core.management.base import BaseCommand
import datetime
from django.core.serializers.json import DjangoJSONEncoder
from awx.main.models.inventory import HostMetric
import json
class Command(BaseCommand):
help = 'This is for offline licensing usage'
def add_arguments(self, parser):
parser.add_argument('--since', type=datetime.datetime.fromisoformat, help='Start Date in ISO format YYYY-MM-DD')
parser.add_argument('--until', type=datetime.datetime.fromisoformat, help='End Date in ISO format YYYY-MM-DD')
parser.add_argument('--json', action='store_true', help='Select output as JSON')
def handle(self, *args, **options):
since = options.get('since')
until = options.get('until')
if since is None and until is None:
print("No Arguments received")
return None
if since is not None and since.tzinfo is None:
since = since.replace(tzinfo=datetime.timezone.utc)
if until is not None and until.tzinfo is None:
until = until.replace(tzinfo=datetime.timezone.utc)
filter_kwargs = {}
if since is not None:
filter_kwargs['last_automation__gte'] = since
if until is not None:
filter_kwargs['last_automation__lte'] = until
result = HostMetric.objects.filter(**filter_kwargs)
# if --json flag is set, output the result in json format
if options['json']:
list_of_queryset = list(result.values('hostname', 'first_automation', 'last_automation'))
json_result = json.dumps(list_of_queryset, cls=DjangoJSONEncoder)
print(json_result)
# --json flag is not set, output in plain text
else:
print(f"Total Number of hosts automated: {len(result)}")
for item in result:
print(
"Hostname : {hostname} | first_automation : {first_automation} | last_automation : {last_automation}".format(
hostname=item.hostname, first_automation=item.first_automation, last_automation=item.last_automation
)
)
return

View File

@@ -10,7 +10,6 @@ import subprocess
import sys
import time
import traceback
import shutil
# Django
from django.conf import settings
@@ -37,20 +36,20 @@ from awx.main.utils.pglock import advisory_lock
logger = logging.getLogger('awx.main.commands.inventory_import')
LICENSE_EXPIRED_MESSAGE = '''\
License expired.
See http://www.ansible.com/renew for license extension information.'''
Subscription expired.
Contact us (https://www.redhat.com/contact) for subscription extension information.'''
LICENSE_NON_EXISTANT_MESSAGE = '''\
No license.
See http://www.ansible.com/renew for license information.'''
No subscription.
Contact us (https://www.redhat.com/contact) for subscription information.'''
LICENSE_MESSAGE = '''\
Number of licensed instances exceeded, would bring available instances to %(new_count)d, system is licensed for %(instance_count)d.
See http://www.ansible.com/renew for license extension information.'''
%(new_count)d instances have been automated, system is subscribed for %(instance_count)d.
Contact us (https://www.redhat.com/contact) for upgrade information.'''
DEMO_LICENSE_MESSAGE = '''\
Demo mode free license count exceeded, would bring available instances to %(new_count)d, demo mode allows %(instance_count)d.
See http://www.ansible.com/renew for licensing information.'''
Demo mode free subscription count exceeded. Current automated instances are %(new_count)d, demo mode allows %(instance_count)d.
Contact us (https://www.redhat.com/contact) for subscription information.'''
def functioning_dir(path):
@@ -67,24 +66,9 @@ class AnsibleInventoryLoader(object):
/usr/bin/ansible/ansible-inventory -i hosts --list
"""
def __init__(self, source, venv_path=None, verbosity=0):
def __init__(self, source, verbosity=0):
self.source = source
self.verbosity = verbosity
if venv_path:
self.venv_path = venv_path
else:
self.venv_path = settings.ANSIBLE_VENV_PATH
def get_path_to_ansible_inventory(self):
venv_exe = os.path.join(self.venv_path, 'bin', 'ansible-inventory')
if os.path.exists(venv_exe):
return venv_exe
elif os.path.exists(os.path.join(self.venv_path, 'bin', 'ansible')):
# if bin/ansible exists but bin/ansible-inventory doesn't, it's
# probably a really old version of ansible that doesn't support
# ansible-inventory
raise RuntimeError("{} does not exist (please upgrade to ansible >= 2.4)".format(venv_exe))
return shutil.which('ansible-inventory')
def get_base_args(self):
bargs = ['podman', 'run', '--user=root', '--quiet']
@@ -143,13 +127,9 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('--inventory-name', dest='inventory_name', type=str, default=None, metavar='n', help='name of inventory to sync')
parser.add_argument('--inventory-id', dest='inventory_id', type=int, default=None, metavar='i', help='id of inventory to sync')
parser.add_argument('--venv', dest='venv', type=str, default=None, help='absolute path to the AWX custom virtualenv to use')
parser.add_argument('--overwrite', dest='overwrite', action='store_true', default=False, help='overwrite the destination hosts and groups')
parser.add_argument('--overwrite-vars', dest='overwrite_vars', action='store_true', default=False, help='overwrite (rather than merge) variables')
parser.add_argument('--keep-vars', dest='keep_vars', action='store_true', default=False, help='DEPRECATED legacy option, has no effect')
parser.add_argument(
'--custom', dest='custom', action='store_true', default=False, help='DEPRECATED indicates a custom inventory script, no longer used'
)
parser.add_argument('--source', dest='source', type=str, default=None, metavar='s', help='inventory directory, file, or script to load')
parser.add_argument(
'--enabled-var',
@@ -776,29 +756,22 @@ class Command(BaseCommand):
instance_count = license_info.get('instance_count', 0)
free_instances = license_info.get('free_instances', 0)
time_remaining = license_info.get('time_remaining', 0)
automated_count = license_info.get('automated_instances', 0)
hard_error = license_info.get('trial', False) is True or license_info['instance_count'] == 10
new_count = Host.objects.active_count()
if time_remaining <= 0:
if hard_error:
logger.error(LICENSE_EXPIRED_MESSAGE)
raise PermissionDenied("License has expired!")
raise PermissionDenied("Subscription has expired!")
else:
logger.warning(LICENSE_EXPIRED_MESSAGE)
# special check for tower-type inventory sources
# but only if running the plugin
TOWER_SOURCE_FILES = ['tower.yml', 'tower.yaml']
if self.inventory_source.source == 'tower' and any(f in self.inventory_source.source_path for f in TOWER_SOURCE_FILES):
# only if this is the 2nd call to license check, we cannot compare before running plugin
if hasattr(self, 'all_group'):
self.remote_tower_license_compare(local_license_type)
if free_instances < 0:
d = {
'new_count': new_count,
'new_count': automated_count,
'instance_count': instance_count,
}
if hard_error:
logger.error(LICENSE_MESSAGE % d)
raise PermissionDenied('License count exceeded!')
raise PermissionDenied('Subscription count exceeded!')
else:
logger.warning(LICENSE_MESSAGE % d)
@@ -839,7 +812,6 @@ class Command(BaseCommand):
raise CommandError('--source is required')
verbosity = int(options.get('verbosity', 1))
self.set_logging_level(verbosity)
venv_path = options.get('venv', None)
# Load inventory object based on name or ID.
if inventory_id:
@@ -869,7 +841,7 @@ class Command(BaseCommand):
_eager_fields=dict(job_args=json.dumps(sys.argv), job_env=dict(os.environ.items()), job_cwd=os.getcwd())
)
data = AnsibleInventoryLoader(source=source, venv_path=venv_path, verbosity=verbosity).load()
data = AnsibleInventoryLoader(source=source, verbosity=verbosity).load()
logger.debug('Finished loading from source: %s', source)

View File

@@ -0,0 +1,43 @@
# Copyright (c) 2021 Ansible, Inc.
# All Rights Reserved
import sys
from awx.main.utils.common import get_custom_venv_choices
from django.core.management.base import BaseCommand
from django.conf import settings
class Command(BaseCommand):
"""Returns a list of custom venv paths from the path passed in the argument"""
def add_arguments(self, parser):
parser.add_argument('-q', action='store_true', help='run with -q to output only the results of the query.')
def handle(self, *args, **options):
super(Command, self).__init__()
venvs = get_custom_venv_choices()
if venvs:
if not options.get('q'):
msg = [
'# Discovered Virtual Environments:',
'\n'.join(venvs),
'',
'- To export the contents of a (deprecated) virtual environment, ' 'run the following command while supplying the path as an argument:',
'awx-manage export_custom_venv /path/to/venv',
'',
'- To view the connections a (deprecated) virtual environment had in the database, run the following command while supplying the path as an argument:',
'awx-manage custom_venv_associations /path/to/venv',
'',
'- Run these commands with `-q` to remove tool tips.',
'',
]
print('\n'.join(msg))
else:
print('\n'.join(venvs), '\n')
else:
msg = ["No custom virtual environments detected in:", settings.BASE_VENV_PATH]
for path in settings.CUSTOM_VENV_PATHS:
msg.append(path)
print('\n'.join(msg), file=sys.stderr)

View File

@@ -10,7 +10,6 @@ class Ungrouped(object):
name = 'ungrouped'
policy_instance_percentage = None
policy_instance_minimum = None
controller = None
@property
def instances(self):
@@ -18,7 +17,7 @@ class Ungrouped(object):
@property
def capacity(self):
return sum([x.capacity for x in self.instances])
return sum(x.capacity for x in self.instances)
class Command(BaseCommand):
@@ -38,8 +37,6 @@ class Command(BaseCommand):
fmt += ' policy={0.policy_instance_percentage}%'
if instance_group.policy_instance_minimum:
fmt += ' policy>={0.policy_instance_minimum}'
if instance_group.controller:
fmt += ' controller={0.controller.name}'
print((fmt + ']').format(instance_group))
for x in instance_group.instances.all():
color = '\033[92m'
@@ -48,8 +45,6 @@ class Command(BaseCommand):
if x.enabled is False:
color = '\033[90m[DISABLED] '
fmt = '\t' + color + '{0.hostname} capacity={0.capacity} version={1}'
if x.last_isolated_check:
fmt += ' last_isolated_check="{0.last_isolated_check:%Y-%m-%d %H:%M:%S}"'
if x.capacity:
fmt += ' heartbeat="{0.modified:%Y-%m-%d %H:%M:%S}"'
print((fmt + '\033[0m').format(x, x.version or '?'))

View File

@@ -1,13 +1,11 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved
from uuid import uuid4
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from awx.main.models import Instance
from django.conf import settings
from django.db import transaction
from django.core.management.base import BaseCommand, CommandError
class Command(BaseCommand):
@@ -20,7 +18,6 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('--hostname', dest='hostname', type=str, help='Hostname used during provisioning')
parser.add_argument('--is-isolated', dest='is_isolated', action='store_true', help='Specify whether the instance is isolated')
def _register_hostname(self, hostname):
if not hostname:
@@ -36,10 +33,7 @@ class Command(BaseCommand):
def handle(self, **options):
if not options.get('hostname'):
raise CommandError("Specify `--hostname` to use this command.")
if options['is_isolated']:
self.uuid = str(uuid4())
else:
self.uuid = settings.SYSTEM_UUID
self.uuid = settings.SYSTEM_UUID
self.changed = False
self._register_hostname(options.get('hostname'))
if self.changed:

View File

@@ -16,8 +16,7 @@ from awx.main.utils.encryption import encrypt_field, decrypt_field, encrypt_valu
class Command(BaseCommand):
"""
Regenerate a new SECRET_KEY value and re-encrypt every secret in the
Tower database.
Regenerate a new SECRET_KEY value and re-encrypt every secret in the database.
"""
@transaction.atomic

View File

@@ -0,0 +1,135 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved
import sys
from distutils.util import strtobool
from argparse import RawTextHelpFormatter
from django.core.management.base import BaseCommand
from django.conf import settings
from awx.main.models import CredentialType, Credential, ExecutionEnvironment
class Command(BaseCommand):
"""Create default execution environments, intended for new installs"""
help = """
Creates or updates the execution environments set in settings.DEFAULT_EXECUTION_ENVIRONMENTS if they are not yet created.
Optionally provide authentication details to create or update a container registry credential that will be set on all of these default execution environments.
Note that settings.DEFAULT_EXECUTION_ENVIRONMENTS is and ordered list, the first in the list will be used for project updates.
"""
# Preserves newlines in the help text
def create_parser(self, *args, **kwargs):
parser = super(Command, self).create_parser(*args, **kwargs)
parser.formatter_class = RawTextHelpFormatter
return parser
def add_arguments(self, parser):
parser.add_argument(
"--registry-url",
type=str,
default="",
help="URL for the container registry",
)
parser.add_argument(
"--registry-username",
type=str,
default="",
help="username for the container registry",
)
parser.add_argument(
"--registry-password",
type=str,
default="",
help="Password or token for CLI authentication with the container registry",
)
parser.add_argument(
"--verify-ssl",
type=lambda x: bool(strtobool(str(x))),
default=True,
help="Verify SSL when authenticating with the container registry",
)
def handle(self, *args, **options):
changed = False
registry_cred = None
if options.get("registry_username"):
if not options.get("registry_password"):
sys.stderr.write("Registry password must be provided when providing registry username\n")
sys.exit(1)
if not options.get("registry_url"):
sys.stderr.write("Registry url must be provided when providing registry username\n")
sys.exit(1)
registry_cred_type = CredentialType.objects.filter(kind="registry")
if not registry_cred_type.exists():
sys.stderr.write("No registry credential type found")
sys.exit(1)
inputs = {
"host": options.get("registry_url"),
"password": options.get("registry_password"),
"username": options.get("registry_username"),
"verify_ssl": options.get("verify_ssl"),
}
registry_cred, cred_created = Credential.objects.get_or_create(
name="Default Execution Environment Registry Credential",
managed=True,
credential_type=registry_cred_type[0],
defaults={'inputs': inputs},
)
if cred_created:
changed = True
print("'Default Execution Environment Credential' registered.")
for key, value in inputs.items():
if not registry_cred.inputs.get(key) or registry_cred.get_input(key) != value:
registry_cred.inputs[key] = value
changed = True
if changed:
registry_cred.save()
print("'Default Execution Environment Credential' updated.")
# Create default globally available Execution Environments
for ee in reversed(settings.GLOBAL_JOB_EXECUTION_ENVIRONMENTS):
_this_ee, ee_created = ExecutionEnvironment.objects.get_or_create(name=ee["name"], defaults={'image': ee["image"], 'credential': registry_cred})
if ee_created:
changed = True
print(f"'{ee['name']}' Default Execution Environment registered.")
else:
if _this_ee.image != ee["image"]:
_this_ee.image = ee["image"]
changed = True
if _this_ee.credential != registry_cred:
_this_ee.credential = registry_cred
changed = True
if changed:
_this_ee.save()
print(f"'{ee['name']}' Default Execution Environment updated.")
# Create the control plane execution environment that is used for project updates and system jobs
ee = settings.CONTROL_PLANE_EXECUTION_ENVIRONMENT
_this_ee, cp_created = ExecutionEnvironment.objects.get_or_create(
name="Control Plane Execution Environment", defaults={'image': ee, 'managed': True, 'credential': registry_cred}
)
if cp_created:
changed = True
print("Control Plane Execution Environment registered.")
else:
if _this_ee.image != ee:
_this_ee.image = ee
changed = True
if _this_ee.credential != registry_cred:
_this_ee.credential = registry_cred
changed = True
if changed:
_this_ee.save()
if changed:
print("(changed: True)")
else:
print("(changed: False)")

View File

@@ -17,10 +17,9 @@ class InstanceNotFound(Exception):
class RegisterQueue:
def __init__(self, queuename, controller, instance_percent, inst_min, hostname_list, is_container_group=None):
def __init__(self, queuename, instance_percent, inst_min, hostname_list, is_container_group=None):
self.instance_not_found_err = None
self.queuename = queuename
self.controller = controller
self.instance_percent = instance_percent
self.instance_min = inst_min
self.hostname_list = hostname_list
@@ -46,20 +45,6 @@ class RegisterQueue:
return (ig, created, changed)
def update_instance_group_controller(self, ig):
changed = False
control_ig = None
if self.controller:
control_ig = InstanceGroup.objects.filter(name=self.controller).first()
if control_ig and ig.controller_id != control_ig.pk:
ig.controller = control_ig
ig.save()
changed = True
return (control_ig, changed)
def add_instances_to_group(self, ig):
changed = False
@@ -88,26 +73,20 @@ class RegisterQueue:
with advisory_lock('cluster_policy_lock'):
with transaction.atomic():
changed2 = False
changed3 = False
(ig, created, changed1) = self.get_create_update_instance_group()
if created:
print("Creating instance group {}".format(ig.name))
elif not created:
print("Instance Group already registered {}".format(ig.name))
if self.controller:
(ig_ctrl, changed2) = self.update_instance_group_controller(ig)
if changed2:
print("Set controller group {} on {}.".format(self.controller, self.queuename))
try:
(instances, changed3) = self.add_instances_to_group(ig)
(instances, changed2) = self.add_instances_to_group(ig)
for i in instances:
print("Added instance {} to {}".format(i.hostname, ig.name))
except InstanceNotFound as e:
self.instance_not_found_err = e
if any([changed1, changed2, changed3]):
if changed1 or changed2:
print('(changed: True)')
@@ -117,7 +96,6 @@ class Command(BaseCommand):
parser.add_argument(
'--hostnames', dest='hostnames', type=str, help='Comma-Delimited Hosts to add to the Queue (will not remove already assigned instances)'
)
parser.add_argument('--controller', dest='controller', type=str, default='', help='The controlling group (makes this an isolated group)')
parser.add_argument(
'--instance_percent', dest='instance_percent', type=int, default=0, help='The percentage of active instances that will be assigned to this group'
),
@@ -133,14 +111,13 @@ class Command(BaseCommand):
queuename = options.get('queuename')
if not queuename:
raise CommandError("Specify `--queuename` to use this command.")
ctrl = options.get('controller')
inst_per = options.get('instance_percent')
instance_min = options.get('instance_minimum')
hostname_list = []
if options.get('hostnames'):
hostname_list = options.get('hostnames').split(",")
rq = RegisterQueue(queuename, ctrl, inst_per, instance_min, hostname_list)
rq = RegisterQueue(queuename, inst_per, instance_min, hostname_list)
rq.register()
if rq.instance_not_found_err:
print(rq.instance_not_found_err.message)

View File

@@ -10,7 +10,6 @@ from datetime import datetime as dt
from django.core.management.base import BaseCommand
from django.db import connection
from django.db.models import Q
from django.db.migrations.executor import MigrationExecutor
from awx.main.analytics.broadcast_websocket import (
@@ -140,7 +139,7 @@ class Command(BaseCommand):
data[family.name] = family.samples[0].value
me = Instance.objects.me()
hostnames = [i.hostname for i in Instance.objects.exclude(Q(hostname=me.hostname) | Q(rampart_groups__controller__isnull=False))]
hostnames = [i.hostname for i in Instance.objects.exclude(hostname=me.hostname)]
host_stats = Command.get_connection_status(me, hostnames, data)
lines = Command._format_lines(host_stats)

View File

@@ -1,47 +0,0 @@
import os
import shutil
import sys
import tempfile
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
import ansible_runner
from awx.main.isolated.manager import set_pythonpath
class Command(BaseCommand):
"""Tests SSH connectivity between a controller and target isolated node"""
help = 'Tests SSH connectivity between a controller and target isolated node'
def add_arguments(self, parser):
parser.add_argument('--hostname', dest='hostname', type=str, help='Hostname of an isolated node')
def handle(self, *args, **options):
hostname = options.get('hostname')
if not hostname:
raise CommandError("--hostname is a required argument")
try:
path = tempfile.mkdtemp(prefix='awx_isolated_ssh', dir=settings.AWX_ISOLATION_BASE_PATH)
ssh_key = None
if all([getattr(settings, 'AWX_ISOLATED_KEY_GENERATION', False) is True, getattr(settings, 'AWX_ISOLATED_PRIVATE_KEY', None)]):
ssh_key = settings.AWX_ISOLATED_PRIVATE_KEY
env = dict(os.environ.items())
env['ANSIBLE_HOST_KEY_CHECKING'] = str(settings.AWX_ISOLATED_HOST_KEY_CHECKING)
set_pythonpath(os.path.join(settings.ANSIBLE_VENV_PATH, 'lib'), env)
res = ansible_runner.interface.run(
private_data_dir=path,
host_pattern='all',
inventory='{} ansible_ssh_user={}'.format(hostname, settings.AWX_ISOLATED_USERNAME),
module='shell',
module_args='ansible-runner --version',
envvars=env,
verbosity=3,
ssh_key=ssh_key,
)
sys.exit(res.rc)
finally:
shutil.rmtree(path)

View File

@@ -11,11 +11,16 @@ from django.conf import settings
from awx.main.utils.filters import SmartFilter
from awx.main.utils.pglock import advisory_lock
___all__ = ['HostManager', 'InstanceManager', 'InstanceGroupManager']
___all__ = ['HostManager', 'InstanceManager', 'InstanceGroupManager', 'DeferJobCreatedManager']
logger = logging.getLogger('awx.main.managers')
class DeferJobCreatedManager(models.Manager):
def get_queryset(self):
return super(DeferJobCreatedManager, self).get_queryset().defer('job_created')
class HostManager(models.Manager):
"""Custom manager class for Hosts model."""
@@ -28,7 +33,7 @@ class HostManager(models.Manager):
- Only consider results that are unique
- Return the count of this query
"""
return self.order_by().exclude(inventory_sources__source='tower').values('name').distinct().count()
return self.order_by().exclude(inventory_sources__source='controller').values('name').distinct().count()
def org_active_count(self, org_id):
"""Return count of active, unique hosts used by an organization.
@@ -40,7 +45,7 @@ class HostManager(models.Manager):
- Only consider results that are unique
- Return the count of this query
"""
return self.order_by().exclude(inventory_sources__source='tower').filter(inventory__organization=org_id).values('name').distinct().count()
return self.order_by().exclude(inventory_sources__source='controller').filter(inventory__organization=org_id).values('name').distinct().count()
def get_queryset(self):
"""When the parent instance of the host query set has a `kind=smart` and a `host_filter`
@@ -141,8 +146,8 @@ class InstanceManager(models.Manager):
pod_ip = os.environ.get('MY_POD_IP')
registered = self.register(ip_address=pod_ip)
is_container_group = settings.IS_K8S
RegisterQueue('tower', None, 100, 0, [], is_container_group).register()
RegisterQueue(settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME, 100, 0, [], is_container_group=False).register()
RegisterQueue(settings.DEFAULT_EXECUTION_QUEUE_NAME, 100, 0, [], is_container_group=True).register()
return registered
else:
return (False, self.me())
@@ -151,13 +156,6 @@ class InstanceManager(models.Manager):
"""Return count of active Tower nodes for licensing."""
return self.all().count()
def my_role(self):
# NOTE: TODO: Likely to repurpose this once standalone ramparts are a thing
return "tower"
def all_non_isolated(self):
return self.exclude(rampart_groups__controller__isnull=False)
class InstanceGroupManager(models.Manager):
"""A custom manager class for the Instance model.

View File

@@ -7,6 +7,7 @@ import time
import urllib.parse
from django.conf import settings
from django.contrib.auth import logout
from django.contrib.auth.models import User
from django.db.migrations.executor import MigrationExecutor
from django.db import connection
@@ -45,7 +46,7 @@ class TimingMiddleware(threading.local, MiddlewareMixin):
response['X-API-Total-Time'] = '%0.3fs' % total_time
if settings.AWX_REQUEST_PROFILE:
response['X-API-Profile-File'] = self.prof.stop()
perf_logger.info(
perf_logger.debug(
f'request: {request}, response_time: {response["X-API-Total-Time"]}',
extra=dict(python_objects=dict(request=request, response=response, X_API_TOTAL_TIME=response["X-API-Total-Time"])),
)
@@ -71,6 +72,21 @@ class SessionTimeoutMiddleware(MiddlewareMixin):
return response
class DisableLocalAuthMiddleware(MiddlewareMixin):
"""
Respects the presence of the DISABLE_LOCAL_AUTH setting and forces
local-only users to logout when they make a request.
"""
def process_request(self, request):
if settings.DISABLE_LOCAL_AUTH:
user = request.user
if not user.pk:
return
if not (user.profile.ldap_dn or user.social_auth.exists() or user.enterprise_auth.exists()):
logout(request)
def _customize_graph():
from awx.main.models import Instance, Schedule, UnifiedJobTemplate

View File

@@ -2,12 +2,8 @@
# Python
from __future__ import unicode_literals
# Django
from django.db import migrations, models
# AWX
from awx.main.migrations import ActivityStreamDisabledMigration
import awx.main.fields
class Migration(ActivityStreamDisabledMigration):

View File

@@ -1,10 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# AWX
from awx.main.migrations import _migration_utils as migration_utils
from awx.main.migrations import _credentialtypes as credentialtypes
from django.db import migrations, models

View File

@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
from awx.main.migrations import ActivityStreamDisabledMigration

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
# Django
from django.db import migrations, models
from django.db import migrations
# AWX
from awx.main.migrations import _migration_utils as migration_utils

View File

@@ -2,7 +2,6 @@
# Generated by Django 1.11.7 on 2017-12-11 16:40
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion

View File

@@ -3,8 +3,7 @@
from __future__ import unicode_literals
import awx.main.fields
from django.conf import settings
from django.db import migrations, models
from django.db import migrations
import django.db.models.deletion

View File

@@ -2,10 +2,7 @@
# Generated by Django 1.11.7 on 2018-02-27 17:58
from __future__ import unicode_literals
import awx.main.fields
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations
# TODO: Squash all of these migrations with '0024_v330_add_oauth_activity_stream_registrar'

View File

@@ -4,7 +4,7 @@ from __future__ import unicode_literals
# AWX
from awx.main.migrations import _credentialtypes as credentialtypes
from django.db import migrations, models
from django.db import migrations
class Migration(migrations.Migration):

View File

@@ -2,8 +2,6 @@
# Generated by Django 1.11.11 on 2018-03-16 20:25
from __future__ import unicode_literals
import awx.main.fields
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion

View File

@@ -4,9 +4,7 @@ from __future__ import unicode_literals
import awx.main.fields
import awx.main.models.activity_stream
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations
class Migration(migrations.Migration):

View File

@@ -2,10 +2,7 @@
# Generated by Django 1.11.11 on 2018-05-23 20:17
from __future__ import unicode_literals
import awx.main.fields
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):

View File

@@ -10,7 +10,7 @@ from awx.main.utils.common import set_current_apps
def migrate_to_static_inputs(apps, schema_editor):
set_current_apps(apps)
CredentialType.setup_tower_managed_defaults()
CredentialType.setup_tower_managed_defaults(apps)
class Migration(migrations.Migration):

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