Compare commits

..

827 Commits
1.0.1 ... 1.0.3

Author SHA1 Message Date
Ryan Petrello
ed1bacdc08 Merge pull request #1090 from ryanpetrello/awx-ansible-overview
add documentation for how awx uses/interacts with ansible
2018-02-02 08:44:11 -05:00
Jake McDermott
f39fa35d86 Merge pull request #1103 from mabashian/1091-status-icons
Tweaked smart status icon styling to prevent overlap with action buttons
2018-02-01 23:03:37 -05:00
Matthew Jones
9266444b19 Merge pull request #1117 from ryanpetrello/fatal-celery-reload
run the celery reload in a shell so the uwsgi hook isn't fatal on fail
2018-02-01 22:39:00 -05:00
Ryan Petrello
35230eded1 run the celery reload in a shell so the uwsgi hook isn't fatal on fail 2018-02-01 22:32:08 -05:00
Jake McDermott
ecacf64c28 Merge pull request #1105 from mabashian/1023-activity-stream-inv-link
Fixed inventory links in activity stream
2018-02-01 18:23:54 -05:00
Jake McDermott
d01e6ab8b6 Merge pull request #1106 from mabashian/1014-team-link-user-permissions
Fixed team links in users permissions tab
2018-02-01 18:23:00 -05:00
Jake McDermott
5653b47aa3 Merge pull request #1112 from mabashian/994-empty-list-text
Updated empty list text
2018-02-01 18:22:11 -05:00
Ryan Petrello
7bc3d85913 Merge pull request #1114 from ryanpetrello/fix-dateutil-bug
work around a bug in dateutil that incorrectly parses Z dates
2018-02-01 16:06:13 -05:00
Ryan Petrello
0a8df7fde2 work around a bug in dateutil that incorrectly parses Z dates
related: https://github.com/dateutil/dateutil/issues/349
2018-02-01 15:51:59 -05:00
Ryan Petrello
b39269c4c2 Merge pull request #1113 from ryanpetrello/fix-schedule-related
fix a bug which can break the schedules list endpoint
2018-02-01 14:50:37 -05:00
Chris Meyers
09981c0020 Merge pull request #1107 from ansible/docs-saml2
Extend saml docs to include new fields added
2018-02-01 14:33:51 -05:00
Ryan Petrello
81bdbef785 fix a bug which can break the schedules list endpoint
see: https://github.com/ansible/ansible-tower/issues/7881
related: https://github.com/ansible/awx/pull/1095
2018-02-01 14:30:56 -05:00
Chris Meyers
3c541a4695 Merge pull request #1111 from ansible/jakemcdermott-update-ldap-docs
Updates to ldap documentation
2018-02-01 14:30:23 -05:00
Jake McDermott
5a1ae9b816 Update ldap.md 2018-02-01 13:57:07 -05:00
mabashian
8c261892ee Updated empty list text 2018-02-01 13:54:33 -05:00
Matthew Jones
b89d4349c0 Merge pull request #1080 from Xiol/feat-projects-vol
Allow AWX projects directory to be a volume
2018-02-01 13:17:34 -05:00
Jake McDermott
3e98363811 Merge pull request #1104 from ansible/doc-formatting
Update saml.md
2018-02-01 11:55:46 -05:00
Chris Meyers
f24289b2ba Extend saml docs to include new fields added 2018-02-01 11:27:01 -05:00
mabashian
9170c557a7 Fixed team links in users permissions tab 2018-02-01 11:23:51 -05:00
Chris Meyers
a47b403f8d Update saml.md 2018-02-01 11:05:08 -05:00
mabashian
83aa7bfac4 Fixed inventory links in activity stream 2018-02-01 11:04:16 -05:00
mabashian
db0b2e6cb6 Tweaked smart status icon styling to prevent overlap with action buttons 2018-02-01 10:44:08 -05:00
Ryan Petrello
f391b7ace4 Merge pull request #1095 from ryanpetrello/schedule-related-proj-inv
add related links to the inventory and project for a schedule
2018-01-31 15:53:13 -05:00
Ryan Petrello
008c9e4320 Merge pull request #1094 from ryanpetrello/leaky-mock
remove some leaky mock.patch() that were causing sporadic test failures
2018-01-31 15:52:58 -05:00
Ryan Petrello
8ddc1c61ef add related links to the inventory and project for a schedule
see: https://github.com/ansible/awx/issues/276
2018-01-31 15:18:11 -05:00
Ryan Petrello
0aa6c7b83f remove some leaky mock.patch() that were causing sporadic test failures 2018-01-31 15:12:59 -05:00
Jake McDermott
e43879d44e Merge pull request #1092 from dovshap/patch-1
Update INSTALL.md
2018-01-31 14:11:11 -05:00
Ryan Petrello
2a6f6111dc add documentation for how awx uses/interacts with ansible 2018-01-31 14:02:18 -05:00
dovshap
6b0659d63a Update INSTALL.md
fix bad link in contents
2018-01-31 11:00:03 -08:00
Shane McDonald
426e901cdf Merge pull request #1089 from KAMiKAZOW/patch-1
Fix CentOS typo in CONTRIBUTING.md
2018-01-30 21:11:10 -05:00
KAMiKAZOW
ac55f93cfb CentOS typo in CONTRIBUTING.md 2018-01-31 03:07:52 +01:00
Ryan Petrello
c32c3db35e Merge pull request #1086 from ryanpetrello/fix-enabled-sso-auth
fix a bug which causes /api/v2/auth/ to list disabled auth backends
2018-01-30 16:35:26 -05:00
Ryan Petrello
20a999f846 Merge pull request #1085 from ryanpetrello/fix-7876
fix a bug in custom venv support that breaks legacy `POST /api/v1/jobs`
2018-01-30 16:21:10 -05:00
Ryan Petrello
81af34fce3 fix a bug which causes /api/v2/auth/ to list disabled auth backends
see: https://github.com/ansible/awx/issues/1073
2018-01-30 16:20:29 -05:00
Ryan Petrello
8fed469975 fix a bug in custom venv support that breaks legacy POST /api/v1/jobs
see: https://github.com/ansible/ansible-tower/issues/7876
2018-01-30 15:29:11 -05:00
Dane Elwell
c6d4a62263 Allow AWX projects directory to be a volume
Signed-off-by: Dane Elwell <dane.elwell@ukfast.co.uk>
2018-01-30 09:49:44 +00:00
Ryan Petrello
a9b77eb706 Merge pull request #1066 from ryanpetrello/fix-schedules-without-inventories
fix a few bugs for scheduled jobs that run without inventories
2018-01-29 16:08:17 -05:00
Ryan Petrello
e642af82cc fix a few bugs for scheduled jobs that run without inventories
see: https://github.com/ansible/ansible-tower/issues/7865
see: https://github.com/ansible/ansible-tower/issues/7866
2018-01-29 15:15:57 -05:00
Ryan Petrello
b0a755d7b5 Merge pull request #1076 from ryanpetrello/rrule-until-changes
adhere to RFC5545 regarding UNTIL timezones
2018-01-29 13:31:17 -05:00
Ryan Petrello
6753f1ca35 adhere to RFC5545 regarding UNTIL timezones
If the "DTSTART" property is specified as a date with UTC time or a date with
local time and time zone reference, then the UNTIL rule part MUST be specified
as a date with UTC time.
2018-01-29 12:42:31 -05:00
Ryan Petrello
f8d9d5f51a Merge pull request #1067 from ryanpetrello/fix-7869
don't allow distant DTSTART values for schedules; it's slow
2018-01-29 12:00:36 -05:00
Wayne Witzel III
bad8c65321 Merge pull request #1074 from wwitzel3/devel
Load Celery inspector manually when needed
2018-01-29 12:00:24 -05:00
Ryan Petrello
6f0c937236 don't allow distant DTSTART values for schedules; it's slow
see: https://github.com/ansible/ansible-tower/issues/7869
2018-01-29 10:16:03 -05:00
Wayne Witzel III
55a616cba6 Load Celery inspector manually when needed 2018-01-29 14:57:03 +00:00
Shane McDonald
87365e5969 Merge pull request #1071 from jakemcdermott/set-selenium-container-image-tags
use selenium hub / node container image version '3.8.1-erbium'
2018-01-28 16:37:03 -05:00
Jake McDermott
7e829e3a9d use selenium hub / node container image version '3.8.1-erbium' 2018-01-28 16:05:29 -05:00
Shane McDonald
b8cba916a5 Merge pull request #1069 from tdgroot/develop-dockerfile_rsync
Add rsync to Dockerfile
2018-01-27 10:14:36 -05:00
Timon de Groot
dc96a1730e Add rsync to Dockerfile 2018-01-27 11:54:51 +01:00
Matthew Jones
d4983ea10d Merge pull request #856 from ewjoachim/docker-compose-491
Fixes #491: Adding Docker Compose installer
2018-01-26 08:33:40 -05:00
Joachim Jablon
209bdd00a1 related #491 Bacpkort #1007 2018-01-26 07:09:28 +01:00
Joachim Jablon
c4efbd62bc related #491 Docker Compose installer
Signed-off-by: Joachim Jablon <ewjoachim@gmail.com>
2018-01-26 07:09:28 +01:00
Joachim Jablon
287a3bc8d4 related #491 Documentation for Docker Compose
Signed-off-by: Joachim Jablon <ewjoachim@gmail.com>
2018-01-26 07:09:28 +01:00
Joachim Jablon
9fefc26528 related #491 Split local_docker docker into 2 task files
Signed-off-by: Joachim Jablon <ewjoachim@gmail.com>
2018-01-26 07:09:28 +01:00
Ryan Petrello
e2d4ef31fd Merge pull request #1061 from ryanpetrello/fix-1042
fix a unicode bug in the stdout endpoint when ?content_encoding=base64
2018-01-25 16:07:21 -05:00
Ryan Petrello
a15e257b9e fix a unicode bug in the stdout endpoint when ?content_encoding=base64
see: https://github.com/ansible/awx/issues/1042
2018-01-25 15:53:43 -05:00
Ryan Petrello
a56370fed5 Merge pull request #1059 from ryanpetrello/reload-celery
reload the entire celery worker pool when uwsgi reloads the Python app
2018-01-25 15:12:22 -05:00
Ryan Petrello
e7ed4811c1 reload the entire celery worker pool when uwsgi reloads the Python app
this is for the development environment only; when uwsgi notices a code
change, it automatically reloads the uwsgi workers; this patch includes
a hook that sends `SIGHUP` to the celery process, causing it to spawn
a new set of workers as well
2018-01-25 14:59:40 -05:00
Ryan Petrello
9860b38438 Merge pull request #1055 from ryanpetrello/lazybaron
only import the redbaron library on-demand
2018-01-25 13:09:58 -05:00
Ryan Petrello
ef80ecd3b6 only import the redbaron library on-demand
redbaron is a library we use to facilitate parsing local settings files;
at _import_ time it generates a parse tree and caches it to disk at
`/tmp`; this process is _really time consuming, and only necessary if
we're actually *using* the library

right now, we're importing this library and paying the penalty
_every_ time we load the awx application
2018-01-25 10:23:44 -05:00
Ryan Petrello
50290a9063 Merge pull request #1024 from ryanpetrello/fix-710-schedule-timezone
support TZID= in schedule rrules
2018-01-25 10:14:57 -05:00
Shane McDonald
fefa4a8bf4 Merge pull request #1049 from ansible/jakemcdermott-fix-1045
add minimum git version to install guide
2018-01-24 15:40:10 -05:00
Jake McDermott
546f88c74d add minimum git version 2018-01-24 15:12:58 -05:00
Jake McDermott
afa1fb489c Merge pull request #1044 from jakemcdermott/fix-948
bump templates form credential_types page limit
2018-01-24 09:35:43 -05:00
Jake McDermott
3571abb42b bump templates form credential_types page limit 2018-01-23 18:28:59 -05:00
Jake McDermott
21425db889 Merge pull request #1041 from jakemcdermott/fix-multicred-bugs
Fix multicred bugs
2018-01-23 13:34:35 -05:00
Jake McDermott
cc64657749 use correct handle for modal tag deselect 2018-01-23 10:32:13 -05:00
Jake McDermott
7300c2ccc1 fix unexpected deselect when selecting no-vault-id vault credentials 2018-01-23 10:19:19 -05:00
Jake McDermott
7c596039c5 fix modal exit button close 2018-01-23 09:39:59 -05:00
Ryan Petrello
9857c8272e add more tests for weird timezone/DST boundaries in schedules
see: https://github.com/ansible/awx/pull/1024
2018-01-22 14:57:57 -05:00
Shane McDonald
797169317c Merge pull request #1037 from shanemcd/devel
Use newer version of git in dev image
2018-01-22 14:43:09 -05:00
Shane McDonald
67c6591f6f Use newer version of git in dev image
More fallout from #982
2018-01-22 13:57:44 -05:00
Ryan Petrello
15906b7e3c support TZID= in schedule rrules
this commit allows schedule `rrule` strings to include local timezone
information via TZID=NNNNN; occurrences are _generated_ in the local
time specific by the user (or UTC, if e.g., DTSTART:YYYYMMDDTHHMMSSZ)
while Schedule.next_run, Schedule.dtstart, and Schedule.dtend will be
stored in the UTC equivalent (i.e., the scheduler will still do math on
"what to run next" based on UTC datetimes).

in addition to this change, there is now a new API endpoint,
`/api/v2/schedules/preview/`, which takes an rrule and shows the next
10 occurrences in local and UTC time.

see: https://github.com/ansible/ansible-tower/issues/823
related: https://github.com/dateutil/dateutil/issues/614
2018-01-22 11:50:00 -05:00
Ryan Petrello
fdd2b84804 Merge pull request #1036 from ryanpetrello/fix-955
fix a bug that breaks workflows w/ a survey password + inventory sync
2018-01-22 10:55:51 -05:00
Ryan Petrello
ac3f7d0fac fix a bug that breaks workflows w/ a survey password + inventory sync
prior versions of awx did not raise an exception for this scenario
- they simply ignored kwargs that they couldn't accept.  this change is
a sort of middle ground - it ignores them, but gives a clue in the logs
as to why

see: https://github.com/ansible/awx/issues/955
related: https://github.com/ansible/awx/pull/803
2018-01-22 09:41:30 -05:00
Shane McDonald
09d63b4883 Merge pull request #1029 from jakemcdermott/fix-navbar
fix navbar / breadcrumb issue
2018-01-19 13:54:56 -05:00
Jake McDermott
b96e33ea50 fix navbar / breadcrumb issue 2018-01-19 13:52:11 -05:00
Matthew Jones
71d23e8c81 Merge pull request #1007 from wallnerryan/alternate-dns-servers
support dns servers: fixes https://github.com/ansible/awx/issues/1004
2018-01-19 08:58:29 -05:00
Ryan Petrello
073feb74cb Merge pull request #1015 from ryanpetrello/fix-980
fix another bug that breaks the JT callback process
2018-01-18 14:26:48 -05:00
Ryan Petrello
43f19cc94b fix another bug that breaks the JT callback process
see: https://github.com/ansible/awx/issues/980
related: 17cd0595d7
2018-01-18 13:17:06 -05:00
Ryan Petrello
ef312f0030 Merge pull request #1011 from ryanpetrello/fix-1010
don't require an IRC password in the notification UI
2018-01-18 12:55:57 -05:00
Christian Adams
d0fec0f19c Merge pull request #1013 from rooftopcellist/rdb_docs
added RDB info to docs
2018-01-18 12:33:00 -05:00
adamscmRH
1e14221625 added RDB info to docs 2018-01-18 11:48:26 -05:00
Matthew Jones
b6a901ac51 Merge pull request #1012 from wwitzel3/devel
first-parent requires git >= 1.8.4
2018-01-18 11:36:33 -05:00
Wayne Witzel III
1af0ee2f8c first-parent requires git >= 1.8.4 2018-01-18 16:12:23 +00:00
Ryan Petrello
b62ac6fbe4 Merge pull request #1001 from ryanpetrello/fix-7852
refactor credential injection for builtin types
2018-01-18 10:49:03 -05:00
Ryan Petrello
e5aaeedc43 don't require an IRC password in the notification UI
see: https://github.com/ansible/awx/issues/1010
2018-01-18 09:14:22 -05:00
Wayne Witzel III
fc5c5400cd Merge pull request #1003 from wwitzel3/devel
Fix notification_data attempting to access name property of an int
2018-01-18 08:55:50 -05:00
Wayne Witzel III
95bead2bb2 Extend notification_data test 2018-01-18 13:30:12 +00:00
Ryan Wallner
bcbda23aee support dns servers 2018-01-18 07:46:09 -05:00
Jake McDermott
5a21783013 Merge pull request #976 from jakemcdermott/multivault-templates-form
multivault select for templates form
2018-01-17 23:20:44 -05:00
Jake McDermott
e33604de71 show credential kind icon on credential tags 2018-01-17 23:07:34 -05:00
Jake McDermott
c50c63a9ff default to machine credential type 2018-01-17 23:07:23 -05:00
Jake McDermott
916d91cbc7 use updated credentials endpoint 2018-01-17 23:07:10 -05:00
Jake McDermott
79bd8b2c72 show vault id 2018-01-17 22:02:54 -05:00
Jake McDermott
5939116b0a update e2e and smoke tests for multivault select 2018-01-17 22:02:43 -05:00
Jake McDermott
6759e60428 add working multivault select for templates form 2018-01-17 22:02:30 -05:00
Jake McDermott
ef8af79700 load multiselect list when vault kind is selected 2018-01-17 22:02:16 -05:00
Ryan Petrello
dbb4d2b011 refactor credential injection for builtin types
this cleanups up a _lot_ of code duplication that we have for builtin
credential types. it will allow customers to setup custom inventory
sources that utilize builtin credential types (e.g., a custom inventory
script that could use an AzureRM credential)

see: https://github.com/ansible/ansible-tower/issues/7852
2018-01-17 16:50:28 -05:00
Wayne Witzel III
4a28065dbb Fix notification_data attempting to access name property of an int 2018-01-17 21:46:49 +00:00
Ryan Petrello
5387846cbb Merge pull request #992 from ryanpetrello/optimize-output-event-filter
optimize OutputEventFilter for large stdout streams
2018-01-17 14:24:15 -05:00
Ryan Petrello
6b247f1f24 Merge pull request #1000 from ryanpetrello/fix-7853
fix a minor unicode handling bug in project names
2018-01-17 14:15:15 -05:00
Ryan Petrello
838b793704 fix a minor unicode handling bug in project names
see: https://github.com/ansible/ansible-tower/issues/7853
2018-01-17 13:37:06 -05:00
Ryan Petrello
3cb8c98a41 Merge pull request #998 from ryanpetrello/fix-980
fix a bug which broke the callback plugin launch process
2018-01-17 12:12:05 -05:00
Ryan Petrello
18f254fc28 Merge pull request #769 from rbywater/feature/cloudformssuffix
Add ability to append suffix to host names for Cloudforms Inventory
2018-01-17 11:43:10 -05:00
Michael Abashian
9c6c6ce816 Merge pull request #990 from mabashian/975-delete-template
Fixed delete on templates list
2018-01-17 11:40:42 -05:00
Chris Meyers
6699be95bf Merge pull request #995 from chrismeyersfsu/improvement-fact_cache_log_job
add job_id to fact cache log output
2018-01-17 11:30:57 -05:00
Ryan Petrello
17cd0595d7 fix a bug which broke the callback plugin launch process
see: https://github.com/ansible/awx/issues/980
2018-01-17 11:28:13 -05:00
Chris Meyers
0402064c0f expose ansible_facts_modified 2018-01-17 10:28:34 -05:00
Chris Meyers
e33265e12c add job_id to fact cache log output 2018-01-17 10:19:27 -05:00
Richard Bywater
b8c76301de Add validation to ensure leading fullstop for suffix 2018-01-17 13:20:59 +13:00
Ryan Petrello
51f7907a01 optimize OutputEventFilter for large stdout streams
update our event data search algorithm to be a bit lazier in event data
discovery; this drastically improves processing speeds for stdout >5MB

see: https://github.com/ansible/awx/issues/417
2018-01-16 14:41:35 -05:00
jlmitch5
1a98cedc0f Merge pull request #993 from ansible/jlmitch5-patch-1
update css so that scroll bar doesn't take padding from main content area
2018-01-16 14:28:14 -05:00
jlmitch5
db974d4fd4 update css so that scroll bar doesn't take padding from main content area 2018-01-16 14:22:08 -05:00
mabashian
d6e663eff0 Fixed delete on templates list 2018-01-16 08:36:38 -05:00
Christian Adams
ccb40c8c68 Merge pull request #986 from rooftopcellist/xtra_vars
extends JT xtra var error msg
2018-01-16 00:58:59 -05:00
Ryan Petrello
6eb04de1a7 Merge pull request #978 from ryanpetrello/fix-7841
fix a minor bug in the JT launch related to support for zero credentials
2018-01-15 20:35:28 -05:00
Shane McDonald
cad5c5e79a Merge pull request #987 from shanemcd/devel
Fix sdist builder image
2018-01-15 20:25:16 -05:00
Shane McDonald
97472cb91b Fix sdist builder image
Fallout from https://github.com/ansible/awx/pull/982
2018-01-15 15:39:48 -05:00
adamscmRH
0c63ea0052 extends JT xtra var error msg 2018-01-15 15:05:03 -05:00
Chris Meyers
2b1d2b2976 Merge pull request #805 from chrismeyersfsu/feature-saml_import_attr
allow for saml attributes to define team and org
2018-01-15 11:57:05 -05:00
Shane McDonald
7d51b1cb9d Merge pull request #982 from shanemcd/devel
Use first parent commit when determining version from tags
2018-01-15 11:04:23 -05:00
Shane McDonald
52e531625c Use first parent commit when determining version from tags
We were having issues where an older tag was being outputed from `git describe`.

From the man page:

Follow only the first parent commit upon seeing a merge commit. This is useful when you wish to not match tags on branches merged in the history of the target commit.
2018-01-15 11:01:47 -05:00
Richard Bywater
b5db652050 Clarify that leading fullstop needed 2018-01-14 14:05:34 +13:00
Jake McDermott
e699402115 Merge pull request #979 from mabashian/template-list-actions
Added old schedule/copy logic to template list
2018-01-12 20:19:31 -05:00
mabashian
d012f5cd99 Added old schedule/copy logic to template list until it can be refactored 2018-01-12 12:23:29 -05:00
Ryan Petrello
4a2ca20b60 fix a minor bug in the JT launch related to support for zero credentials
see: https://github.com/ansible/ansible-tower/issues/7841
2018-01-12 11:37:33 -05:00
Chris Meyers
e49dfd6ee2 only run saml pipeline if saml social auth
* Do not trigger saml social auth pipeline methods if the user logging
in was not created by the saml social auth backend.
2018-01-11 16:20:49 -05:00
Jake McDermott
fb414802fa Merge pull request #970 from ansible/smoketest-fixes-for-lists
update test selector for add button dropdown arrow
2018-01-11 16:13:51 -05:00
Michael Abashian
00f400e839 Merge pull request #971 from mabashian/892-delete-inv-src
Fixed a few straggling success/error promises and replaced with then/catch
2018-01-11 14:51:29 -05:00
Chris Meyers
234e33df0e Merge pull request #959 from chrismeyersfsu/feature-multiple_ldap_servers
implement multiple ldap servers
2018-01-11 14:45:38 -05:00
mabashian
f9b0a3121f Fixed a few straggling success/error promises and replaced with then/catch 2018-01-11 13:59:46 -05:00
Jake McDermott
0afdca3674 update test selector for add button dropdown arrow 2018-01-11 13:48:03 -05:00
Matthew Jones
03cef6fea3 Merge pull request #969 from matburt/default_x_forwarded_for
Add X-Forwarded-For as a default source of remote host headers
2018-01-11 12:01:27 -05:00
Matthew Jones
7dc0fce1aa Use x-forwarded-for by default in openshift and kubernetes 2018-01-11 12:00:01 -05:00
Matthew Jones
648d27f28d Merge pull request #909 from scottp-dpaw/add-openshift-hint
Add REMOTE_HOST_HEADERS override to OpenShift template
2018-01-11 11:56:05 -05:00
jlmitch5
5a5e5bc121 Merge pull request #898 from jlmitch5/newTemplateList
implementation for expanded template list
2018-01-11 11:23:56 -05:00
John Mitchell
aea37654e2 updated template list to using new components 2018-01-11 11:20:12 -05:00
Chris Meyers
2ed97aeb0c implement multiple ldap servers 2018-01-11 09:03:14 -05:00
Ryan Petrello
9431b0b6ff Merge pull request #962 from ryanpetrello/fix-7843
fix a unicode handling bug
2018-01-10 18:17:58 -05:00
Ryan Petrello
a5007ccd41 fix a unicode handling bug
see: https://github.com/ansible/ansible-tower/issues/7843
related: https://github.com/ansible/awx/pull/807
2018-01-10 15:56:31 -05:00
Michael Abashian
81fc4219ae Merge pull request #957 from mabashian/860-facts
Fixed display of host facts
2018-01-10 15:02:23 -05:00
Ryan Petrello
c3c4d79890 Merge pull request #958 from ryanpetrello/multivenv
add an example for custom virtualenv setup in containers
2018-01-10 14:24:42 -05:00
Ryan Petrello
b01b229fea add an example for custom virtualenv setup in containers 2018-01-10 13:48:55 -05:00
mabashian
984b7e066d Fixed display of host facts 2018-01-10 13:18:38 -05:00
Matthew Jones
67d927121d Merge pull request #940 from ryanpetrello/multivenv
implement support for per-playbook/project/org virtualenvs
2018-01-10 12:15:38 -05:00
Matthew Jones
ae06cff991 Merge pull request #938 from ansible/kubernetes_install_support
Kubernetes install support
2018-01-10 09:57:33 -05:00
Matthew Jones
7ea6d7bf4d Clean up documentation for kubernetes installer 2018-01-10 09:39:07 -05:00
Matthew Jones
fad4a549d0 Remove oc command usage from docker registry k8s reference 2018-01-10 09:38:00 -05:00
Matthew Jones
9365e477c5 Merge pull request #951 from ansible/remove_nodeport
Remove nodeport customization
2018-01-10 09:32:36 -05:00
Matthew Jones
d0b3cac72a Remove nodeport definition 2018-01-10 09:29:12 -05:00
Chris Meyers
de02138dfd spelling is hard 2018-01-10 09:26:11 -05:00
Matthew Jones
44f0b003fc Kubernetes install documentation 2018-01-10 09:25:59 -05:00
Matthew Jones
56aed597b2 Add initial support for kubernetes to the installer 2018-01-10 09:25:59 -05:00
Matthew Jones
f33ee03b98 Remove nodeport customization
This isn't strictly necessary for the Openshift routes and can
sometimes cause problems when the resource is already defined in openshift
2018-01-10 09:23:46 -05:00
Ryan Petrello
69a3b0def6 Merge pull request #946 from ryanpetrello/fix-7846
fix a handful of issues for playbooks that contain unicode
2018-01-10 09:16:40 -05:00
Matthew Jones
6504972d82 Merge pull request #741 from rbywater/bugfix/cloudformsinventory
Fix CloudForms enabled & id variable names - relates to #705
2018-01-10 00:22:58 -05:00
Ryan Petrello
4bb2b5768e properly compose stdout downloads that contain unicode 2018-01-09 23:52:02 -05:00
Ryan Petrello
c0a641ed52 properly handle unicode for isolated job buffers
from: https://docs.python.org/2/library/stringio.html#module-cStringIO
"Unlike the StringIO module, this module is not able to accept Unicode
strings that cannot be encoded as plain ASCII strings."

see: https://github.com/ansible/ansible-tower/issues/7846
2018-01-09 23:46:17 -05:00
Ryan Petrello
1e8c89f536 implement support for per-playbook/project/org virtualenvs
see: https://github.com/ansible/awx/issues/34
2018-01-09 22:47:01 -05:00
Shane McDonald
54d3412820 Merge pull request #942 from wwitzel3/devel
Update asgi-amqp requirement
2018-01-09 19:17:45 -05:00
Wayne Witzel III
1690938dfb Update asgi-amqp requirement 2018-01-09 23:54:30 +00:00
Chris Meyers
0a9d3d47b9 more efficiently determine saml team mapping 2018-01-09 12:16:07 -05:00
Ryan Petrello
2952b0a0fe Merge pull request #807 from AlanCoding/inv_update_name
Make inventory update name combination of inventory and source
2018-01-08 10:43:44 -05:00
Ryan Petrello
1d3e8f8b87 Merge pull request #831 from AlanCoding/field_names
Use Options models to consolidate field_names list
2018-01-08 10:36:16 -05:00
Ryan Petrello
97c040aaa1 Merge pull request #839 from AlanCoding/cache_settings_dict
Cache the global settings list, cProfile speedup
2018-01-08 10:35:00 -05:00
Ryan Petrello
818c95501a Merge pull request #920 from ryanpetrello/fix-914
add vault_id to launch endpoints default vault credentials
2018-01-08 10:31:31 -05:00
Chris Meyers
664bdec57f add documentation 2018-01-05 14:43:33 -05:00
Michael Abashian
92068930a6 Merge pull request #919 from ansible/jakemcdermott-add-dialog-slider-imports
add dialog and slider vendor imports
2018-01-05 08:48:11 -05:00
Chris Meyers
d07a946183 Merge pull request #921 from chrismeyersfsu/fix-handle_work_error-689
Fix handle_work_error()
2018-01-05 07:54:03 -05:00
Chris Meyers
9d58b15135 allow for saml attributes to define team and org
related to https://github.com/ansible/awx/issues/217

* Adds a configure tower in tower setting for users to configure a saml
attribute that tower will use to put users into teams and orgs.
2018-01-04 15:35:11 -05:00
Chris Meyers
a0038276a4 do not use a custom task exception
* Celery + json pickling do not handle custom Exceptions (and may never
do so). Mentioning of, if handling custom Exceptions then the code would
be susceptible to same arbitrary code execution that python pickle is
vulnerable to.
* So don't use custom Exceptions.
2018-01-04 15:30:52 -05:00
Chris Meyers
f0ff6ecb0a handle_work_error signature to work
* celery error callback signature isn't well defined. Thus, our error
callback signature is made to handle just about any call signature and
depend on only 1 attribute, id, existing.

See https://github.com/celery/celery/issues/3709
2018-01-04 15:23:13 -05:00
Ryan Petrello
60743d6ba6 add the vault_id to the response payload on the JT launch endpoint
see: https://github.com/ansible/awx/issues/914
2018-01-04 15:13:48 -05:00
Ryan Petrello
4707b5e020 Merge pull request #917 from ryanpetrello/more-stdout-event-polish
more stdout event polish
2018-01-04 14:54:46 -05:00
Jake McDermott
ed7d7fcf00 add dialog and slider vendor imports 2018-01-04 14:46:42 -05:00
Aaron Tan
6c2a7f3782 Merge pull request #906 from jangsutsr/refactor_named_url_tests
Refactor named URL unit tests
2018-01-04 14:20:27 -05:00
Ryan Petrello
47875c5f9a Merge pull request #916 from ryanpetrello/memcache-fact-cache-size-warning
make the fact caching plugin fail more gracefully for large payloads
2018-01-04 13:06:29 -05:00
Ryan Petrello
f28f7c6184 refactor job event signal generation code 2018-01-04 12:50:12 -05:00
Ryan Petrello
1494c8395b update websockets docs to reflect new event groups 2018-01-04 11:40:15 -05:00
Ryan Petrello
2691e1d707 make the fact caching plugin fail more gracefully for large payloads
related: https://github.com/ansible/ansible/pull/34424
2018-01-04 11:33:47 -05:00
Ryan Petrello
6d413bd412 Merge pull request #833 from ryanpetrello/stdout-events
generalize stdout event processing to emit events for all job types
2018-01-04 11:28:52 -05:00
Aaron Tan
54bf7e13d8 Refactor named URL unit tests
The original tests set no longer works after Django 1.11 due to more
strict rules against dynamic model definition. The refactored tests set
aims at each existing model that apply named URL rules,  instead of
abstract general use cases, thus significantly improves maintainability
and readability.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2018-01-03 14:00:30 -05:00
Ryan Petrello
c6b6a3ad89 send and subcribe to summary events for all new events 2018-01-03 09:09:45 -05:00
Ryan Petrello
2bd656e61d calculate stdout download length using the ORM, not raw SQL 2018-01-03 09:09:44 -05:00
Ryan Petrello
35b8e40d3c remove deprecation from the stdout endpoint; text downloads still use it 2018-01-03 09:09:44 -05:00
Ryan Petrello
c4d901bf2c add functional API tests for deprecated job event stdout composition
see: https://github.com/ansible/awx/issues/200
2018-01-03 09:09:44 -05:00
Ryan Petrello
1369f72885 add new API endpoints and websocket emit for new job event types
see: https://github.com/ansible/awx/issues/200
2018-01-03 09:09:44 -05:00
Ryan Petrello
0b30e7907b change stdout composition to generate from job events on the fly
this approach totally removes the process of reading and writing stdout
files on the local file system at settings.JOBOUTPUT_ROOT when jobs are
run; now stdout content is only written on-demand as it's fetched for
the deprecated `stdout` endpoint

see: https://github.com/ansible/awx/issues/200
2018-01-03 09:09:43 -05:00
Ryan Petrello
fc94b3a943 generalize stdout event processing to emit events for *all* job types
* introduces three new models: `ProjectUpdateEvent`,
  `InventoryUpdateEvent`, and `SystemJobEvent`
* simplifies the stdout callback management in `tasks.py` - now _all_
  job run types capture and emit events to the callback receiver
* supports stdout reconstruction from events for stdout downloads for
  _all_ job types
* configures `ProjectUpdate` runs to configure the awx display callback
  (so we can capture real playbook events for `project_update.yml`)
* ProjectUpdate, InventoryUpdate, and SystemJob runs no longer write
  text blobs to the deprecated `main_unifiedjob.result_stdout_text` column

see: https://github.com/ansible/awx/issues/200
2018-01-03 09:09:42 -05:00
Scott Percival
fde9099198 Add REMOTE_HOST_HEADERS override to OpenShift template
Signed-off-by: Scott Percival <scott.percival@dbca.wa.gov.au>
2018-01-03 09:53:17 +08:00
Michael Abashian
815cd829e0 Merge pull request #872 from mabashian/865-jquery-ui-upgrade-bug
Fixed spinners after jquery-ui upgrade
2018-01-02 13:18:51 -05:00
Ryan Petrello
28c612ae9c Merge pull request #871 from AlanCoding/dirty_extra_data
Fix bug when creating system job schedule
2018-01-02 09:22:07 -05:00
Bill Nottingham
d6ed6a856d Merge pull request #845 from wenottingham/he-sees-you-when-you're-sleeping
Tweak collected information.
2017-12-21 13:52:11 -05:00
mabashian
706b370f7e Fixed spinners after jquery-ui upgrade 2017-12-20 16:02:53 -05:00
AlanCoding
80a2d10742 fix bug when creating system job schedule 2017-12-20 15:30:57 -05:00
Jake McDermott
f7259a1e78 Merge pull request #844 from jakemcdermott/fix-package-json-backmerge-issue
package.json updates / restore ui watch functionality
2017-12-18 17:03:03 -05:00
AlanCoding
08570fe785 make inventory update name combination of inventory and source 2017-12-18 16:21:39 -05:00
Jake McDermott
987cdc6802 Bump versions of angular-codemirror, jquery-ui, and moment 2017-12-18 16:21:29 -05:00
Alan Rominger
6e27294e2b Merge pull request #846 from AlanCoding/encrypt_on_save
Encrypt password answers on config save
2017-12-18 16:20:08 -05:00
AlanCoding
3439ba5f3b allow WFJT nodes without required variables 2017-12-18 12:03:40 -05:00
AlanCoding
c8e10adc96 fix bug saving extra_data and follow prompts rules
display_extra_vars was not taking a copy of the data before
acting on it - this causes a bug where the activity stream will
modify the existing object on the model. That leads to new data
not being accepted.

Also moved the processing of extra_data to prior to the accept
or ignore kwargs logic so that we pass the right (post-encryption)
form of the variables.
2017-12-18 10:50:22 -05:00
Christian Adams
7e261b5246 Merge pull request #847 from rooftopcellist/contributing_typos
Fixed Typos
2017-12-15 11:09:43 -05:00
AlanCoding
1e1839915d validate against unencrypted values at spawn point 2017-12-15 10:47:23 -05:00
AlanCoding
74bf058d62 encrypt password answers on config save 2017-12-15 07:48:55 -05:00
Matthew Jones
5ec537bad2 Merge pull request #843 from ansible/remove_old_tests
Removing old unused tests
2017-12-14 23:55:12 -05:00
Bill Nottingham
568901af74 Tweak collected information. 2017-12-14 19:22:18 -05:00
adamscmRH
c2e9926330 Fixed Typos 2017-12-14 16:13:04 -05:00
Jake McDermott
c4ccfa1b27 restoring ui watch functionality 2017-12-14 14:23:46 -05:00
Matthew Jones
478bcc0b07 Removing old unused tests 2017-12-14 11:34:43 -05:00
AlanCoding
0bb9c58e25 cache the global settings list, cProfile speedup 2017-12-14 11:29:30 -05:00
Alan Rominger
9c783aa0ce Merge pull request #804 from AlanCoding/active_count
simplify query for active_count
2017-12-14 10:47:12 -05:00
Alan Rominger
526391a072 Merge pull request #838 from AlanCoding/no_unicode_loop_2
Avoid slowdown generating smart_filter (alternative 2)
2017-12-14 10:23:31 -05:00
AlanCoding
98f8faa349 simplify query for active_count 2017-12-14 09:53:26 -05:00
AlanCoding
8a2a5b0fb1 avoid slowdown generating smart_filter 2017-12-14 09:39:39 -05:00
Jake McDermott
07cfa6cba5 Merge pull request #834 from AlanCoding/jump-the-start-line 2017-12-13 22:43:54 -05:00
AlanCoding
e188692acf use Options models to consolidate field_names list 2017-12-13 22:39:38 -05:00
Jake McDermott
ad70754b6a Merge pull request #832 from mabashian/linting-error-cleanup
Fixed linting/leftover merge errors
2017-12-13 19:46:02 -05:00
AlanCoding
9fb24f1a4c add hack to TimingMiddlWare for Shippable tests 2017-12-13 18:49:26 -05:00
mabashian
aefa30e1e9 Fixed linting/leftover merge errors 2017-12-13 18:28:52 -05:00
Alan Rominger
7eb2d86890 Merge pull request #749 from AlanCoding/detail_opt
Apply list view optimizations to detail view
2017-12-13 18:19:00 -05:00
Matthew Jones
2fb0144914 Add libcurl-devel to official image build 2017-12-13 16:14:55 -05:00
AlanCoding
e3a731bb9e apply listview optimizations to detail view 2017-12-13 16:09:37 -05:00
Ryan Petrello
451e9a7504 Merge pull request #826 from AlanCoding/322flake
flake8 fixes from removal of re-encrypt test
2017-12-13 15:23:41 -05:00
Ryan Petrello
8311acfba2 Merge pull request #825 from AlanCoding/towervars
Add back in support of towervars lost in merge
2017-12-13 15:19:47 -05:00
AlanCoding
77a1c405a6 flake8 fixes from removal of reencrypt test 2017-12-13 14:32:34 -05:00
AlanCoding
1b0bca8229 add back in support of towervars lost in merge 2017-12-13 14:30:11 -05:00
Ryan Petrello
bd91e8eb54 Merge pull request #824 from ryanpetrello/devel
fix a few tests caused by fallout between 3.2.2 bugs and 3.3 multicred
2017-12-13 14:10:39 -05:00
Ryan Petrello
ea4cd99003 fix a few tests caused by fallout between 3.2.2 bugs and 3.3 multicred 2017-12-13 14:02:25 -05:00
Shane McDonald
00ce244716 Merge pull request #822 from jakemcdermott/fix-merge-issues
fix merge issue with inventory source service
2017-12-13 13:32:13 -05:00
Jake McDermott
3b791609cd fix merge issue with inventory source service 2017-12-13 13:23:15 -05:00
Matthew Jones
a8d4eb7c1d Merge pull request #821 from ryanpetrello/devel
more test cleanup from 3.2.2 merge
2017-12-13 13:15:59 -05:00
Ryan Petrello
d35bfafcf5 more test cleanup from 3.2.2 merge 2017-12-13 13:14:22 -05:00
Ryan Petrello
9f8ef4d1e5 Merge pull request #820 from ryanpetrello/devel
fix a number of failing unit tests related to the 3.2.2 merge
2017-12-13 13:04:55 -05:00
Ryan Petrello
a978d094b4 fix a number of failing unit tests related to the 3.2.2 merge 2017-12-13 13:03:17 -05:00
Shane McDonald
47e422ba7a Merge pull request #819 from ansible/jakemcdermott-patch-1
fix arg name clash in hosts list controller
2017-12-13 13:02:47 -05:00
Jake McDermott
4b86815275 fix arg name clash in hosts list controller 2017-12-13 13:01:11 -05:00
Alan Rominger
6c1c850c5f Merge pull request #816 from AlanCoding/ints
use credential property that returns integers
2017-12-13 12:56:07 -05:00
AlanCoding
f4f1e0fd3c use credential property that returns integers 2017-12-13 12:54:32 -05:00
Matthew Jones
ca84e1c654 Merge pull request #817 from ansible/jakemcdermott-patch-1
fix missing comma in package.json
2017-12-13 12:48:16 -05:00
Jake McDermott
6b6e898882 fix missing comma in package.json 2017-12-13 12:45:26 -05:00
Matthew Jones
9dbcc5934e Merge remote-tracking branch 'tower/release_3.2.2' into devel 2017-12-13 12:25:47 -05:00
Ryan Petrello
05bec924e4 Merge pull request #795 from ryanpetrello/move-deprecated-stdout
move legacy UnifiedJob stdout data to a separate unmanaged model
2017-12-13 09:35:58 -05:00
Jake McDermott
40d1f2671f Merge pull request #811 from AlanCoding/i_wont_be_ignored
Fix bug creating inventory source schedules
2017-12-12 18:32:54 -05:00
Ryan Petrello
202161f090 move legacy UnifiedJob stdout data to a separate unmanaged model
This data often (in the case of inventory updates) represents large data
blobs (5+MB per job run).  Storing it on the polymorphic base class
table, `main_unifiedjob`, causes it to be automatically fetched on every
query (and every polymorphic join) against that table, which can result
in _very_ poor performance for awx across the board.  Django offers
`defer()`, but it's quite complicated to sprinkle this everywhere (and
easy to get wrong/introduce side effects related to our RBAC and usage
of polymorphism).

This change moves the field definition to a separate unmanaged model
(which references the same underlying `main_unifiedjob` table) and adds
a proxy for fetching the data as needed

see https://github.com/ansible/awx/issues/200
2017-12-12 18:16:19 -05:00
AlanCoding
7243f871b4 fix bug creating inventory source schedules 2017-12-12 17:49:51 -05:00
Jared Tabor
2c64a2ce63 Merge pull request #783 from jaredevantabor/notification-toggle
fixing url used for determining which notification to toggle on/off
2017-12-12 11:31:48 -08:00
Jared Tabor
86eb0353c5 fixing url used for determining which notification to toggle on/off
for #711
2017-12-12 11:07:21 -08:00
Matthew Jones
282290e151 Fix an issue referencing postgres port from openshift deployment 2017-12-12 10:52:02 -05:00
Alan Rominger
8d348f916b Merge pull request #794 from AlanCoding/hide_config_pass
Hide survey passwords in saved launch configs
2017-12-12 10:37:41 -05:00
AlanCoding
659d31324d hide survey passwords in saved launch configs 2017-12-12 09:35:46 -05:00
Ryan Petrello
1bc2d83403 Merge pull request #789 from ryanpetrello/multivault-acceptance
add some more tests and acceptance docs to wrap up multivault support
2017-12-11 20:35:27 -05:00
Ryan Petrello
8c90d36290 add some more tests and acceptance docs to wrap up multivault support
see: https://github.com/ansible/awx/issues/352
2017-12-11 16:56:02 -05:00
Greg Considine
fac7fd45f8 Merge pull request #614 from gconsidine/ui/fix/toggle-button-container
Adjust style of toggle button to accommodate text that exceeds 42px
2017-12-11 16:09:44 -05:00
Bill Nottingham
9be438a60a Merge pull request #788 from wenottingham/no-country-for-old-python
Don't bother checking for python 2.6 in the venv
2017-12-11 14:57:25 -05:00
Bill Nottingham
c62430c282 Drop python2.6 checks. 2017-12-11 13:59:00 -05:00
Alan Rominger
1be3c77ac6 Merge pull request #787 from AlanCoding/workflow_system_jobs
allow using SystemJobTemplates in workflows
2017-12-11 13:21:33 -05:00
Matthew Jones
34c206fab0 Bump psql-container pg version to 9.6 2017-12-11 12:01:28 -05:00
gconsidine
a2f64f1053 Adjust style of toggle button to accommodate text that exceeds 42px 2017-12-11 11:47:21 -05:00
Shane McDonald
334d47f3ab Pull updated translations 2017-12-11 09:42:06 -05:00
AlanCoding
4adfb9804e allow using SystemJobTemplates in workflows 2017-12-11 08:58:45 -05:00
Alan Rominger
64ac1ee238 Merge pull request #746 from AlanCoding/i_forgot
Intentionally forget start_args when job is done
2017-12-11 08:08:27 -05:00
AlanCoding
0bf06479d5 add migration to remove old start_args 2017-12-10 12:08:59 -05:00
AlanCoding
1f8cab4171 intentionally forget start_args when job is done 2017-12-10 12:08:54 -05:00
Jake McDermott
526bcc4a68 Merge pull request #785 from jakemcdermott/stored-xss-test-update
fix lint error and stabilize stored xss test case
2017-12-10 12:07:46 -05:00
Jake McDermott
9dcdf20fb0 stabilize template form stored xss test case 2017-12-10 11:41:41 -05:00
Jake McDermott
be0f66fd94 fix linting error in stored xss test 2017-12-10 11:39:13 -05:00
Alan Rominger
2135291f35 Merge pull request #740 from AlanCoding/configs_rebased5
Feature: saved launchtime configurations
2017-12-08 16:55:00 -05:00
AlanCoding
a9aae91634 generalize schedule prompts validation
This makes ScheduleSerializer behave same as WFJT nodes
Prevents providing job_type for workflow jobs, as example
2017-12-08 16:23:56 -05:00
Ryan Petrello
4724b6a3d6 Merge pull request #613 from ryanpetrello/release_3.2.2
change how we detect the current user at LDAP login to avoid a nuanced recursion error
2017-12-08 15:46:32 -05:00
Ryan Petrello
ce94ba4c83 change how we detect the current user to avoid a nuanced recursion error
see: https://github.com/ansible/ansible-tower/issues/7802
2017-12-08 15:35:47 -05:00
AlanCoding
905ff7dad7 fix bugs where ask_ var was checked on node 2017-12-08 13:57:33 -05:00
AlanCoding
e59a724efa fix bug that broke combining WFJT and node vars 2017-12-08 13:48:45 -05:00
AlanCoding
1c8217936d Bug fixes from integration ran on launchtime branch
Make error message for muti-vault validation more
consistent with historical message
2017-12-08 13:46:38 -05:00
AlanCoding
72a8854c27 Make ask_mapping a simple class property
from PR feedback of saved launchtime configurations
2017-12-08 13:45:23 -05:00
AlanCoding
98df442ced combine launch config and multi-cred migrations 2017-12-08 13:45:21 -05:00
AlanCoding
5ada021a6e Tweak validation to allow multiple vault credentials
support providing vault passwords based on id
include needed passwords in launch serializer defaults
2017-12-08 13:43:43 -05:00
AlanCoding
34a8e0a9b6 Feature: saved launchtime configurations
Consolidate prompts accept/reject logic in unified models
Break out accept/reject logic for variables
Surface new promptable fields on WFJT nodes, schedules

Make schedules and workflows accurately reject variables
  that are not allowed by the prompting
  rules or the survey rules on the template

Validate against unallowed extra_data in system job schedules
Prevent schedule or WFJT node POST/PATCH with unprompted data
Move system job days validation to new mechanism
Add new psuedo-field for WFJT node credential
Add validation for node related credentials
Add related config model to unified job
Use JobLaunchConfig model for launch RBAC check

Support credential overwrite behavior with multi-creds
  change modern manual launch to use merge behavior
Refactor JobLaunchSerializer, self.instance=None
Modularize job launch view to create "modern" data
Auto-create config object with every job
Add create schedule endpoint for jobs
2017-12-08 13:38:54 -05:00
Marliana Lara
cd8a4b4669 Merge pull request #645 from marshmalien/feature/retry_failed_hosts
Feature - Retry failed hosts
2017-12-07 12:54:11 -05:00
Ryan Petrello
0dc4fa975b Merge pull request #612 from ryanpetrello/release_3.2.2
fix a race condition in "host.last_job" when jobs are deleted
2017-12-06 13:43:45 -05:00
Ryan Petrello
1fb890f4eb fix a race condition in "host.last_job" when jobs are deleted
see: https://github.com/ansible/ansible-tower/issues/7815
2017-12-06 11:30:19 -05:00
Matthew Jones
7fc896e183 Merge pull request #774 from matburt/jupyter_for_devel
Adding jupyter notebook support to the AWX development environment
2017-12-06 09:49:07 -05:00
Matthew Jones
da0b686369 Adding jupyter notebook support to the AWX development environment
* Jupyter starts alongside the other awx services and is available on
  0.0.0.0:8888
* make target: make jupyter
* default settings in settings/development.py
* Added jupyter, matplotlib, numpy to dev dependencies
2017-12-05 23:46:18 -05:00
Matthew Jones
9488105381 Merge pull request #773 from shanemcd/devel
Add m2r to setup requirements file
2017-12-05 15:38:31 -05:00
Shane McDonald
ec14ae1930 Add m2r to setup requirements file
We `pip download` this file for offline installs. Automat lists this package as a setup_requires, but `pip download` doesn’t resolve these dependencies (distutils will attempt to install them via easy_install when setup.py is invoked).
2017-12-05 15:26:56 -05:00
Shane McDonald
15e8fd5eca Pull updated translations 2017-12-05 14:17:18 -05:00
Greg Considine
e1e225d6a0 Merge pull request #771 from gconsidine/ui/fix/input-replace-revert
Ui/fix/input replace revert
2017-12-05 13:43:32 -05:00
gconsidine
3ad174b15b Add e2e test case to verify revert/replace 2017-12-05 12:25:48 -05:00
gconsidine
b5644ed65b Fix replace/revert functionality on secret input fields 2017-12-05 10:39:15 -05:00
Ryan Petrello
06e751fea1 Merge pull request #611 from ryanpetrello/release_3.2.2
more unit tests for survey default handling
2017-12-05 09:18:48 -05:00
Ryan Petrello
fe93ef5488 more unit tests for survey default handling 2017-12-05 09:04:57 -05:00
Jake McDermott
13d84b8d35 Merge pull request #768 from tchia04/fix_typo_credential_types
Fix typo: Failed to get credential tpyes
2017-12-04 22:26:52 -05:00
Richard Bywater
9b05a41eec Add ability to append suffix to host names for Cloudforms Inventory
Allows for use of a suffix that will be appended to host names returned
from Cloudforms API if that suffix is not present.

For example with a suffix of 'example.org', the following results would
be shown for a particular Cloudforms host name:
someexample -> someexample.example.org
someexample.example.org -> someexample.example.org

The main use-case for this is, when one Inventory Source is returning
names that have a FQDN name whilst others are returning a shortname, to
ensure that the hosts in an inventory aren't effectively duplicated.
2017-12-05 14:47:33 +13:00
Tony Chia
9275b024de Update main.js
Changed "credential tpyes" to "credential types"
2017-12-04 16:27:46 -08:00
Jared Tabor
4f8d4994cf Merge pull request #765 from jaredevantabor/fix-764
Update error handling on host service after angular upgrade
2017-12-04 14:28:41 -08:00
Jared Tabor
a3144ee234 Update error handling on host service after angular upgrade 2017-12-04 13:52:34 -08:00
Alan Rominger
7fe22e9c53 Merge pull request #757 from AlanCoding/vault_cred_noop
allow no-op case for vault_credential
2017-12-04 16:01:00 -05:00
Alan Rominger
42d8368596 Merge pull request #763 from AlanCoding/remember_where_you_came_from
add AWX meta extra_vars for workflow + schedule
2017-12-04 15:52:30 -05:00
Ryan Petrello
2c12f1b66e Merge pull request #610 from ryanpetrello/faster-result-stdout-cleanup
don't fetch stdout when purging jobs - it's slow and causes OOMs
2017-12-04 15:41:16 -05:00
AlanCoding
eecf997856 add AWX meta extra_vars: WFJT + schedule 2017-12-04 15:33:05 -05:00
Ryan Petrello
33dedc88c8 don't fetch stdout when purging jobs - it's slow and causes OOMs
see: https://github.com/ansible/ansible-tower/issues/7751
2017-12-04 15:14:55 -05:00
Alan Rominger
759867c863 Merge pull request #609 from AlanCoding/more_encryption_tests
encryption tests around the contract with survey functionality
2017-12-04 14:20:30 -05:00
Alan Rominger
d4613d448c Merge pull request #608 from AlanCoding/empty_string_defaults
allow password default reuse with empty default
2017-12-04 14:19:32 -05:00
Matthew Jones
21bdea05a0 Merge pull request #762 from matburt/fix_pg_port
Make sure we define postgres port customization during install
2017-12-04 14:16:09 -05:00
AlanCoding
dbd68c5747 encryption tests around the contract with survey functionality 2017-12-04 11:45:07 -05:00
Matthew Jones
a3071c2a1f Make sure we define postgres port customization during install 2017-12-04 11:08:40 -05:00
AlanCoding
d23d7c422d allow password default reuse with empty default 2017-12-04 10:49:36 -05:00
Ryan Petrello
4b793dc58a Merge pull request #606 from ryanpetrello/test-7806
improve validation for empty default passwords
2017-12-04 10:19:06 -05:00
Ryan Petrello
112757e202 properly handle JT launch POST for required survey fields w/ no default
see: ansible/ansible-tower#7805
2017-12-04 09:45:21 -05:00
Ryan Petrello
12380fe1b1 add more tests for survey default encryption
see: https://github.com/ansible/ansible-tower/issues/7805
see: https://github.com/ansible/ansible-tower/issues/7806
see: https://github.com/ansible/ansible-tower/issues/7807
2017-12-04 09:45:14 -05:00
Matthew Jones
cf0cc2e2f2 Add system requirements to install docs 2017-12-04 07:56:34 -05:00
Ryan Petrello
b987b7daa0 Merge pull request #605 from ryanpetrello/release_3.2.2
fix another survey encryption-related bug
2017-12-01 17:30:43 -05:00
Ryan Petrello
6c7851b51f fix another survey encryption-related bug 2017-12-01 17:11:00 -05:00
Aaron Tan
1ff0591553 Merge pull request #603 from jangsutsr/fix-7737-1
Follow up fix #542
2017-12-01 16:07:14 -05:00
Aaron Tan
58ad214dcf Follow up fix #542
Relates
https://github.com/ansible/ansible-tower/issues/7737#issuecomment-348566452

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-12-01 15:58:33 -05:00
Ryan Petrello
a71cee9300 Merge pull request #604 from ryanpetrello/survey_spec_validation_refactor
refactor survey spec validation into a separate testable function
2017-12-01 15:44:07 -05:00
Ryan Petrello
1057b93570 refactor survey spec validation into a separate testable function 2017-12-01 15:34:07 -05:00
Alan Rominger
e0edfeac7c Merge pull request #602 from AlanCoding/clean_defaults
block user from entering encrypted as bare default
2017-12-01 14:54:42 -05:00
AlanCoding
47f45bf9b3 block user from entering encrypted as bare default 2017-12-01 14:44:06 -05:00
Ryan Petrello
8d162f9044 Merge pull request #601 from ryanpetrello/flake8-fixes
backport a few fixes from awx to address busted ci
2017-12-01 12:48:06 -05:00
AlanCoding
6269b43456 update tests to new Ansible core code 2017-12-01 12:31:56 -05:00
AlanCoding
67867cf0c8 flake8: comply with new E722 rule 2017-12-01 12:16:44 -05:00
Ryan Petrello
7538b4ce15 Merge pull request #600 from ryanpetrello/fix-7800-migration
upgrade survey encryption migration to work around an old survey bug
2017-12-01 12:13:18 -05:00
Ryan Petrello
e7918ad637 Merge pull request #752 from ryanpetrello/multivault
support specifying multiple vault IDs for a playbook run
2017-12-01 11:43:39 -05:00
Ryan Petrello
8c6a1e348d upgrade survey encryption migration to work around an old survey bug
see: https://github.com/ansible/ansible-tower/issues/7800
2017-12-01 11:34:47 -05:00
AlanCoding
dfc154ed95 allow no-op case for vault_credential 2017-12-01 10:29:23 -05:00
Ryan Petrello
a1f8f65add support specifying multiple vault IDs for a playbook run
see: https://github.com/ansible/awx/issues/352
2017-11-30 16:55:17 -05:00
Shane McDonald
3cd80ef67a Update pot files 2017-11-30 15:29:29 -05:00
Wayne Witzel III
f3310236e4 Merge pull request #599 from wwitzel3/release_3.2.2
Fix git project sync bug.
2017-11-30 11:22:29 -05:00
Wayne Witzel III
ed28faa3db Use TMP instead of TMPDIR and only set it in RunProjectUpdate 2017-11-30 16:10:12 +00:00
Alan Rominger
fde5a8850d Merge pull request #748 from AlanCoding/no_job_in_relaunch
Do not show job serialization in relaunch GET
2017-11-30 09:58:35 -05:00
AlanCoding
c359c072c4 do not show job serialization in relaunch GET 2017-11-30 08:47:35 -05:00
Jake McDermott
ee0aa40542 Merge pull request #743 from jakemcdermott/gcp-service-file
fix submit when no input object defined
2017-11-29 20:50:24 -05:00
Jake McDermott
81f2184aa7 fix submit when no input object defined 2017-11-29 19:50:46 -05:00
Jake McDermott
96c66b1e20 Merge pull request #712 from jakemcdermott/gcp-service-file
add input field for gcp service account json file
2017-11-29 18:41:23 -05:00
Jake McDermott
dbb9ffbaf4 use settings when setting up user data 2017-11-29 18:27:46 -05:00
Jake McDermott
06a7c024fe add e2e test for gcp service account file input 2017-11-29 18:27:34 -05:00
Jake McDermott
1229a10f35 add gcp service account file input 2017-11-29 18:27:24 -05:00
Jake McDermott
f15b1ae549 disable textarea drag and drop when field is disabled 2017-11-29 18:27:12 -05:00
Jake McDermott
71fea2e360 allow for programmatic input to text and textarea-secret fields 2017-11-29 18:26:59 -05:00
Jake McDermott
5baa371739 add unit test for file input component 2017-11-29 18:26:47 -05:00
Jake McDermott
cc8b5bc808 add file input component 2017-11-29 18:26:36 -05:00
Alan Rominger
53c6248a6d Merge pull request #647 from AlanCoding/no_sql
remove raw SQL in visible_roles
2017-11-29 16:46:09 -05:00
Ryan Petrello
fc4b02b79f Merge pull request #597 from ryanpetrello/jenkins-no-like-unicode
removing some cruft we thought would help us catch bugs (it didn't)
2017-11-29 16:39:20 -05:00
Ryan Petrello
a3dd9eb4b7 removing some cruft we thought would help us catch bugs (it didn't) 2017-11-29 16:23:07 -05:00
AlanCoding
c4bc310271 remove raw SQL in visible_roles 2017-11-29 16:04:31 -05:00
Richard Bywater
079abc162f Fix CloudForms enabled & id variable names
On Cloudforms (Version 2.0 at least), the dictionary that gets passed to
the inventory_import has a top-level 'cloudforms' dictionary element
that contains the 'id' and 'power_state' rather than those elements
being at the top-level of the dictionary.

This change adds in the 'cloudforms' into the expected name.
2017-11-30 09:30:23 +13:00
Ryan Petrello
d773d163f7 Merge pull request #595 from ryanpetrello/fix-workflow-survey-encrypt
more survey password encryption bug squashing
2017-11-29 15:09:40 -05:00
Chris Meyers
1899795d08 Merge pull request #721 from chrismeyersfsu/feature-2_factor
allow support for saml + 2-factor
2017-11-29 14:54:57 -05:00
Alan Rominger
43c58b5bf5 Merge pull request #731 from AlanCoding/enabled_fix
fix inventory import bug with enabled_var
2017-11-29 14:46:16 -05:00
Ryan Petrello
68ada92f3b more survey password encryption bug squashing
the nature of this latest bug is that the WorkflowJob has a *different*
implementation of _accept_or_ignore_job_kwargs, and it wasn't performing
encryption for extra vars provided at launch time; this change places the
encryption mechanism in UJT.create_unified_job so that it works the same
for _all_ UJTs

see: https://github.com/ansible/ansible-tower/issues/7798
see: https://github.com/ansible/ansible-tower/issues/7046
2017-11-29 14:40:41 -05:00
AlanCoding
2c06bfc9ce fix inventory import bug with enabled_var 2017-11-29 14:12:03 -05:00
Aaron Tan
4c43afda19 Merge pull request #586 from jangsutsr/fix-7768
Supress exception with concurrent deletion
2017-11-29 13:40:45 -05:00
Alan Rominger
5602b5d2d7 Merge pull request #733 from AlanCoding/credentials_in_list
Show credentials in list view
2017-11-29 12:09:52 -05:00
Chris Meyers
032318494b added tests for new settings field type 2017-11-29 11:52:00 -05:00
Bill Nottingham
40c22dcec8 Merge pull request #643 from wenottingham/whitespace-the-final-frontier
Fix extra whitespace in callback URL.
2017-11-29 11:29:45 -05:00
Alan Rominger
04f682bf7a Merge pull request #694 from AlanCoding/credentials_not_a_thing
adjust assertions about JT credentials to be correct
2017-11-29 10:41:48 -05:00
Alan Rominger
070a12a10c Merge pull request #692 from AlanCoding/vault_credential_check
Modify JT access tests to reflect new vault_credential reality
2017-11-29 10:40:35 -05:00
Ryan Petrello
91cc4689c9 Merge pull request #594 from ryanpetrello/fix-sosreport-venv
fix incorrect virtualenv path for sosreport plugin
2017-11-29 10:07:12 -05:00
Hideki Saito
febfcf709d fix incorrect virtualenv path for sosreport plugin 2017-11-29 09:57:41 -05:00
Wayne Witzel III
53460db4d7 Merge pull request #736 from ewjoachim/fix-social-core
Fix import of social_core.exceptions in sso/pipeline.py
2017-11-29 09:26:43 -05:00
AlanCoding
37a44c439e show credentials in list view 2017-11-29 08:14:45 -05:00
Joachim Jablon
6609f38fa2 Fix import of social_core.exceptions in sso/pipeline.py
Signed-off-by: Joachim Jablon <ewjoachim@gmail.com>
2017-11-29 14:08:58 +01:00
Alan Rominger
8f5be46d52 Merge pull request #730 from AlanCoding/list_bug
fix bug with inventory update queryset
2017-11-28 18:41:39 -05:00
Ryan Petrello
cf1d5a29f6 Merge pull request #593 from ryanpetrello/fix-7796
fix another encrypted survey password bug
2017-11-28 17:08:35 -05:00
Ryan Petrello
1425021106 fix another encrypted survey password bug
properly encrypt extra_vars that overlap with survey passwords when
`ask_variables_on_launch=true`

see: https://github.com/ansible/ansible-tower/issues/7796
2017-11-28 16:52:47 -05:00
Bill Nottingham
3866dcaaae Merge pull request #732 from wenottingham/quote-fu
Remove stray quote from help string.
2017-11-28 15:38:42 -05:00
Ryan Petrello
7b42316366 Merge pull request #592 from ryanpetrello/fix-7793
fix a bug which caused v1 cred backwards-compat to apply to v2 requests
2017-11-28 14:49:54 -05:00
Bill Nottingham
8cede51bac Remove stray quote from help string. 2017-11-28 14:32:39 -05:00
AlanCoding
a880f47925 fix bug with inventory update queryset 2017-11-28 14:13:35 -05:00
Chris Meyers
383c3cfe3e add more saml fields 2017-11-28 13:49:35 -05:00
Shane McDonald
32fcb84cf6 Merge pull request #722 from jakemcdermott/tools-awx-pycrypto
add pycrypto distro package to tools awx container image
2017-11-28 13:42:02 -05:00
Ryan Petrello
ce9d75c2e4 Merge pull request #591 from ryanpetrello/rename-ovirt
rename oVirt4 to Red Hat Virtualization
2017-11-28 13:10:58 -05:00
Ryan Petrello
26845642f0 fix a bug which caused v1 cred backwards-compat to apply to v2 requests
see: https://github.com/ansible/ansible-tower/issues/7793
2017-11-28 13:05:13 -05:00
Jake McDermott
34195a1b35 add pycrypto distro package to tools awx container image 2017-11-28 12:45:53 -05:00
Ryan Petrello
6fa0d9d4ed rename oVirt4 to Red Hat Virtualization
see: https://github.com/ansible/ansible-tower/issues/7790
2017-11-28 11:02:42 -05:00
Greg Considine
c723ba5289 Merge pull request #717 from gconsidine/ui/bump-dependency-versions
Update dependency versions to pull in latest 1.x Angular version
2017-11-28 10:11:12 -05:00
gconsidine
3ff9fa9931 Remove test on async fn with no callback and no returned promise 2017-11-28 09:54:54 -05:00
Ryan Petrello
7accac2f63 Merge pull request #590 from ryanpetrello/fix-7784
fix a bug in survey password default validation within workflows
2017-11-27 18:04:30 -05:00
Ryan Petrello
044c047ac6 fix a bug in survey password default validation
see: https://github.com/ansible/ansible-tower/issues/7046
see: https://github.com/ansible/ansible-tower/issues/7764
see: https://github.com/ansible/ansible-tower/issues/7784
2017-11-27 17:25:45 -05:00
Wayne Witzel III
3202e77b57 Merge pull request #720 from wwitzel3/devel
Update to asgi_amqp 1.0.1
2017-11-27 14:57:39 -05:00
Wayne Witzel III
a858093db8 Update to asgi_amqp 1.0.1 2017-11-27 19:41:30 +00:00
Chris Meyers
5a2ecd25e7 Merge pull request #589 from ansible/fix-project_update_cascade_fast
correctly cascade job cancel
2017-11-27 13:21:25 -05:00
Chris Meyers
6c89935521 correctly cascade job cancel
* Check the reason for a dependent project update failure. If it's
because of a cancel, then let the normal cancel mechanisms update the
jobs status and explanation. Do not update the dependent job's status
for a project update that was canceled, in the run code.
2017-11-27 12:34:55 -05:00
gconsidine
86a559caef Update dependency versions to pull in latest 1.x Angular version 2017-11-27 11:12:45 -05:00
Michael Abashian
33ff10728d Merge pull request #680 from mabashian/delete-warning-text
Tweaked language on delete warning modal
2017-11-22 15:02:55 -05:00
mabashian
ff1f322c88 Removed unused string from credentials strings 2017-11-22 13:29:52 -05:00
mabashian
d3da899459 Defined delete string in the base with the ability to pass the resource name in 2017-11-22 13:28:02 -05:00
AlanCoding
9fe524cd20 adjust assertions about JT credentials to be correct 2017-11-21 10:03:57 -05:00
AlanCoding
1481a62b23 modify JT access tests to reflect new vault_credential reality 2017-11-21 08:40:04 -05:00
Alan Rominger
ce6d96feda Merge pull request #687 from AlanCoding/new_kill
allow deletion of new jobs
2017-11-21 07:20:05 -05:00
AlanCoding
6c57a3bb68 allow deletion of new jobs 2017-11-20 11:19:22 -05:00
Aaron Tan
0641c6b0a6 Supress exception with concurrent deletion
Relates https://github.com/ansible/ansible-tower/issues/7768

This issue, as well as
https://github.com/ansible/ansible-tower/issues/7622, both rooted in a
concurrency issue of Django ORM:
https://github.com/ansible/ansible-tower/issues/762://code.djangoproject.com/ticket/28806

The solution related deals specifically with the related issue, but is
not a general solution. A general workaround can be found in
https://github.com/ansible/tower/pull/500.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-11-17 16:29:08 -05:00
mabashian
565b0b82dd Tweaked language on delete warning modal 2017-11-17 12:45:01 -05:00
Alan Rominger
4ea27e0d1b Merge pull request #587 from AlanCoding/computed_self
update original when updating computed fields
2017-11-17 12:23:43 -05:00
Wayne Witzel III
79c196fc08 Merge pull request #588 from wwitzel3/release_3.2.2
Include all previously run operations to satisfy Django migration planner
2017-11-17 12:12:21 -05:00
Wayne Witzel III
249a5e5e4d Include all previously run operations to satisfy Django migration planner. 2017-11-17 12:02:07 -05:00
AlanCoding
51c73cb357 update original when updating computed fields 2017-11-17 10:16:49 -05:00
Chris Meyers
98f2d936d9 allow support for saml + 2-factor
* python-social-auth has SOCIAL_AUTH_SAML_SECURITY_CONFIG, which is
forwarded to python-saml settings configuration. This commit exposes
SOCIAL_AUTH_SAML_SECURITY_CONFIG to configure tower in tower to allow
users to set requestedAuthnContext, which will disable the requesting of
password type auth from the idp. Thus, it's up to the idp to choose
which auth to use (i.e. 2-factor).
2017-11-17 09:25:50 -05:00
Ryan Petrello
8d35b71321 Merge pull request #585 from ryanpetrello/fix-wfjt-survey-encryption
re-encrypt WFJT.survey_spec and WorkflowJob.extra_vars too
2017-11-17 08:52:54 -05:00
Ryan Petrello
a80d5b1b39 reencrypt WFJT.survey_spec too
https://github.com/ansible/ansible-tower/issues/7046
2017-11-16 23:00:22 -05:00
Wayne Witzel III
e5d86419c8 Merge pull request #582 from AlanCoding/smart_computed2
update smart inventory computed fields
2017-11-16 19:36:08 -05:00
Greg Considine
54a98ff612 Merge pull request #581 from gconsidine/ui/fix/disabled-button-opacity
Update disabled button color to match style guide
2017-11-16 16:40:06 -05:00
Matthew Jones
9b5371f2ab Merge pull request #670 from chrismeyersfsu/job_events_docs
add docs for job events
2017-11-16 13:46:35 -05:00
Ryan Petrello
e7077185bf Merge pull request #584 from ryanpetrello/release_3.2.2
make settings.AWX_ISOLATED_KEY_GENERATION readonly
2017-11-16 13:42:00 -05:00
Ryan Petrello
4187d02b8a make settings.AWX_ISOLATED_KEY_GENERATION readonly
see: https://github.com/ansible/ansible-tower/issues/7380
2017-11-16 13:35:37 -05:00
Matthew Jones
457359322f Merge pull request #583 from ansible/nicer_error_tower_inventory
Present the tower inventory sync failure in a better way
2017-11-16 13:16:22 -05:00
Matthew Jones
8a65c6e1c8 Present the tower inventory sync failure in a better way
This allows it to be handled better by ansible 2.4+
2017-11-16 12:59:12 -05:00
Chris Meyers
c4e6fc23fc add docs for job events
* Focus on the ordering of Job Event creation. Important to know when
thinking through different Ansible execution strategies.
2017-11-16 12:48:48 -05:00
AlanCoding
fb29f68efc update smart inventory computed fields 2017-11-16 11:57:30 -05:00
Alan Rominger
71127c039d Merge pull request #668 from AlanCoding/null_cred_okay2
Do not filter out JTs with null credentials
2017-11-16 11:18:16 -05:00
gconsidine
1fcddba558 Update disabled button color to match style guide 2017-11-16 11:15:23 -05:00
AlanCoding
127da5525c do not filter out JTs with null credentials 2017-11-16 10:20:41 -05:00
Alan Rominger
0f52ab47a0 Merge pull request #665 from AlanCoding/prefetch_credentials
prefetch UnifiedJob related credentials
2017-11-16 09:57:22 -05:00
Matthew Jones
b06a508ceb Merge pull request #651 from tumbl3w33d/646_configurable_search_domains
Make DNS search domain configurable for awx containers
2017-11-15 23:32:16 -05:00
AlanCoding
8cb5ce8307 prefetch UnifiedJob related credentials 2017-11-15 22:35:10 -05:00
Benjamin Wenzel
c1aa4129f9 Make DNS search domain configurable for awx containers
related #646
2017-11-15 21:11:56 +01:00
Matthew Jones
d6b10b7f44 Merge pull request #657 from ansible/openshift_fixes
Openshift fixes
2017-11-15 13:29:41 -05:00
Shane McDonald
e2aa9dc599 Merge pull request #658 from shanemcd/devel
Enable image stream lookups in AWX OpenShift Project
2017-11-15 13:21:51 -05:00
Shane McDonald
a043369d07 Enable image stream lookups in AWX OpenShift Project
See the OpenShift docs on this for more info: https://docs.openshift.com/container-platform/3.6/dev_guide/managing_images.html#using-is-with-k8s

If you are not using OpenShift’s internal registry you will need to manually set awx_task_openshift_image and awx_web_openshift_image.
2017-11-15 13:15:56 -05:00
Matthew Jones
03eca250d9 Fix an openshift issue writing the inventory file
Openshift was throwing an error here, though I'm not sure why it makes
a whole lot of difference to call fdopen() vs open(). This was
introduced when this method was unified under the new
ansible-inventory system. This fixes it for all cases. mkstemp(),
while not necessary, is a useful addition to keep from leaking
inventory details unnecessarily.
2017-11-15 13:12:54 -05:00
Matthew Jones
65d01d508b Fix an issue with handler tasks after celery upgrade
There's a bug in celery 4.X when using bound tasks as error
handlers. We don't actually need it to be bound especially since the
request object is now available in the function signature
2017-11-15 13:12:06 -05:00
Chris Meyers
e20599d7bb Merge pull request #580 from chrismeyersfsu/fix-project_update_cascade_tower
cascade cancel proj update when job canceled
2017-11-15 11:19:35 -05:00
Chris Meyers
9288b53015 cascade cancel proj update when job canceled
* Implicit project update, launch_type='sync', get "associated" with a
job via project_update. When a job is canceled, so should this implicit
project update. This change enforces that logic.
2017-11-15 11:17:52 -05:00
Ryan Petrello
82be0a8af2 Merge pull request #579 from ryanpetrello/fix-survey-encryption-migration-failure
fix a bug in the survey reencryption migration
2017-11-15 10:38:35 -05:00
Ryan Petrello
35c374fc79 fix a bug in the survey reencryption migration
see: https://github.com/ansible/ansible-tower/issues/7046
2017-11-15 10:26:46 -05:00
Alan Rominger
dbe135991b Merge pull request #575 from AlanCoding/single_cancel
do not propogate cancel of inventory sync back up to project
2017-11-15 09:46:41 -05:00
Ryan Petrello
3a2ec25fb4 Merge pull request #649 from ryanpetrello/multicred
fix a permissions bug for credentials specified at JT launch time
2017-11-15 08:49:08 -05:00
Ryan Petrello
fa09d68603 add a few minor optimizations and some refactoring for multi-cred 2017-11-14 16:47:28 -05:00
Ryan Petrello
eb140d9e69 fix a permissions bug for credentials specified at JT launch time
hat tip to @alancoding for spotting this one
2017-11-14 16:21:05 -05:00
Bill Nottingham
64f89b3fce Merge pull request #578 from wenottingham/protect-our-environment
Remove some environment variables the callback plugin doesn't actually use
2017-11-14 16:10:53 -05:00
Bill Nottingham
aaaae87aa7 Remove some environment variables the callback plugin doesn't actually use. 2017-11-14 15:57:49 -05:00
Jared Tabor
5852c16ba6 Merge pull request #613 from jaredevantabor/fix-569
removing codemirror instantiation from $transition event
2017-11-14 11:09:41 -08:00
Ryan Petrello
ebd8941439 Merge pull request #595 from ryanpetrello/multicred
replace all Job/JT relations with a single M2M credentials relation
2017-11-14 14:07:18 -05:00
Jared Tabor
32cb18fc85 removing codemirror instantiation from $transition event 2017-11-14 10:24:36 -08:00
Marliana Lara
aeb8eb3d1e Fix jshint errors 2017-11-14 13:23:05 -05:00
Marliana Lara
6654cc35f7 Add relaunch component to Completed Jobs list 2017-11-14 13:04:20 -05:00
Ryan Petrello
28ce9b700e replace all Job/JT relations with a single M2M credentials relation
Includes backwards compatibility for now-deprecated .credential,
.vault_credential, and .extra_credentials

This is a building block for multi-vault implementation and Alan's saved
launch configurations (both coming soon)

see: https://github.com/ansible/awx/issues/352
see: https://github.com/ansible/awx/issues/169
2017-11-14 12:49:12 -05:00
Bill Nottingham
0558bd82bb Fix extra whitespace in callback URL. 2017-11-14 12:03:52 -05:00
Ryan Petrello
f887aaa71f Merge pull request #637 from ryanpetrello/fix-django-settings-bug
undo an optimization in django.conf.settings that breaks awx settings
2017-11-14 11:56:24 -05:00
Marliana Lara
69ada03b7b Add relaunch component to Job Results panel 2017-11-14 11:51:53 -05:00
Marliana Lara
ee6beae50a Add relaunchButton component and styles 2017-11-14 11:41:46 -05:00
Matthew Jones
799feac0e1 Merge pull request #638 from shanemcd/devel
Fix OpenShift configmap
2017-11-14 11:40:12 -05:00
Shane McDonald
0d86678a44 Fix OpenShift configmap
These variables changed in 8faf588775
2017-11-14 11:32:05 -05:00
Ryan Petrello
38f893c124 undo an optimization in django.conf.settings that breaks awx settings 2017-11-14 11:03:50 -05:00
Greg Considine
a2b444f179 Merge pull request #625 from gconsidine/ui/fix/home-dashboard-popover
Revert versions of D3 used by awx and ansible/nvd3
2017-11-14 10:48:40 -05:00
Matthew Jones
f46bacdeaa Merge pull request #636 from ansible/fix_celery_inspector
Delay instantiation of the celery app for the inspector
2017-11-14 10:42:10 -05:00
Matthew Jones
9ee77a95c6 Delay instantiation of the celery app for the inspector
This keeps the instance from re-using a pool that might have already
expired and is unusable for the inspector that needs to run as part of
the task manager
2017-11-14 10:33:47 -05:00
Alan Rominger
93b80307db Merge pull request #624 from AlanCoding/dev_super
get development supervisor use working again
2017-11-14 10:14:11 -05:00
Alan Rominger
0a883edd4d Merge pull request #632 from AlanCoding/some_test_fixes
do not use expensive visible_roles for Activity Stream filter
2017-11-14 09:56:27 -05:00
gconsidine
4cd9556f7b Revert versions of D3 used by awx and ansible/nvd3 2017-11-14 09:47:25 -05:00
Wayne Witzel III
9ed2a0da8f Merge pull request #627 from wwitzel3/devel
Fix image_build
2017-11-14 08:53:21 -05:00
AlanCoding
7eac219eae do not use expensive visible_roles for Act Stream filter 2017-11-14 08:37:14 -05:00
AlanCoding
805170ffd7 get development supervisor use working again 2017-11-13 20:31:32 -05:00
Wayne Witzel III
d696f6c3f6 Fix image_build 2017-11-13 19:11:58 -05:00
Wayne Witzel III
3cdeb446c4 Merge pull request #622 from wwitzel3/devel
Using metavar with a flag is not allowed or useful
2017-11-13 17:12:03 -05:00
Wayne Witzel III
58737a8e28 Using metavar with a flag is not allowed or useful 2017-11-13 16:05:54 -05:00
Wayne Witzel III
2fb74f5b02 Merge pull request #621 from wwitzel3/devel
Fix mgmt cmds, use real types not strings
2017-11-13 15:38:19 -05:00
Wayne Witzel III
768a3f62f1 Fix mgmt cmds, use real types not strings 2017-11-13 15:32:31 -05:00
Bill Nottingham
b03a64dd53 Merge pull request #567 from wenottingham/the-source--not-just-a-magazine
Assorted updates to project_update.yml
2017-11-13 15:18:42 -05:00
Ryan Petrello
44a2d7a346 Merge pull request #577 from ryanpetrello/release_3.2.2
render survey_spec for display purposes in a safe manner
2017-11-13 15:18:09 -05:00
Shane McDonald
386382c456 Merge pull request #619 from wwitzel3/devel
Fix installer references to asgi_amqp
2017-11-13 14:10:58 -05:00
Wayne Witzel III
d9f8f7721a Fix installer references to asgi_amqp 2017-11-13 13:39:39 -05:00
Wayne Witzel III
d2711f4af0 Merge pull request #618 from wwitzel3/devel
Silence models.E006 until rename the Project and InventorySource
2017-11-13 13:23:15 -05:00
Wayne Witzel III
77fd7ea4a8 Silence models.E006 until we can rename the Project and InventorySource models 2017-11-13 13:19:29 -05:00
Ryan Petrello
be00b1ca96 render survey_spec for display purposes in a safe manner
survey_spec is a nested dict, so if we don't `deepcopy()` it, updates
to the individual fields could corrupt the original data structure;
this was causing a bug whereby activity stream updates converted
encrypted survey password defaults -> `$encrypted$`, but inadvertently
modified the originating model due to shared references

see: https://github.com/ansible/ansible-tower/issues/7769
2017-11-13 13:01:56 -05:00
Wayne Witzel III
faa5a5e024 Merge pull request #600 from wwitzel3/django111
Upgrade AWX major dependencies
2017-11-13 12:26:04 -05:00
Wayne Witzel III
798d27c2cb Fix task_manager test 2017-11-13 12:02:00 -05:00
Wayne Witzel III
5b4dc9e7ee Disable group sending in consumer (Issue ansible/awx#615) 2017-11-13 10:19:14 -05:00
AlanCoding
33574d70c8 do not propogate cancel of inventory sync back up to project 2017-11-13 08:44:00 -05:00
Wayne Witzel III
f118e27047 Flake8 fixes and URL updates 2017-11-10 17:04:33 -05:00
Michael Abashian
2ab33467d8 Merge pull request #601 from mabashian/275-delete-warnings
More verbose delete warnings
2017-11-10 16:40:12 -05:00
mabashian
42a6757a10 Pass params in object to request function 2017-11-10 16:14:40 -05:00
gconsidine
aa38c1123c Check for null resource and update e2e model usage 2017-11-10 15:59:38 -05:00
gconsidine
5fcff09aae Update string-related component tests 2017-11-10 12:33:27 -05:00
Ryan Petrello
bc705ad8ce Merge pull request #574 from ryanpetrello/fix-7764
properly perform validation on encrypted survey defaults
2017-11-10 12:07:54 -05:00
mabashian
5e2ecda413 Define type in delete jt unit test 2017-11-10 11:55:41 -05:00
mabashian
25dc3f8778 Update delete modals and fixed unit test failures 2017-11-10 11:31:11 -05:00
Michael Abashian
2957f5bc7f Merge pull request #1 from gconsidine/275-delete-warnings
275 delete warnings
2017-11-10 11:28:33 -05:00
Ryan Petrello
78961c8037 properly perform validation on encrypted survey defaults
see: https://github.com/ansible/ansible-tower/issues/7764
2017-11-10 10:52:09 -05:00
gconsidine
8713e38c44 Update the base model to use string service instead of each sub model 2017-11-10 10:42:05 -05:00
Wayne Witzel III
96904968d8 Fix migration issues, tests, and templates 2017-11-09 17:29:48 -05:00
Wayne Witzel III
6d6bbbb627 Update URL strucuture, fixed string based calls 2017-11-09 17:24:04 -05:00
Wayne Witzel III
14c5123fda Update celery environ and tasks 2017-11-09 17:21:19 -05:00
Wayne Witzel III
de376292ba Update management commands 2017-11-09 17:18:18 -05:00
Wayne Witzel III
8faf588775 Update package versions, settings, and tooling 2017-11-09 17:17:30 -05:00
gconsidine
e8fd40ace0 Update model request interface and references 2017-11-09 17:01:32 -05:00
Bill Nottingham
a2b18a9f6e Add test to short-circuit checkout if revision is already checked out.
Move role checkout to a separate play, to work with this.
2017-11-08 18:29:59 -05:00
Jake McDermott
8f6289707b Merge pull request #596 from jakemcdermott/stored-xss-test
add test suite for stored xss
2017-11-08 16:47:03 -05:00
mabashian
4cd2f93c31 Updated delete warnings to indicate resources that may be invalidated as a result of deletion 2017-11-08 16:38:34 -05:00
Alan Rominger
e22486ada8 Merge pull request #573 from AlanCoding/7765
[3.2.2] fix bug of system auditor 404 viewing job
2017-11-08 11:16:28 -05:00
AlanCoding
0051da95c9 fix bug of system auditor 404 viewing job 2017-11-08 10:44:41 -05:00
Ryan Petrello
122142c040 Merge pull request #572 from ryanpetrello/isolated-debug-toolkit
add some useful tools for isolated connectivity debugging
2017-11-08 10:08:05 -05:00
Ryan Petrello
91ad0a9f89 add a useful tool for isolated connectivity debugging 2017-11-08 09:27:33 -05:00
Jake McDermott
79f450df8e add stored xss test suite 2017-11-07 13:43:20 -05:00
Jake McDermott
aab66b8ce8 add namespacing, schedules, and sources to fixtures 2017-11-07 13:43:05 -05:00
Jake McDermott
0afe94c4d4 add navigateTo command 2017-11-07 13:42:41 -05:00
Ryan Fitzpatrick
6ea3ecbb26 Merge pull request #567 from rmfitzpatrick/tower_inv_source_filter_wording
Provide more specificity to Tower inventory filter help text
2017-11-07 10:55:30 -05:00
Chris Church
6c1919273b Merge pull request #551 from cchurch/🥓
Include JSON string in temporary inventory script with %r
2017-11-06 17:46:12 -05:00
Alan Rominger
1ed3a8f0e9 Merge pull request #566 from AlanCoding/no_can_read
Fix bug where system gets 404 viewing job detail view
2017-11-06 15:23:30 -05:00
Michael Abashian
7dc30ab866 Merge pull request #554 from mabashian/274-right-click-new-tab
Fixed most lists so that name links can be opened in a new tab
2017-11-06 15:18:11 -05:00
mabashian
8f82fc26a2 Removed commented line from schedule list config 2017-11-06 14:46:31 -05:00
Jared Tabor
e87dce023b Merge pull request #568 from jaredevantabor/source-deletion
When deleting a source, delete the source's groups too
2017-11-06 11:27:46 -08:00
Matthew Jones
89a05e9bbc Handle json decoder errors from tower inventory source 2017-11-06 14:15:53 -05:00
Matthew Jones
74c9b9cf6a Adding pycrypto distro package
Without this a lot of things break and it's no longer marked as a
dependency for the ansible core project
2017-11-06 11:18:45 -05:00
Jared Tabor
96fbc9ea27 Merge pull request #571 from jaredevantabor/6551
Band aid for rapidly deleting groups
2017-11-03 16:28:22 -07:00
Jared Tabor
e70d377a53 feedback from PR: launch both DELETE calls at the same time
for both groups and hosts.
2017-11-03 16:26:00 -07:00
Jared Tabor
f65ef9f75c prolong removing the delete modal until after the list refreshes, post-delete 2017-11-03 15:25:39 -07:00
Bill Nottingham
632ff959ff Merge pull request #573 from wenottingham/going-up-for-some-headers
Preformatted text doesn't actually work in our popovers; don't try to use it.
2017-11-03 15:23:05 -04:00
Bill Nottingham
19d093f7aa Preformatted text doesn't actually work in our popovers; don't try to use it. 2017-11-03 13:25:58 -04:00
Wayne Witzel III
7149c41804 Merge pull request #570 from wwitzel3/release_3.2.2
Handle ProgrammingError in squashed helpers
2017-11-03 10:45:09 -04:00
Wayne Witzel III
1a5b5c32b8 Handle ProgrammingError in squashed helpers 2017-11-03 10:34:25 -04:00
Wayne Witzel III
1b44ca8ef4 Merge pull request #569 from wwitzel3/release_3.2.2
Handle programming error when evaluating the replaces list for 320
2017-11-03 09:02:58 -04:00
Wayne Witzel III
d7f4707044 Handle programming error when evaluating the replaces list for 320 2017-11-03 08:53:53 -04:00
AlanCoding
270a41443c fix bug of system auditor 404 viewing job 2017-11-03 08:20:15 -04:00
Jared Tabor
9d39ac83f9 When deleting a source, delete the source's groups too 2017-11-02 15:59:09 -07:00
Wayne Witzel III
ce393da6fd Merge pull request #564 from wwitzel3/squashbillies
Squashbillies - Fixing direct upgrades from 3.0/3.1 bug fix revisions.
2017-11-02 16:19:26 -04:00
Wayne Witzel III
2f86774006 3.2.0 should not have any replacements defined unless 0005a or 0005b migrations have been run previously 2017-11-02 16:11:45 -04:00
Jake McDermott
8666512d99 Merge pull request #550 from jakemcdermott/run_both_unit_test_suites
run both ui unit test suites and linting tasks, collect results for shippable
2017-11-02 15:40:30 -04:00
Ryan Fitzpatrick
e2c63c41e7 Provide more specificity to Tower inventory filter help text 2017-11-02 15:01:03 -04:00
Bill Nottingham
c827e73dac Update comments and task names. 2017-11-02 14:11:48 -04:00
Wayne Witzel III
f9685717b8 Move post 3.0 migrations to pre 3.1 position in migration files 2017-11-02 14:06:36 -04:00
Wayne Witzel III
47a3ba9bd5 Rename squash 300 to 30 2017-11-02 14:06:36 -04:00
Wayne Witzel III
af3e6f792c Rename squash 310 to 31 2017-11-02 14:06:35 -04:00
Wayne Witzel III
fc56a1c170 Fix 3.0 to 3.2 migration paths 2017-11-02 14:06:35 -04:00
Wayne Witzel III
84fb908261 Fix 3.1 to 3.2 migration paths 2017-11-02 14:06:33 -04:00
jlmitch5
cb4a38d7a7 Merge pull request #566 from ansible/click-to-close
Add close logic to clicking outside of the bounds of a lookup modal
2017-11-02 13:33:03 -04:00
John Mitchell
9518c38bb8 add close logic to clicking outside of the bounds of a lookup modal 2017-11-02 12:20:53 -04:00
Matthew Jones
5e37d6ea7e Remove unused TOWER_HOST and AWX_HOST env vars
These were conflicting with the new Tower credential
2017-11-02 10:44:06 -04:00
Matthew Jones
b70f7bd866 Merge pull request #549 from cchurch/allow-non-fqdn-for-ldap-server-uri
Allow non-FQDN for AUTH_LDAP_SERVER_URI.
2017-11-02 08:57:04 -04:00
Jake McDermott
77e11fe8fe collect unit test results for shippable
Signed-off-by: Jake McDermott <jmcdermott@ansible.com>
2017-11-02 01:22:07 -04:00
Jake McDermott
93f35b037d remove unused config 2017-11-01 15:31:00 -04:00
mabashian
d056cb22ef Fixed most lists so that name links can be opened in a new tab 2017-11-01 14:26:48 -04:00
Jake McDermott
4883876dc5 run both unit test suites and linting tasks 2017-11-01 13:36:34 -04:00
Chris Church
863b5e2e8e Output repr() of JSON in temporary inventory script to prevent Python from devouring escape sequences. 2017-11-01 12:59:49 -04:00
Chris Church
0f8e073d10 Allow non-FQDN for AUTH_LDAP_SERVER_URI. 2017-11-01 12:51:41 -04:00
jlmitch5
54e76b2534 Merge pull request #565 from ansible/no_placeholder_select2_typeahead
munge placeholder from select2 typeahead search bar
2017-11-01 12:45:29 -04:00
Alan Rominger
0579db1162 Merge pull request #439 from AlanCoding/retry_subset
Feature: retry on subset of jobs hosts
2017-11-01 11:33:15 -04:00
Bill Nottingham
7f20118d48 Merge pull request #547 from wenottingham/its-time-for-an-audit
Add system auditor placeholder.
2017-11-01 11:32:15 -04:00
Bill Nottingham
89d0f90e27 Add system auditor placeholder. 2017-11-01 10:46:39 -04:00
AlanCoding
41c84b4652 update retry-on-failed acceptance docs
Relaunching by other status values is tabled for later.
2017-11-01 10:24:46 -04:00
AlanCoding
0ae9283fba Feature: retry on subset of jobs hosts 2017-11-01 10:22:52 -04:00
Matthew Jones
f1813c35ed Merge pull request #528 from AlanCoding/fix_dep_update
fix bug with dependent SCM inv updates
2017-11-01 09:03:11 -04:00
Matthew Jones
0c5978715e Merge pull request #523 from AlanCoding/wfjt_spec_fix
fix admin edit of WFJT survey spec
2017-11-01 09:02:36 -04:00
Matthew Jones
5c1a6b7d6d Merge pull request #535 from matburt/fix_pgdata_issue
Specify a PGDATA directory to prevent container re-create issues
2017-11-01 08:46:24 -04:00
Jim Ladd
84c439b774 Merge pull request #542 from jladdjr/awx_349_acceptance_doc
Update custom credential document for mult-file injection
2017-10-31 19:14:37 -04:00
Jim Ladd
655759a5fc Update custom credential document for mult-file injection 2017-10-31 16:34:03 -04:00
Jake McDermott
6c85902ce8 Merge pull request #541 from jakemcdermott/update-credentials-title-selector
fix credentials form title selector
2017-10-31 16:30:00 -04:00
Jake McDermott
ef0c2086eb fix credentials form title selector when running container chrome 2017-10-31 16:11:44 -04:00
Matthew Jones
ffb148aaa9 Merge pull request #534 from dleehr/fix-install-2.3
Updates INSTALL.md to reflect Ansible 2.4 requirement
2017-10-31 15:07:06 -04:00
jlmitch5
b8ed41fa82 munge placeholder from select2 typeahead search bar 2017-10-31 14:39:25 -04:00
Michael Abashian
fbd03287ea Merge pull request #549 from mabashian/7697-smart-inv-pagination
Only pass host filter param to smart inv shortcut form
2017-10-31 13:29:52 -04:00
Michael Abashian
7919433288 Merge pull request #548 from mabashian/7752-host-list
Fixed related host list linking
2017-10-31 13:29:35 -04:00
Matthew Jones
bf281f6ea9 Specify a PGDATA directory to prevent container re-create issues 2017-10-31 10:20:08 -04:00
Ryan Petrello
3568be84c8 Merge pull request #561 from ryanpetrello/idle-hands
improve the callback worker's ability to deal with idle/disconnected DB
2017-10-31 10:05:29 -04:00
Ryan Petrello
8d2ab3de42 improve the callback worker's ability to deal with idle/disconnected DB
if database connectivity is lost, callback workers currently raise an
uncaught exception and hang; this can cause the entire process to stop
handling callback events

see: https://github.com/ansible/ansible-tower/issues/7660
2017-10-31 09:51:13 -04:00
Dan Leehr
641897713f Updates INSTALL.md to reflect Ansible 2.4 requirement 2017-10-30 22:41:58 -04:00
Jared Tabor
4c4cbaef9f Merge pull request #562 from jaredevantabor/timezone
Changing angular-tz-extensions branch
2017-10-30 14:21:19 -07:00
Jared Tabor
aef224732c changing angular-tz to point to a branch with a patch for UTC timezones
and also patching angular-scheduler to point to angular 1.4.14
and also patching angular-codemirror to point to angular 1.4.14,
and adding fsevents:"*" to the package.json, and regenerating
npm-shrinkwrap.json for the new dependencies and their branches.
2017-10-30 14:20:24 -07:00
Jake McDermott
b0c1be7338 Merge pull request #563 from jakemcdermott/bug-7718
append credential types documentation link to popovers
2017-10-30 16:24:19 -04:00
Jake McDermott
14a3a6073e append credential types documentation link to help popovers 2017-10-30 15:23:27 -04:00
AlanCoding
d7ae95684c fix bug with dependent SCM inv updates
This change causes all SCM inventory updates to run a local
project sync unless they were specifically marked as a
dependency of an already-existing project update, as
opposed to just doing so on manual launch types.

This should be a more robust criteria.
2017-10-30 11:59:33 -04:00
AlanCoding
8b39b3b41a fix admin edit of WFJT survey spec 2017-10-29 16:27:16 -04:00
Jake McDermott
fc7c2117e9 Merge pull request #553 from jakemcdermott/bug-5449
use abbreviated month name for dashboard chart
2017-10-27 17:01:47 -04:00
Ryan Petrello
0876d7825c Merge pull request #520 from ryanpetrello/phantom-version-comment
help people avoid mistakenly inputting their version info as a comment
2017-10-27 14:59:11 -04:00
Ryan Petrello
3953366a9e help people avoid mistakenly inputting their version info as a comment 2017-10-27 14:43:20 -04:00
Alan Rominger
d7f5ef6564 Merge pull request #511 from AlanCoding/wrong_type_error
raise error for invalid type lookup
2017-10-27 14:14:11 -04:00
Matthew Jones
63cf681369 Merge pull request #418 from Comradephate/patch-1
Divorce the "local docker install" portion of the install playbook from the image build + push logic
2017-10-27 12:31:09 -04:00
Aaron Tan
962de13965 Merge pull request #503 from jangsutsr/fix-7712
[3.2.2]Special handle host related_search_fields
2017-10-27 11:16:09 -04:00
Aaron Tan
7211ff22df Special handle host related_search_fields
Relates #7712 of ansible-tower.

UI uses `related_search_fields` list to populate help text for resourse
search, `ansible_facts` is searchable via UI but the general pickup
logic would ignore it. So make it a corner case.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-27 10:55:43 -04:00
Alan Rominger
003d7f0915 Merge pull request #543 from AlanCoding/urlencode_host_filter
[3.2.2] urlencode unquote host_filter on save
2017-10-27 08:50:39 -04:00
Matthew Jones
f019452207 Merge pull request #551 from ansible/tower_inventory_source
Tower inventory source
2017-10-27 08:41:24 -04:00
Alan Rominger
c323a2393a Merge pull request #552 from AlanCoding/retry_cleanup
[3.2.2] retry cleanup of build artifacts for bwrap race condition
2017-10-27 08:23:28 -04:00
Matthew Jones
85be3c7692 Align inventory variables with Ansible modules 2017-10-27 08:12:14 -04:00
Matthew Jones
5f3ebc26e0 Adding license checks for Tower inventory source
* For Tower the license must match between the source and destination
* For AWX the check is disabled
* Hosts imported from another Tower don't count against your license
  in the local Tower
* Fix up some issues with enablement
* Prevent slashes from being used in the instance filter
* Add &all=1 filter to make sure we pick up all hosts
2017-10-27 08:12:14 -04:00
Matthew Jones
d282966aa1 Use towervars to enable turning on remote tracking vars on Tower src
* This allows the local Tower to track enabled state and unique
  instance id for each host imported from the remote Tower
2017-10-27 08:12:14 -04:00
Matthew Jones
71e132ce0f Show instance filter ui element with tower inventory source 2017-10-27 08:12:14 -04:00
Jake McDermott
d6d84e8f5e use abbreviated month name for dashboard chart 2017-10-26 21:44:01 -04:00
Jared Tabor
a0f1c8fc7c Merge pull request #499 from jaredevantabor/project-based-nav
Adding Project Based Navigation of Job Templates
2017-10-26 18:11:34 -07:00
Jared Tabor
4fbfddaa93 changes from PR feedback: removing ghost action icon
and fixing a bug where the list of job templates was improperly
updated when a job was running and live events were received.
2017-10-26 16:50:12 -07:00
Alan Rominger
bc7793def1 Merge pull request #494 from AlanCoding/get_queryset_modest_refactor
Refactor get_queryset inside of access.py
2017-10-26 13:52:08 -04:00
Matthew Jones
fdc7f58bb4 Support passing instance filters to tower inventory src
* Switch ignore ssl errors to default on
* Application inventory source defaults for Tower src
2017-10-26 13:51:05 -04:00
Matthew Jones
6c597ad165 Adding initial credential and invsrc for Tower
* New credential type for Tower
* Inventory source definitions and migrations for Tower
* Initial Tower inventory source script
2017-10-26 13:51:05 -04:00
AlanCoding
48ec69c4f5 retry cleanup of build artifacts for bwrap race condition 2017-10-26 13:33:21 -04:00
AlanCoding
4e16b19ae6 Refactor access.py get_queryset into filtering method
Use BaseAccess class to enforce the superuser and system
  auditor conditions, as well as the optimizations.
Declare optimizations on access class as tuple.
Limit role of access class method narrowly to RBAC filtering.
2017-10-26 11:40:08 -04:00
Aaron Tan
1ea3d55167 Merge pull request #550 from jangsutsr/fix-7737-1
Follow up fix #7737
2017-10-26 11:29:05 -04:00
AlanCoding
b4a446dba0 raise error for invalid type lookup 2017-10-26 11:25:40 -04:00
Aaron Tan
7181bd1c9b Follow up fix #7737
The original fix introduced migration failure, this PR managed to fix
that.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-26 11:15:07 -04:00
Ryan Petrello
9e8ac3b09b Merge pull request #547 from ryanpetrello/fix-cleanup-memory-usage
[3.2.2] Backport (from awx) various memory optimizations for job cleanup
2017-10-26 10:39:58 -04:00
Aaron Tan
e24e1fc1f0 Merge pull request #542 from jangsutsr/fix-7737
[3.2.2]support `AZURE_CLOUD_ENVIRONMENT`
2017-10-26 10:20:14 -04:00
Aaron Tan
f28b48a473 support AZURE_CLOUD_ENVIRONMENT
Relates #7737 of ansible-tower.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-26 10:11:21 -04:00
Michael Abashian
4f58537949 Merge pull request #546 from mabashian/6209-license-readonly-auth-forms
Make codemirror ready-only when auth form field is disabled
2017-10-26 09:58:24 -04:00
mabashian
0512f65c8f Only pass host filter param to smart inv shortcut form 2017-10-26 09:55:36 -04:00
Alan Rominger
641b18fe13 Merge pull request #509 from AlanCoding/lib_test_fixes
update tests to new Ansible core code
2017-10-26 09:28:52 -04:00
Bill Nottingham
c680327ec3 Merge pull request #506 from wenottingham/its-log
Remove accidentally committed log files
2017-10-26 09:17:30 -04:00
AlanCoding
e5d2eb9f3d update tests to new Ansible core code 2017-10-26 08:34:00 -04:00
Bill Nottingham
da25f4104c Update .gitignore for npm log files. 2017-10-25 21:37:29 -04:00
Bill Nottingham
871dc81da3 Avoid task duplication by using default(omit). 2017-10-25 21:30:46 -04:00
mabashian
947bdeed3e Fixed related host list linking 2017-10-25 16:59:44 -04:00
Bill Nottingham
1285e8ffef Add blocks around the different SCMs, for clarity purposes. 2017-10-25 16:58:41 -04:00
Bill Nottingham
a8947c3b96 Remove accidentally committed log files 2017-10-25 16:38:56 -04:00
Greg Considine
565d116955 Merge pull request #505 from gconsidine/ui/fix/multiple-dependency-include
Update dependencies that share Angular as a dependency
2017-10-25 16:07:29 -04:00
Jake McDermott
1fe9f43690 Merge pull request #502 from jakemcdermott/update_test_config
test config cleanup and tooling updates
2017-10-25 15:39:55 -04:00
gconsidine
4a522fd10f Update dependencies that share Angular as a dependency 2017-10-25 14:48:18 -04:00
Jared Tabor
5e349590fd making JOB TEMPLATES tab the last tab on the projects form 2017-10-25 11:21:36 -07:00
Jared Tabor
625c0ad578 Adding Project Based Navigation of Job Templates
This adds a Job Templates tab onto the Project form that gives
the user the ability to see all the job templates using a project.
Clicking the add button on this list will take the user to the job
template form with the project field auto-filled with the project.
2017-10-25 11:21:36 -07:00
Mike McMahon
d3a7bec674 Backport (from awx) various memory optimizations for job cleanup
see: https://github.com/ansible/ansible-tower/issues/7751

0388568 Reduces the job to only looking at objects older than the cutoff date
0234311 missing colon and missing variable usage
399e0e5 switching to iterator and adding the missed Job cleanup
0cd34c1 jobs take count of gte cutoff, process only lt cutoff
2017-10-25 12:17:46 -04:00
Ryan Petrello
652facba9f Merge pull request #545 from ryanpetrello/fix-7746
work around an ansible bug that can cause project syncs to fail
2017-10-25 11:37:15 -04:00
mabashian
b1ef7506ea Make codemirror ready-only when auth form field is disabled 2017-10-25 11:30:26 -04:00
Ryan Petrello
c95d7d465a work around an ansible bug that can cause project syncs to fail
https://github.com/ansible/ansible-tower/issues/7746
https://github.com/ansible/ansible/issues/30064
2017-10-25 11:09:39 -04:00
Jake McDermott
3800a16f3e refactor e2e settings and config modules
This should make the settings and configuration logic less implicit and
a little easier to follow. Some familiarity with the configuration behavior
of nightwatch is still necessary in places - specifically, one should know
that all test_settings defined for non-default environments are treated as
overrides to the values defined for the default environment.
2017-10-25 10:58:39 -04:00
Jake McDermott
d70a0c8c24 cleanup e2e test development tooling and add readme examples 2017-10-25 10:22:18 -04:00
Aaron Tan
e999b35c42 Merge pull request #493 from jangsutsr/fix-474
Add protection against credential getattr
2017-10-25 09:45:25 -04:00
Michael Abashian
70919638ba Merge pull request #541 from mabashian/7608-adhoc-launch-modal
Made adhoc launch modal height dynamic
2017-10-24 14:07:32 -04:00
Michael Abashian
6ea48cd73e Merge pull request #540 from mabashian/6370-delete-inv-src
Delete inv source hosts before inv source
2017-10-24 14:07:08 -04:00
Michael Abashian
63ca8e4134 Merge pull request #538 from mabashian/7707-host-filter-remove-tags-v2
Fixed removing host filter search term with encoded character
2017-10-24 14:06:37 -04:00
Aaron Tan
725cc469cf Merge pull request #544 from jangsutsr/fix-7747
[3.2.2]Include vault credential check in job relaunch
2017-10-24 12:14:01 -04:00
Aaron Tan
553e81f888 Add protection against credential getattr
Relates #474.

Add protection in `__getattr__` method to prevent possible infinite
recursion loop.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-24 12:08:41 -04:00
Aaron Tan
665a4d83e3 Include vault credential check in job relaunch
Relates #7747 of ansible-tower.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-24 11:00:13 -04:00
AlanCoding
018514d657 urlencode unquote host_filter on save 2017-10-24 08:05:08 -04:00
Alan Rominger
73ece87e68 Merge pull request #487 from AlanCoding/E722
flake8: comply with new E722 rule
2017-10-23 14:58:27 -04:00
AlanCoding
90f63774f4 flake8: comply with new E722 rule 2017-10-23 14:36:48 -04:00
Marliana Lara
17aecc17d2 Merge pull request #472 from marshmalien/angular_upgrade_1_6_6
Upgrade to AngularJS v1.6.6
2017-10-23 14:13:11 -04:00
Marliana Lara
9157f53d43 Update angular-scheduler and angular-tz-extensions versions 2017-10-23 12:29:28 -04:00
Marliana Lara
9bb696aa6e Fix for input directive using strict comparison to determined "checked" row 2017-10-23 12:29:27 -04:00
Marliana Lara
32da686724 Handle errors with ProcessErrors 2017-10-23 12:29:26 -04:00
Marliana Lara
cee81e9df6 Fix any unhandled rejections 2017-10-23 12:29:25 -04:00
Ben Thomasson
b544922da1 Fix incorrect JS syntax 2017-10-23 12:29:24 -04:00
Ben Thomasson
b3c2f35358 Change success to then manually 2017-10-23 12:29:23 -04:00
Ben Thomasson
7d767f8f63 Automatically change .error to .catch.
Use this script to change .error to .catch using this linux script:

    #!/bin/bash -ex
    #Run in awx/awx/ui/client/src
    FILES=`grep -l -R "\.error(\s*function\s*(data,\s*status)\s*{" . | xargs`
    sed -i "s/\.error(\s*function\s*(data,\s*status)\s*{/.catch(({data, status}) => {/g" $FILES

    FILES=`grep -l -R "\.error(this\.error\.bind(this))" . | xargs`
    sed -i "s/\.error(this\.error\.bind(this))/\.catch(this\.catch\.bind(this))/g" $FILES

    FILES=`grep -l -R "\.error(\s*function\s*(error)\s*{" . | xargs`
    sed -i "s/\.error(\s*function\s*(error)\s*{/.catch(({error}) => {/g" $FILES

    FILES=`grep -l -R "\.error(\s*function\s*(obj,\s*status)\s*{" . | xargs`
    sed -i "s/\.error(\s*function\s*(obj,\s*status)\s*{/.catch(({obj, status}) => {/g" $FILES

    FILES=`grep -l -R "\.error(\s*function\s*(res,\s*status)\s*{" . | xargs`
    sed -i "s/\.error(\s*function\s*(res,\s*status)\s*{/.catch(({res, status}) => {/g" $FILES

    FILES=`grep -l -R "\.error(\s*function\s*(msg,\s*code)\s*{" . | xargs`
    sed -i "s/\.error(\s*function\s*(msg,\s*code)\s*{/.catch(({msg, code}) => {/g" $FILES

    FILES=`grep -l -R "\.error(\s*function\s*()\s*{" . | xargs`
    sed -i "s/\.error(\s*function\s*()\s*{/.catch(() => {/g" $FILES
2017-10-23 12:29:22 -04:00
Ben Thomasson
834e6c692c Automatically change instances of .success to .then with this linux script:
#Run in awx/awx/ui/client/src

    #!/bin/bash -ex
    FILES=`grep -l -R "\.success(\s*function\s*(data)\s*{" . | xargs`
    sed -i "s/\.success(\s*function\s*(data)\s*{/\.then(({data}) => {/g" $FILES

    FILES=`grep -l -R "\.success(\s*function\s*()\s*{" . | xargs`
    sed -i "s/\.success(\s*function\s*()\s*{/\.then(() => {/g" $FILES

    FILES=`grep -l -R "\.success(this\.success\.bind(this))" . | xargs`
    sed -i "s/\.success(this\.success\.bind(this))/\.then(this\.then\.bind(this))/g" $FILES
2017-10-23 12:29:21 -04:00
Ben Thomasson
fabdab78ef Upgrade AngularJS to 1.6.6 2017-10-23 12:29:10 -04:00
mabashian
71d428433f Made adhoc launch modal height dynamic 2017-10-23 12:09:25 -04:00
Michael Abashian
2f689fffbe Merge pull request #531 from mabashian/4796-workflow-resize-v2
Zoom workflow graph to fit screen on initial load
2017-10-23 10:47:14 -04:00
mabashian
3119d5ed22 Delete inv source hosts before inv source 2017-10-20 20:10:36 -04:00
Ryan Petrello
aab27e9b93 Merge pull request #539 from ryanpetrello/fix-7740
fix a unicode handling bug in inventory source name migration
2017-10-20 13:35:20 -04:00
Ryan Petrello
b60a30cbd4 fix a unicode handling bug in inventory source name migration
see: https://github.com/ansible/ansible-tower/issues/7740
2017-10-20 12:13:44 -04:00
Bill Nottingham
a313109b15 Merge pull request #475 from wenottingham/scm-tooltip
Update tooltip for update-on-launch.
2017-10-20 10:32:34 -04:00
Ryan Petrello
88acd95a72 Merge pull request #534 from ryanpetrello/release_3.2.2
store cloudforms inventory cache files in the proper location on disk
2017-10-20 09:41:05 -04:00
Ryan Petrello
7b36630f47 Merge pull request #460 from ryanpetrello/cloudforms-cache-path
store cloudforms inventory cache files in the proper location on disk
2017-10-20 09:40:02 -04:00
Jaron Rolfe
cc5f329d33 Explanation for image removal block and idiomatic handling of var that enables it 2017-10-19 21:43:37 -04:00
mabashian
c3fbb07535 Fixed removing host filter search term with encoded character 2017-10-19 19:31:41 -04:00
Bill Nottingham
31c1e1684d Update tooltip for update-on-launch.
This better describes how this setting is used.
2017-10-19 16:57:50 -04:00
Alan Rominger
083e56d97d Merge pull request #464 from AlanCoding/actiony_permissions
fix bug where JT admins could not edit spec
2017-10-19 16:22:14 -04:00
AlanCoding
098a407e25 fix bug where JT admins could not edit spec 2017-10-19 16:05:44 -04:00
Alan Rominger
6347db56c5 Merge pull request #473 from AlanCoding/test_fix_exc
fix test fallout from 321 merge
2017-10-19 16:05:01 -04:00
AlanCoding
e660879a00 fix test fallout from 321 merge 2017-10-19 15:47:51 -04:00
Matthew Jones
5635f5fb49 Merge branch 'release_3.2.1' into devel
* release_3.2.1:
  fallback to empty dict when processing extra_data
  fix migration problem from 3.1.1
  move 0005a migration to 0005b
  feedback on ad hoc prohibited vars error msg
  Fix the way we include i18n files in sdist
  Fix migrations to support 3.1.2 -> 3.2.1+ upgrade path
  fix missing parameter to update_capacity method
  fix WARNING log when launching ad hoc command
  Validate against ansible variables on ad hoc launch
  do not allow ansible connection type of local for ad_hoc
  work around an ansible 2.4 inventory caching bug
  fix scan job migration unicode issue
  Assert isolated nodes have capacity set to 0 and restored based on version
  Set capacity to zero if the isolated node has an old version
2017-10-19 13:30:26 -04:00
Michael Abashian
8d043e6f85 Merge pull request #532 from mabashian/7681-disassociate-help-popover
Disassociate host/group popover text
2017-10-19 11:12:28 -04:00
Michael Abashian
31602c4b28 Merge pull request #533 from mabashian/7720-adhoc-launch-error
Fixed error message when launching adhoc command
2017-10-19 11:11:44 -04:00
Ryan Petrello
57cd8adc2d Merge pull request #537 from ryanpetrello/ovirt4-auth-module
properly support authentication for ovirt4 ansible modules
2017-10-19 09:57:16 -04:00
Ryan Petrello
c1e20fe7a0 properly support authentication for ovirt4 ansible modules
see: https://github.com/ansible/ansible-tower/issues/6522
see: https://github.com/ansible/ansible-tower/issues/6522#issuecomment-337909863
2017-10-19 09:47:25 -04:00
Ryan Petrello
b1f5529aa4 Merge pull request #536 from ryanpetrello/fix-7741
properly follow symlinks for bwrap'd working directories
2017-10-19 08:58:16 -04:00
Jared Tabor
0497a4ba96 Merge pull request #396 from jaredevantabor/ui-router
Upgrade Angular UI Router to v1.0.7
2017-10-18 20:31:03 -07:00
Jared Tabor
275e02a8cf fixing issue with scrolling due to UI-router upgrade 2017-10-18 20:16:05 -07:00
Jared Tabor
887a09d052 fixing issue from UI-router upgrade where document title wouldn't update
with the name of the state.
2017-10-18 16:34:39 -07:00
Jared Tabor
02af117f51 adjusting unit tests to pass 2017-10-18 16:34:39 -07:00
Jared Tabor
6e2de1b4b0 changing "dyanmic" to "dynamic" 2017-10-18 16:34:39 -07:00
Jared Tabor
47f743e623 fixing removeTerm for smart search to work 2017-10-18 16:34:39 -07:00
Jared Tabor
4f0fa57a1b removing $urlMatcherFactory and $urlRouter b/c they're deprecated
in favor or $urlService
2017-10-18 16:34:39 -07:00
Jared Tabor
3d5f301a07 removing notify:false, it's deprecated 2017-10-18 16:34:39 -07:00
Jared Tabor
f9c991e660 replacing all stateChangeSuccess for $transition.onSuccess 2017-10-18 16:34:39 -07:00
Jared Tabor
6e3f4a7a6e fixing issues w/ lazyloaded states 2017-10-18 16:34:38 -07:00
Jared Tabor
07139820cb updating angular-ui-router to v. 1.0.7 2017-10-18 16:34:38 -07:00
Alan Rominger
350699eda8 Merge pull request #504 from AlanCoding/fk_error_msg
[3.2.2] tweak of error message for ForeignKey filters
2017-10-18 19:06:12 -04:00
Ryan Petrello
764356bf47 Merge pull request #459 from ryanpetrello/simplified-inventory-building
remove support for job-scoped auth tokens
2017-10-18 17:35:37 -04:00
Ryan Petrello
ea683344f5 remove support for job-scoped auth tokens
When Jobs and Adhoc Commands are launched, awx uses a job-scoped auth
token to dynamically fetch inventory via the awx REST API; this process
is complicated, hard to debug, and likely won't work going forward with
oauth2-based tokens in awx

see: https://github.com/ansible/awx/issues/21
2017-10-18 17:11:47 -04:00
Ryan Petrello
10a7544d68 properly follow symlinks for bwrap'd working directories
see: https://github.com/ansible/ansible-tower/issues/7741
2017-10-18 17:03:10 -04:00
Jared Tabor
d3eea5e694 generalizing class which is ignored when trying to drag the host-event-modal
it was only applied to .CodeMirror, which is only used by the JSON tab
2017-10-18 10:55:53 -07:00
Marliana Lara
8fd9fea113 Merge pull request #530 from marshmalien/fix/7702-job-stdout-wordwrap
Fix job standard out word-wrap
2017-10-18 13:51:36 -04:00
Jared Tabor
bff13e168a Merge pull request #461 from jaredevantabor/host-event-selecting
Fixing Host Event Modal Selecting
2017-10-18 09:23:46 -07:00
Wayne Witzel III
470a4b7746 Merge pull request #535 from wwitzel3/release_3.2.2
use getattr in social auth django strategy
2017-10-18 11:02:11 -04:00
Wayne Witzel III
38c2ea7025 use getattr in social auth django strategy 2017-10-18 10:20:44 -04:00
Jared Tabor
774a3da7f4 generalizing class which is ignored when trying to drag the host-event-modal
it was only applied to .CodeMirror, which is only used by the JSON tab
2017-10-17 16:03:39 -07:00
Bill Nottingham
5f3b4575de Merge pull request #456 from wenottingham/i-am-becoming
Set ANSIBLE_BECOME_ASK_PASS to avoid deprecation warning.
2017-10-17 18:11:33 -04:00
Ryan Petrello
5895654538 store cloudforms inventory cache files in the proper location on disk
with process isolation enabled (which is the awx default), cloudforms
caches inventory script results on disk; awx should direct cloudforms to
store these cache files in a location that's exposed to the isolated
environment

see: ansible/ansible#31760
2017-10-17 17:07:21 -04:00
Ryan Petrello
59f9967dba store cloudforms inventory cache files in the proper location on disk
with process isolation enabled (which is the awx default), cloudforms
caches inventory script results on disk; awx should direct cloudforms to
store these cache files in a location that's exposed to the isolated
environment

see: ansible/ansible#31760
2017-10-17 17:06:48 -04:00
Bill Nottingham
058475c131 Set ANSIBLE_BECOME_ASK_PASS to avoid deprecation warning. 2017-10-17 16:00:16 -04:00
mabashian
b402d9ba6d Fixed error message when launching adhoc command 2017-10-17 14:42:24 -04:00
Chris Meyers
3685cb5517 Merge pull request #440 from chrismeyersfsu/fix-callback_unit_tests
fixes ansible callback import json warning
2017-10-17 13:53:45 -04:00
mabashian
5db478a4a0 Zoom workflow graph to fit screen on initial load 2017-10-17 12:59:44 -04:00
mabashian
059347eec3 Made disassociate host/group titles more descriptive 2017-10-17 10:23:17 -04:00
mabashian
e8dbfa42cf Fixed disassociate host from group help text 2017-10-17 10:10:34 -04:00
Michael Abashian
3d12e040ed Merge pull request #528 from mabashian/5129-jt-spinner-v2
Moved wait stop calls on jt form so that they fire right before reloading state
2017-10-16 16:20:02 -04:00
Michael Abashian
fceca3bcae Merge pull request #527 from mabashian/7697-smart-inventory-shortcut
Fixed smart inv button bug navigating to page 2 of hosts.
2017-10-16 16:19:40 -04:00
Chris Meyers
4e2cf62e89 fixes ansible callback import json warning
[WARNING]: Failure using method (v2_runner_on_ok) in callback plugin
(<awx_display_callback.module.AWXDefaultCallbackModule object at
0x47f6090>):
'module' object has no attribute 'dumps'

The above error is thrown by ansible if callback plugins don't respect
the same import precedence configuration as Ansible. ansible callback/*
dir includes a json.py file. This is imported by ansible
callback/__init__.py when a callback plugin implementation imports from
Ansible callback base without setting the correct import precedence.
2017-10-16 10:29:41 -04:00
Jaron Rolfe
5e17d72922 Improve push capabilities and allow build playbook to push 2017-10-16 00:38:28 -04:00
Jaron Rolfe
67df298f21 Replace deprecated "include" with "include_tasks" 2017-10-15 22:15:11 -04:00
Alan Rominger
353a9a55c7 Merge pull request #406 from AlanCoding/variables_debt
Consolidation of variables parsing throughout codebase
2017-10-13 15:40:36 -04:00
Matthew Jones
0ac3598ca5 Merge pull request #431 from matburt/lower_awx_uid
Lower the default uid by which we'll rewrite passwd
2017-10-13 15:33:36 -04:00
Jake McDermott
06f06173b0 Merge pull request #408 from jakemcdermott/smoke-tests
add smoke test
2017-10-13 15:21:00 -04:00
Marliana Lara
fcd03fb1c2 Fix job standard out error message word-wrap 2017-10-13 14:59:57 -04:00
Matthew Jones
da5e6883d4 Lower the default uid by which we'll rewrite passwd
This fixes some issues with openshift under certain security policies
2017-10-13 14:27:30 -04:00
Matthew Jones
ef05df9224 Merge pull request #421 from carbonin/use_http_host_in_slash_redirect
Use $http_host in trailing slash redirect
2017-10-13 14:12:21 -04:00
Ryan Petrello
8b8c0e325f Merge pull request #430 from ryanpetrello/fix-isolated-version
stop hard-coding the awx version in the isolated development environment
2017-10-13 12:35:37 -04:00
Ryan Petrello
5bb06fdb50 stop hard-coding the awx version in the isolated development environment
see: #296
2017-10-13 12:17:04 -04:00
AlanCoding
993fa9290d additional verbosity for vars parsing exceptions 2017-10-13 11:41:11 -04:00
Jim Ladd
5924571904 Merge pull request #384 from jladdjr/awx365_post_response_discrepancy
Address discrepancy in POST response between jobs launches and project / inventory source updates
2017-10-13 09:59:29 -04:00
Chris Meyers
9cc4520a34 Merge pull request #409 from chrismeyersfsu/replay_job_events
add job event replay awx-manage command
2017-10-13 09:39:28 -04:00
Chris Meyers
62987196cb add speedup support to event replay and stats
* add tests
* add verbosity support
2017-10-13 09:25:18 -04:00
Nick Carboni
cfa21af432 Use $http_host in trailing slash redirect
This allows the port from the request header to be used
rather than having the request redirected to the port
being used inside the container which may not be
accessible

Fixes #420
related #420

Signed-off-by: Nick Carboni <ncarboni@redhat.com>
2017-10-12 17:35:55 -04:00
Jim Ladd
6f1c7ee733 Update several endpoints to match JT launch POST response
Signed-off-by: Jim Ladd <jladd@redhat.com>
2017-10-12 17:35:34 -04:00
mabashian
2cab6982c1 Moved wait stop calls on jt form so that they fire right before reloading state 2017-10-12 17:01:32 -04:00
mabashian
3ede367df4 Fixed smart inv button bug navigating to page 2 of hosts. Added tooltip when button is disabled. 2017-10-12 16:56:21 -04:00
Aaron Tan
bcd2a8f211 Merge pull request #382 from jangsutsr/fix-264
Implement workflow job failure
2017-10-12 16:34:08 -04:00
Jaron Rolfe
ee15db4c7c allow for private registry without latest tag
The logic that sets awx_web_docker_actual_image and awx_task_docker_actual_image creates and pushes images to the private registry tagged with the awx version, which is appropriate, but then tries to pull with no tag. (so docker defaults to "latest", which does not exist)
2017-10-12 15:57:34 -04:00
Alan Rominger
f6bf0ad21f Merge pull request #521 from AlanCoding/update_isolated
[3.2.2] update isolated container requirements
2017-10-12 14:24:38 -04:00
Alan Rominger
ad0e43dc52 Merge pull request #379 from AlanCoding/awx160
Enforce max line length of 160 characters
2017-10-12 14:05:31 -04:00
Aaron Tan
5287e5c111 Implement workflow job failure
Relates #264.

This PR proposed and implemented a way of defining workflow failure
state:

A workflow job fails if one of the conditions below satisfies.
* At least one node runs into states `canceled` or `error`.
* At least one leaf node runs into states `failed`, but no child node is
  spawned to run (no error handler).

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-12 11:08:33 -04:00
Chris Meyers
e19a57c50a add job event replay awx-manage command
* awx-manage replay_job_event --job_id <id>
2017-10-12 09:40:30 -04:00
Jake McDermott
113d62a95f add smoke test 2017-10-11 18:28:56 -04:00
Jake McDermott
b5899c193a update object fields and commands 2017-10-11 18:28:36 -04:00
Greg Considine
817b397d20 Merge pull request #524 from gconsidine/ui/fix/remove-unsupported-query-tokens
Remove unsupported tokens from search generated queries
2017-10-11 17:54:26 -04:00
AlanCoding
8b41810189 Consolidation of variables parsing throughout codebase
* Remove attempted support of key=value pattern, because
  it is not actually allowed in practice
* Have variables validator defer to the utils variables parser
* Prune serializers of a handful of cases that previous
  attempts at cleanup have missed
2017-10-11 16:21:50 -04:00
Matthew Jones
f25ab7c6da Merge pull request #403 from jangsutsr/fix-391
Add extra encoding to ldap_dn verification
2017-10-11 14:35:35 -04:00
AlanCoding
f03b40aa50 enforce max line length of 160 characters 2017-10-11 12:38:39 -04:00
Aaron Tan
9dd4c7aaa3 Add extra encoding to ldap_dn verification
Relates #391.

Upstream `python-ldap` (surprisingly) does not support utf-8 DN. So
explicit encoding is needed.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-11 12:28:26 -04:00
jlmitch5
b61fdaf721 Merge pull request #526 from jlmitch5/hideWorkflowAndSurveyButtons
hide workflow and survey buttons from non-detail tabs
2017-10-11 11:35:35 -04:00
John Mitchell
1603106cb4 include workflow editor when showing buttons' 2017-10-11 10:58:38 -04:00
Aaron Tan
1454000b91 Merge pull request #522 from jangsutsr/ldap_docs
Add LDAP deploy instructions
2017-10-11 10:07:29 -04:00
Alan Rominger
b2e63d5e47 Merge pull request #510 from AlanCoding/event_accounting
add logger statement for number of events
2017-10-10 22:12:11 -04:00
Alan Rominger
e7ede6af4a Merge pull request #525 from AlanCoding/update_isolated_version
[3.2.2] update fallback isolated version to 3.2.2
2017-10-10 22:06:09 -04:00
Alan Rominger
5503d4efb4 Merge pull request #523 from AlanCoding/fix_isolated_capacity
[3.2.2] fix equation for isolated instance capacity
2017-10-10 22:04:03 -04:00
Jake McDermott
d4af743805 Merge pull request #397 from jakemcdermott/unit-linting
additional test de-linting
2017-10-10 20:56:40 -04:00
Jake McDermott
8b395c934c de-lint unit tests 2017-10-10 20:23:15 -04:00
Jake McDermott
ae0855614b update unit test file names 2017-10-10 20:18:05 -04:00
Jake McDermott
169cd1a466 Merge pull request #395 from gconsidine/ui/combine-test-dirs
Ui/combine test dirs
2017-10-10 18:33:12 -04:00
John Mitchell
54640dbca0 hide workflow and survey buttons from non-detail tabs
since the two are basically sub-states of the edit form (detail tab), they should only show up when that tab is selected
2017-10-10 17:08:04 -04:00
gconsidine
82f81752e4 De-lint test files and update test,build config 2017-10-10 16:59:42 -04:00
gconsidine
8b6cc0e323 Combine test directories 2017-10-10 16:59:42 -04:00
Greg Considine
c0996f5fb1 Merge pull request #394 from gconsidine/ui/fix/closing-curly-brace
Add closing curly brace in strings file
2017-10-10 16:58:41 -04:00
gconsidine
3998796bf0 Add closing curly brace in strings file 2017-10-10 16:42:56 -04:00
AlanCoding
eab82f3efa updated fallback isolated version to 3.2.2 2017-10-10 15:45:20 -04:00
gconsidine
9e3d90896b Remove unsupported tokens from search generated queries 2017-10-10 15:22:17 -04:00
AlanCoding
e66a1002ee fix equation for isolated instance capacity 2017-10-10 14:58:09 -04:00
Aaron Tan
82160e2072 Add LDAP deploy instructions
Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-10 14:54:53 -04:00
AlanCoding
e814f28039 add logger statement for number of events 2017-10-10 14:48:00 -04:00
AlanCoding
03e58523b2 tweak of error message for ForeignKey filters 2017-10-10 14:47:37 -04:00
AlanCoding
341ef411a4 update isolated container requirements 2017-10-10 14:46:41 -04:00
Aaron Tan
8d19555cf1 Merge pull request #519 from jangsutsr/fix-7726
Disable inventory var overwrite in inv import
2017-10-10 14:38:50 -04:00
Greg Considine
d23fd0515d Merge pull request #518 from gconsidine/ui/fix/credential-kind-list-display
Use credential_type to fetch associated types in list view
2017-10-10 14:38:50 -04:00
Aaron Tan
b9483c28b0 Disable inventory var overwrite in inv import
Relates #7726 of ansible-tower.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-10 14:38:50 -04:00
Alan Rominger
6f9fc0c3f8 Merge pull request #514 from AlanCoding/no_ordereddit
[3.2.2] prevent OrderedDict syntax in error message
2017-10-10 14:38:49 -04:00
gconsidine
766a088749 Use credential_type to fetch associated types in list view 2017-10-10 14:38:49 -04:00
Chris Church
2b539cab85 Merge pull request #511 from cchurch/ldap-filter-dash-support
[3.2.2] Support dash in LDAP attribute names in filters.
2017-10-10 14:38:49 -04:00
AlanCoding
2fb67a3648 prevent OrderedDict syntax in error message 2017-10-10 14:38:49 -04:00
Greg Considine
64c5e3994e Merge pull request #513 from gconsidine/ui/fix/lookup-component-empty-input
Set lookup value changed from something to nothing to be null
2017-10-10 14:38:49 -04:00
Alan Rominger
7b792926eb Merge pull request #509 from AlanCoding/max_ui_events
[3.2.2] add CTiT setting for max UI job events
2017-10-10 14:38:49 -04:00
Chris Church
c067788428 Support dash in LDAP attribute names in filters. 2017-10-10 14:38:49 -04:00
gconsidine
b7071a48c2 Set lookup value changed from something to nothing to be null 2017-10-10 14:38:49 -04:00
AlanCoding
dee4b72303 add CTiT setting for max UI job events 2017-10-10 14:38:49 -04:00
Alan Rominger
5994a77b84 Merge pull request #508 from AlanCoding/password_handholding
[3.2.2] reword error message about encrypted user input
2017-10-10 14:38:48 -04:00
Marliana Lara
f93506fe2c Merge pull request #491 from marshmalien/fix/7661-host-config-key-border
[3.2.2] Fix missing right border of lookup buttons
2017-10-10 14:38:48 -04:00
Alan Rominger
7c86e38b81 Merge pull request #506 from AlanCoding/active_job_period
[3.2.2] add period to active job conflict error
2017-10-10 14:38:48 -04:00
AlanCoding
1c374fba7d reword error message about encrypted user input 2017-10-10 14:38:48 -04:00
Marliana Lara
2cc9e2ca0b Fix hidden right border of form input lookup buttons 2017-10-10 14:38:48 -04:00
Alan Rominger
335dfd564a Merge pull request #505 from AlanCoding/v1_jt_vc_ct_sf
[3.2.2] Exclude credential type content from v1
2017-10-10 14:38:48 -04:00
AlanCoding
5380d57ce8 add period to active job conflict error
Rename StateConflict to ActiveJobConflict and used shared
message inside of that exception class.
2017-10-10 14:38:48 -04:00
AlanCoding
a01f80db5b Exclude credential type content from v1
credential_type_id was showing up in vault_credential
summary_fields in API v1
2017-10-10 14:38:48 -04:00
Aaron Tan
d7eba47adb Merge pull request #456 from jangsutsr/fix-7656
[3.2.2]Remove search term separators
2017-10-10 14:38:47 -04:00
Alan Rominger
5fffdec69d Merge pull request #490 from AlanCoding/many_deleter_320
[3.2.2] Delete all hosts or groups from inventory source
2017-10-10 14:38:47 -04:00
Aaron Tan
358ef76529 Remove search term separators
Relates #7656 in ansible-tower.

We have been using comma `,` and space ` ` to separate search terms in
query string `<field_name>__search=<search terms>`, however in general
we can always use `&` to achieve separation like
`<field_name>__search=<search term 1>&<field_name>__search=<search term
2>&...`. Using specific delimiters makes it impossible for search terms
to contain those delimiters, so they are better off being removed.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-10 14:38:47 -04:00
Aaron Tan
bb628c52ad Merge pull request #487 from jangsutsr/fix-7586
[3.2.2]Fix SAML auth behind load balancer issue.
2017-10-10 14:38:47 -04:00
AlanCoding
d2e0b26287 allow deleting hosts and groups from inv src sublists 2017-10-10 14:38:47 -04:00
Ryan Petrello
f2d46baf09 Merge pull request #496 from ryanpetrello/fix-6683
fix a bug when Tower is integrated with ipsilon SAML server
2017-10-10 14:38:47 -04:00
Ryan Petrello
c6fdadd7f2 Merge pull request #497 from ryanpetrello/fix-7259
properly sanitize encrypted default passwords in JT.survey_spec
2017-10-10 14:38:47 -04:00
Aaron Tan
cc8b115c6a Fix SAML auth behind load balancer issue.
Relates to #7586 of ansible-tower as a follow-up of fix #420 of tower.

The original fix works for Django version 1.9 and above, this PR
expanded the solution to Django verison 1.8 and below.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-10 14:38:47 -04:00
Ryan Petrello
82d05e0a10 properly sanitize encrypted default passwords in JT.survey_spec
see: https://github.com/ansible/ansible-tower/issues/7259
2017-10-10 14:38:47 -04:00
Ryan Petrello
9978b3f9ad Merge pull request #489 from ryanpetrello/release_3.2.2
fix busted 3.2.2 activity stream migration
2017-10-10 14:38:46 -04:00
Alan Rominger
4f4af058b3 Merge pull request #480 from AlanCoding/committed_cap
[3.2.2] add IG committed capacity to serializer
2017-10-10 14:38:46 -04:00
Ryan Petrello
b372cebf8d fix a bug when Tower is integrated with ipsilon SAML server
https://github.com/ansible/ansible-tower/issues/6683
2017-10-10 14:38:46 -04:00
Alan Rominger
3df8e2beb1 Merge pull request #494 from AlanCoding/wfjt_perm_fix2
[3.2.2] fix bug checking WFJT node for prompted resources
2017-10-10 14:38:46 -04:00
AlanCoding
c45fbcf2ee add IG committed capacity to serializer 2017-10-10 14:38:46 -04:00
Ryan Petrello
5efa50788f Merge pull request #481 from ryanpetrello/fix-7046
[3.2.2] encrypt job survey data
2017-10-10 14:38:46 -04:00
AlanCoding
3abbe87e10 fix bug checking WFJT node for prompted resources 2017-10-10 14:38:46 -04:00
Ryan Petrello
f26bdb3e96 migrate existing survey passwords to be encrypted
see: https://github.com/ansible/ansible-tower/issues/7046
2017-10-10 14:38:46 -04:00
Ryan Petrello
4be4e3db7f encrypt job survey data
see: https://github.com/ansible/ansible-tower/issues/7046
2017-10-10 14:38:46 -04:00
Alan Rominger
4ea92f0dcb Merge pull request #306 from AlanCoding/new_perf_logging
[3.2.2] new method of performance logging
2017-10-10 14:38:45 -04:00
Ryan Petrello
a0cfbb93e9 fix busted 3.2.2 activity stream migration
see: ansible/ansible-tower#7704
2017-10-10 14:38:45 -04:00
Aaron Tan
08a784d50c Merge pull request #474 from jangsutsr/fix-7386
Include Tower configurations into activity stream
2017-10-10 14:38:45 -04:00
AlanCoding
9ee18d02c8 new method of performance logging 2017-10-10 14:38:45 -04:00
Ryan Petrello
4fd190e4c8 Merge pull request #468 from ryanpetrello/smarter-credtype-migrations
[3.2.2] add new credential types in a more stable way in migrations
2017-10-10 14:38:45 -04:00
Aaron Tan
a11e33458f Include Tower configurations into activity stream
Relates #7386 of ansible-tower.

Due to the uniqueness of Tower configuration datastore model, it is not
fully compatible with activity stream workflow. This PR introduced
setting field for activitystream model along with other changes to make
Tower configuration a special case for activity streams.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-10 14:38:45 -04:00
Aaron Tan
84fdfbb898 Merge pull request #469 from jangsutsr/fix-7684
[3.2.2] Prevent slugify username from social sso backends
2017-10-10 14:38:45 -04:00
Ryan Petrello
f4a252a331 add new credential types in a more stable way in migrations
instead of writing individual migrations for new built-in credential
types, this change makes the "setup_tower_managed_defaults" function
idempotent so that it only adds the credential types you're missing
2017-10-10 14:38:45 -04:00
Ryan Petrello
d4fe60756b Merge pull request #466 from ryanpetrello/ovirt4-inv-source
don't install pycurl from pypi; use a system package instead
2017-10-10 14:38:45 -04:00
Aaron Tan
f4ab979b59 Prevent slugify username from social sso backends
Relates #7684 of ansible-tower.

Slugify username in python-social-auth means disallowing
any non-alphanumerial characters, which is an over-kill
for awx/tower, thus disabling it.

Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
2017-10-10 14:38:45 -04:00
Ryan Petrello
3d3d79b6b3 Merge pull request #464 from ryanpetrello/ovirt4-inv-source
add ovirt sdk dependency for ovirt4 support
2017-10-10 14:38:44 -04:00
Ryan Petrello
e06d4d7734 don't install pycurl from pypi; use a system package instead
the ovirt4 sdk relies on pycurl, which is complicated to install w/ pip;
rely on pycurl to be provided by a system package instead
2017-10-10 14:38:44 -04:00
Ryan Petrello
ab18a4a440 Merge pull request #454 from ryanpetrello/ovirt4-inv-source
support ovirt4 as a built-in inventory source
2017-10-10 14:38:44 -04:00
Ryan Petrello
7438062b97 add ovirt sdk dependency for ovirt4 support 2017-10-10 14:38:44 -04:00
Ryan Petrello
4510cd11db Merge pull request #452 from ryanpetrello/fix-7609
disable GCE inventory caching w/ a .ini file
2017-10-10 14:38:44 -04:00
Ryan Petrello
74f2509482 support ovirt4 as a built-in inventory source
see: https://github.com/ansible/ansible-tower/issues/6522
2017-10-10 14:38:44 -04:00
Ryan Petrello
f84e42ed15 Merge pull request #451 from ryanpetrello/fix-7609
disable GCE inventory source cache
2017-10-10 14:38:44 -04:00
Ryan Petrello
94b4dabee2 disable GCE inventory caching w/ a .ini file
see: https://github.com/ansible/ansible-tower/issues/7609
see: https://github.com/ansible/tower/pull/451#pullrequestreview-64454393
2017-10-10 14:38:44 -04:00
Ryan Petrello
94d44e8791 disable GCE inventory source cache
by default, the GCE inventory script caches results on disk for
5 minutes; disable this behavior

see: https://github.com/ansible/ansible-tower/issues/7609
2017-10-10 14:38:44 -04:00
Ryan Petrello
d24166bd68 Merge pull request #442 from ryanpetrello/fix-7554
properly encode LDAP DN values on validation
2017-10-10 14:38:43 -04:00
Ryan Petrello
62f82e7a7e Merge pull request #441 from ryanpetrello/fix-7607
allow the credential type to be changed for unused credentials
2017-10-10 14:38:43 -04:00
Ryan Petrello
7a21a45781 properly encode LDAP DN values on validation
see: https://github.com/ansible/ansible-tower/issues/7554
2017-10-10 14:38:43 -04:00
Ryan Petrello
91ec0a4482 Merge pull request #430 from ryanpetrello/fix-7620
don't show polymorphic_ctype in unique validation error messaging
2017-10-10 14:38:43 -04:00
Ryan Petrello
c8f4320b58 allow the credential type to be changed for unused credentials
see: https://github.com/ansible/ansible-tower/issues/7607
2017-10-10 14:38:43 -04:00
Ryan Petrello
71a725c5f8 Merge pull request #432 from ryanpetrello/fix-7513
add awx meta variables to adhoc command extra_vars
2017-10-10 14:38:43 -04:00
Ryan Petrello
96572fe3d4 don't show polymorphic_ctype in unique validation error messaging
see: https://github.com/ansible/ansible-tower/issues/7620
2017-10-10 14:38:43 -04:00
Ryan Petrello
554a9586c6 add awx meta variables to adhoc command extra_vars
see: https://github.com/ansible/ansible-tower/issues/7513
2017-10-10 14:38:37 -04:00
Ryan Petrello
f41c8cf4f2 Merge pull request #426 from ryanpetrello/fix-7655
don't append to the activity stream on LDAP group disassociate
2017-10-10 14:38:18 -04:00
Ryan Petrello
f2f42c2c8a don't append to the activity stream on LDAP group disassociate
for organizations w/ a large number of ldap orgs/teams, this results in
a _huge_ number of extraneous activity stream entries

see: https://github.com/ansible/ansible-tower/issues/7655
2017-10-10 14:38:18 -04:00
Alan Rominger
70f8ec78de Merge pull request #517 from AlanCoding/vars_exception
fallback to empty dict when processing extra_data
2017-10-10 09:30:06 -04:00
AlanCoding
e2c398ade2 fallback to empty dict when processing extra_data 2017-10-10 08:13:45 -04:00
Alan Rominger
7365e4a63f Merge pull request #516 from AlanCoding/abc_migrations
Fix 3.1.1->3.2.1 migration error
2017-10-09 16:37:35 -04:00
AlanCoding
d4fc4bcd61 fix migration problem from 3.1.1 2017-10-09 15:49:38 -04:00
AlanCoding
4237b9ed5c move 0005a migration to 0005b 2017-10-09 15:48:52 -04:00
Alan Rominger
2dd2541550 Merge pull request #507 from AlanCoding/adhoc_word_smithing
[3.2.2] feedback on ad hoc prohibited vars error msg
2017-10-06 14:15:16 -04:00
AlanCoding
edda5e5420 feedback on ad hoc prohibited vars error msg 2017-10-06 14:07:38 -04:00
Matthew Jones
721674f0cd Merge pull request #502 from wwitzel3/release_3.2.1
[3.2.1] Fix broken migration from 3.1.1/3.1.2 -> 3.2.1
2017-10-06 13:19:34 -04:00
Shane McDonald
f97ca9c42f Fix the way we include i18n files in sdist 2017-10-06 11:57:08 -04:00
Wayne Witzel III
8f883d8d43 Fix migrations to support 3.1.2 -> 3.2.1+ upgrade path 2017-10-06 09:25:43 -04:00
Wayne Witzel III
5bcf704b76 Merge pull request #501 from wwitzel3/release_3.2.1
[3.2.1] Fix missing update_capacity paramenter
2017-10-06 00:37:07 -04:00
Wayne Witzel III
2818bb5833 fix missing parameter to update_capacity method 2017-10-06 00:23:12 -04:00
Alan Rominger
e8b79cde4a Merge pull request #499 from AlanCoding/adhoc_local
[3.2.1] Disallow Ansible vars in adhoc launch serializer + wayne's change
2017-10-05 15:30:06 -04:00
AlanCoding
81c14ce942 fix WARNING log when launching ad hoc command 2017-10-05 13:42:23 -04:00
AlanCoding
eacbeef660 Validate against ansible variables on ad hoc launch
Share code between this check for ad hoc and JT callback
2017-10-05 12:14:05 -04:00
Wayne Witzel III
02e3f45422 do not allow ansible connection type of local for ad_hoc 2017-10-04 17:55:36 -04:00
Chris Meyers
00afc87af1 Merge pull request #493 from chrismeyersfsu/fix-scan_job_migrations_unicode2
fix scan job migration unicode issue
2017-10-03 16:28:54 -04:00
Ryan Petrello
e48bebb761 Merge pull request #495 from ryanpetrello/fix-7713
work around an ansible 2.4 inventory caching bug
2017-10-03 16:26:41 -04:00
Ryan Petrello
4c5ec2fb3a work around an ansible 2.4 inventory caching bug
see: https://github.com/ansible/awx/issues/246
2017-10-03 15:45:11 -04:00
Chris Meyers
cad8710ac7 fix scan job migration unicode issue 2017-10-03 11:31:43 -04:00
Wayne Witzel III
96fd07d0f3 Assert isolated nodes have capacity set to 0 and restored based on version 2017-10-02 14:43:19 -04:00
Wayne Witzel III
692007072d Set capacity to zero if the isolated node has an old version 2017-10-02 14:43:18 -04:00
758 changed files with 30857 additions and 29579 deletions

View File

@@ -14,13 +14,11 @@
<!-- Briefly describe the problem. -->
##### ENVIRONMENT
<!--
* AWX version: X.Y.Z
* AWX install method: openshift, minishift, docker on linux, docker for mac, boot2docker
* Ansible version: X.Y.Z
* Operating System:
* Web Browser:
-->
##### STEPS TO REPRODUCE

2
.gitignore vendored
View File

@@ -49,7 +49,7 @@ __pycache__
/.istanbul.yml
**/node_modules/**
/tmp
npm-debug.log
**/npm-debug.log*
# UI build flag files
awx/ui/.deps_built

View File

@@ -57,7 +57,7 @@ For Linux platforms, refer to the following from Docker:
> https://docs.docker.com/engine/installation/linux/docker-ce/fedora/
**Centos**
**CentOS**
> https://docs.docker.com/engine/installation/linux/docker-ce/centos/
@@ -217,7 +217,7 @@ If you want to start and use the development environment, you'll first need to b
(container)# /bootstrap_development.sh
```
The above will do all the setup tasks, including running database migrations, so it amy take a couple minutes.
The above will do all the setup tasks, including running database migrations, so it may take a couple minutes.
Now you can start each service individually, or start all services in a pre-configured tmux session like so:
@@ -281,7 +281,7 @@ For feature work, take a look at the current [Enhancements](https://github.com/a
If it has someone assigned to it then that person is the person responsible for working the enhancement. If you feel like you could contribute then reach out to that person.
Fixing bugs, adding translations, and updating the documentation are always appreciated, so reviewing the backlog of issues is always a good place to start.
Fixing bugs, adding translations, and updating the documentation are always appreciated, so reviewing the backlog of issues is always a good place to start. For extra information on debugging tools, see [Debugging](https://github.com/ansible/awx/blob/devel/docs/debugging.md).
**NOTE**
@@ -293,7 +293,7 @@ Fixing bugs, adding translations, and updating the documentation are always appr
## Submitting Pull Requests
Fixes and Features for AWX will go through the Github pull request process. Submit your pull request (PR) agains the `devel` branch.
Fixes and Features for AWX will go through the Github pull request process. Submit your pull request (PR) against the `devel` branch.
Here are a few things you can do to help the visibility of your change, and increase the likelihood that it will be accepted:
@@ -312,7 +312,7 @@ It's generally a good idea to discuss features with us first by engaging us in t
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`.
Sometimes it might take us a while to fully review your PR. We try to keep the `devel` branch in good working order, and so we review requests carefuly. Please be patient.
Sometimes it might take us a while to fully review your PR. We try to keep the `devel` branch in good working order, and so we review requests carefully. Please be patient.
All submitted PRs will have the linter and unit tests run against them, and the status reported in the PR.

View File

@@ -8,28 +8,35 @@ This document provides a guide for installing AWX.
- [Clone the repo](#clone-the-repo)
- [AWX branding](#awx-branding)
- [Prerequisites](#prerequisites)
- [System Requirements](#system-requirements)
- [AWX Tunables](#awx-tunables)
- [Choose a deployment platform](#choose-a-deployment-platform)
- [Official vs Building Images](#official-vs-building-images)
- [OpenShift](#openshift)
- [Prerequisites](#prerequisites)
- [Prerequisites](#prerequisites-1)
- [Deploying to Minishift](#deploying-to-minishift)
- [Pre-build steps](#pre-build-steps)
- [PostgreSQL](#postgresql)
- [Start the build](#start-the-build)
- [Post build](#post-build)
- [Accessing AWX](#accessing-awx)
- [Docker](#docker)
- [Kubernetes](#kubernetes)
- [Prerequisites](#prerequisites-2)
- [Pre-build steps](#pre-build-steps-1)
- [Start the build](#start-the-build-1)
- [Accessing AWX](#accessing-awx-1)
- [SSL Termination](#ssl-termination)
- [Docker or Docker Compose](#docker-or-docker-compose)
- [Prerequisites](#prerequisites-3)
- [Pre-build steps](#pre-build-steps-2)
- [Deploying to a remote host](#deploying-to-a-remote-host)
- [Inventory variables](#inventory-variables)
- [Docker registry](#docker-registry)
- [PostgreSQL](#postgresql-1)
- [Proxy settings](#proxy-settings)
- [Start the build](#start-the-build-1)
- [Start the build](#start-the-build-2)
- [Post build](#post-build-1)
- [Accessing AWX](#accessing-awx-1)
- [Accessing AWX](#accessing-awx-2)
## Getting started
@@ -49,11 +56,20 @@ To install the assets, clone the `awx-logos` repo so that it is next to your `aw
Before you can run a deployment, you'll need the following installed in your local environment:
- [Ansible](http://docs.ansible.com/ansible/latest/intro_installation.html) Requires Version 2.3+
- [Ansible](http://docs.ansible.com/ansible/latest/intro_installation.html) Requires Version 2.4+
- [Docker](https://docs.docker.com/engine/installation/)
- [docker-py](https://github.com/docker/docker-py) Python module
- [GNU Make](https://www.gnu.org/software/make/)
- [Git](https://git-scm.com/)
- [Git](https://git-scm.com/) Requires Version 1.8.4+
### System Requirements
The system that runs the AWX service will need to satisfy the following requirements
- At leasts 4GB of memory
- At least 2 cpu cores
- At least 20GB of space
- Running Docker, Openshift, or Kubernetes
### AWX Tunables
@@ -61,11 +77,14 @@ Before you can run a deployment, you'll need the following installed in your loc
### Choose a deployment platform
We currently support running AWX as a containerized application using Docker images deployed to either an OpenShift cluster, or a standalone Docker daemon. The remainder of this document will walk you through the process of building the images, and deploying them to either platform.
We currently support running AWX as a containerized application using Docker images deployed to either an OpenShift cluster, docker-compose or a standalone Docker daemon. The remainder of this document will walk you through the process of building the images, and deploying them to either platform.
The [installer](./installer) directory contains an [inventory](./installer/inventory) file, and a playbook, [install.yml](./installer/install.yml). You'll begin by setting variables in the inventory file according to the platform you wish to use, and then you'll start the image build and deployment process by running the playbook.
In the sections below, you'll find deployment details and instructions for each platform. To deploy to Docker, view the [Docker section](#docker), and for OpenShift, view the [OpenShift section](#openshift).
In the sections below, you'll find deployment details and instructions for each platform:
- [Docker and Docker Compose](#docker-and-docker-compose)
- [OpenShift](#openshift)
- [Kubernetes](#kubernetes).
### Official vs Building Images
@@ -123,10 +142,6 @@ Before starting the build process, review the [inventory](./installer/inventory)
> Name of the OpenShift project that will be created, and used as the namespace for the AWX app. Defaults to *awx*.
*awx_node_port*
> The web server port running inside the AWX pod. Defaults to *30083*.
*openshift_user*
> Username of the OpenShift user that will create the project, and deploy the application. Defaults to *developer*.
@@ -134,7 +149,7 @@ Before starting the build process, review the [inventory](./installer/inventory)
*docker_registry*
> IP address and port, or URL, for accessing a registry that the OpenShift cluster can access. Defaults to *172.30.1.1:5000*, the internal registry delivered with Minishift. This is not needed if you are using official hosted images.
n
*docker_registry_repository*
> Namespace to use when pushing and pulling images to and from the registry. Generally this will match the project name. It defaults to *awx*. This is not needed if you are using official hosted images.
@@ -261,16 +276,88 @@ The above example is taken from a Minishift instance. From a web browser, use `h
Once you access the AWX server, you will be prompted with a login dialog. The default administrator username is `admin`, and the password is `password`.
## Docker
## Kubernetes
### Prerequisites
You will need the following installed on the host where AWX will be deployed:
A Kubernetes deployment will require you to have access to a Kubernetes cluster as well as the following tools:
- [Docker](https://docs.docker.com/engine/installation/)
- [docker-py](https://github.com/docker/docker-py) Python module
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [helm](https://docs.helm.sh/using_helm/#quickstart-guide)
Note: After installing Docker, the Docker service must be started.
The installation program will reference `kubectl` directly. `helm` is only necessary if you are letting the installer configure PostgreSQL for you.
### Pre-build steps
Before starting the build process, review the [inventory](./installer/inventory) file, and uncomment and provide values for the following variables found in the `[all:vars]` section uncommenting when necessary. Make sure the openshift and standalone docker sections are commented out:
*kubernetes_context*
> Prior to running the installer, make sure you've configured the context for the cluster you'll be installing to. This is how the installer knows which cluster to connect to and what authentication to use
*awx_kubernetes_namespace*
> Name of the Kubernetes namespace where the AWX resources will be installed. This will be created if it doesn't exist
*docker_registry_*
> These settings should be used if building your own base images. You'll need access to an external registry and are responsible for making sure your kube cluster can talk to it and use it. If these are undefined and the dockerhub_ configuration settings are uncommented then the images will be pulled from dockerhub instead
### Start the build
After making changes to the `inventory` file use `ansible-playbook` to begin the install
```bash
$ ansible-playbook -i inventory install.yml
```
### Post build
After the playbook run completes, check the status of the deployment by running `kubectl get pods --namespace awx` (replace awx with the namespace you used):
```bash
# View the running pods, it may take a few minutes for everything to be marked in the Running state
$ kubectl get pods --namespace awx
NAME READY STATUS RESTARTS AGE
awx-2558692395-2r8ss 4/4 Running 0 29s
awx-postgresql-355348841-kltkn 1/1 Running 0 1m
```
### Accessing AWX
The AWX web interface is running in the AWX pod behind the `awx-web-svc` service:
```bash
# View available services
$ kubectl get svc --namespace awx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
awx-postgresql ClusterIP 10.7.250.208 <none> 5432/TCP 2m
awx-web-svc NodePort 10.7.241.35 <none> 80:30177/TCP 1m
```
The deployment process creates an `Ingress` named `awx-web-svc` also. Some kubernetes cloud providers will automatically handle routing configuration when an Ingress is created others may require that you more explicitly configure it. You can see what kubernetes knows about things with:
```bash
kubectl get ing --namespace awx
NAME HOSTS ADDRESS PORTS AGE
awx-web-svc * 35.227.x.y 80 3m
```
If your provider is able to allocate an IP Address from the Ingress controller then you can navigate to the address and access the AWX interface. For some providers it can take a few minutes to allocate and make this accessible. For other providers it may require you to manually intervene.
### SSL Termination
Unlike Openshift's `Route` the Kubernetes `Ingress` doesn't yet handle SSL termination. As such the default configuration will only expose AWX through HTTP on port 80. You are responsible for configuring SSL support until support is added (either to Kubernetes or AWX itself).
## Docker or Docker-Compose
### Prerequisites
- [Docker](https://docs.docker.com/engine/installation/) on the host where AWX will be deployed. After installing Docker, the Docker service must be started (depending on your OS, you may have to add the local user that uses Docker to the ``docker`` group, refer to the documentation for details)
- [docker-py](https://github.com/docker/docker-py) Python module.
If you're installing using Docker Compose, you'll need [Docker Compose](https://docs.docker.com/compose/install/).
### Pre-build steps
@@ -313,6 +400,13 @@ Before starting the build process, review the [inventory](./installer/inventory)
> Provide a port number that can be mapped from the Docker daemon host to the web server running inside the AWX container. Defaults to *80*.
*use_docker_compose*
> Switch to ``true`` to use Docker Compose instead of the standalone Docker install.
*docker_compose_dir*
When using docker-compose, the `docker-compose.yml` file will be created there (default `/var/lib/awx`).
#### Docker registry
@@ -330,6 +424,10 @@ If you wish to tag and push built images to a Docker registry, set the following
> Username of the user that will push images to the registry. Defaults to *developer*.
*docker_remove_local_images*
> Due to the way that the docker_image module behaves, images will not be pushed to a remote repository if they are present locally. Set this to delete local versions of the images that will be pushed to the remote. This will fail if containers are currently running from those images.
**Note**
> These settings are ignored if using official images
@@ -390,6 +488,8 @@ e240ed8209cd awx_task:1.0.0.8 "/tini -- /bin/sh ..." 2 minutes ago
97e196120ab3 postgres:9.6 "docker-entrypoint..." 2 minutes ago Up 2 minutes 5432/tcp postgres
```
If you're deploying using Docker Compose, container names will be prefixed by the name of the folder where the docker-compose.yml file is created (by default, `awx`).
Immediately after the containers start, the *awx_task* container will perform required setup tasks, including database migrations. These tasks need to complete before the web interface can be accessed. To monitor the progress, you can follow the container's STDOUT by running the following:
```bash
@@ -452,3 +552,14 @@ Added instance awx to tower
The AWX web server is accessible on the deployment host, using the *host_port* value set in the *inventory* file. The default URL is [http://localhost](http://localhost).
You will prompted with a login dialog. The default administrator username is `admin`, and the password is `password`.
### Maintenance using docker-compose
After the installation, maintenance operations with docker-compose can be done by using the `docker-compose.yml` file created at the location pointed by `docker_compose_dir`.
Among the possible operations, you may:
- Stop AWX : `docker-compose stop`
- Upgrade AWX : `docker-compose pull && docker-compose up --force-recreate`
See the [docker-compose documentation](https://docs.docker.com/compose/) for details.

View File

@@ -1,4 +1,6 @@
recursive-include awx *.py
recursive-include awx *.po
recursive-include awx *.mo
recursive-include awx/static *
recursive-include awx/templates *.html
recursive-include awx/api/templates *.md *.html

View File

@@ -12,10 +12,10 @@ MANAGEMENT_COMMAND ?= awx-manage
IMAGE_REPOSITORY_AUTH ?=
IMAGE_REPOSITORY_BASE ?= https://gcr.io
VERSION=$(shell git describe --long)
VERSION3=$(shell git describe --long | sed 's/\-g.*//')
VERSION3DOT=$(shell git describe --long | sed 's/\-g.*//' | sed 's/\-/\./')
RELEASE_VERSION=$(shell git describe --long | sed 's@\([0-9.]\{1,\}\).*@\1@')
VERSION=$(shell git describe --long --first-parent)
VERSION3=$(shell git describe --long --first-parent | sed 's/\-g.*//')
VERSION3DOT=$(shell git describe --long --first-parent | sed 's/\-g.*//' | sed 's/\-/\./')
RELEASE_VERSION=$(shell git describe --long --first-parent | sed 's@\([0-9.]\{1,\}\).*@\1@')
# NOTE: This defaults the container image version to the branch that's active
COMPOSE_TAG ?= $(GIT_BRANCH)
@@ -83,7 +83,9 @@ I18N_FLAG_FILE = .i18n_built
clean-ui:
rm -rf awx/ui/static/
rm -rf awx/ui/node_modules/
rm -rf awx/ui/coverage/
rm -rf awx/ui/test/unit/reports/
rm -rf awx/ui/test/spec/reports/
rm -rf awx/ui/test/e2e/reports/
rm -rf awx/ui/client/languages/
rm -f $(UI_DEPS_FLAG_FILE)
rm -f $(UI_RELEASE_FLAG_FILE)
@@ -201,8 +203,11 @@ develop:
fi
version_file:
mkdir -p /var/lib/awx/
python -c "import awx as awx; print awx.__version__" > /var/lib/awx/.awx_version
mkdir -p /var/lib/awx/; \
if [ "$(VENV_BASE)" ]; then \
. $(VENV_BASE)/awx/bin/activate; \
fi; \
python -c "import awx as awx; print awx.__version__" > /var/lib/awx/.awx_version; \
# Do any one-time init tasks.
comma := ,
@@ -282,7 +287,7 @@ flower:
@if [ "$(VENV_BASE)" ]; then \
. $(VENV_BASE)/awx/bin/activate; \
fi; \
$(PYTHON) manage.py celery flower --address=0.0.0.0 --port=5555 --broker=amqp://guest:guest@$(RABBITMQ_HOST):5672//
celery flower --address=0.0.0.0 --port=5555 --broker=amqp://guest:guest@$(RABBITMQ_HOST):5672//
collectstatic:
@if [ "$(VENV_BASE)" ]; then \
@@ -294,7 +299,7 @@ uwsgi: collectstatic
@if [ "$(VENV_BASE)" ]; then \
. $(VENV_BASE)/awx/bin/activate; \
fi; \
uwsgi -b 32768 --socket 127.0.0.1:8050 --module=awx.wsgi:application --home=/venv/awx --chdir=/awx_devel/ --vacuum --processes=5 --harakiri=120 --master --no-orphans --py-autoreload 1 --max-requests=1000 --stats /tmp/stats.socket --master-fifo=/awxfifo --lazy-apps --logformat "%(addr) %(method) %(uri) - %(proto) %(status)"
uwsgi -b 32768 --socket 127.0.0.1:8050 --module=awx.wsgi:application --home=/venv/awx --chdir=/awx_devel/ --vacuum --processes=5 --harakiri=120 --master --no-orphans --py-autoreload 1 --max-requests=1000 --stats /tmp/stats.socket --master-fifo=/awxfifo --lazy-apps --logformat "%(addr) %(method) %(uri) - %(proto) %(status)" --hook-accepting1-once="exec:/bin/sh -c '[ -f /tmp/celery_pid ] && kill -1 `cat /tmp/celery_pid`'"
daphne:
@if [ "$(VENV_BASE)" ]; then \
@@ -317,11 +322,11 @@ runserver:
# Run to start the background celery worker for development.
celeryd:
rm -f /tmp/celery_pid
@if [ "$(VENV_BASE)" ]; then \
. $(VENV_BASE)/awx/bin/activate; \
fi; \
$(PYTHON) manage.py celeryd -l DEBUG -B -Ofair --autoreload --autoscale=100,4 --schedule=$(CELERY_SCHEDULE_FILE) -Q tower_scheduler,tower_broadcast_all,$(COMPOSE_HOST),$(AWX_GROUP_QUEUES) -n celery@$(COMPOSE_HOST)
#$(PYTHON) manage.py celery multi show projects jobs default -l DEBUG -Q:projects projects -Q:jobs jobs -Q:default default -c:projects 1 -c:jobs 3 -c:default 3 -Ofair -B --schedule=$(CELERY_SCHEDULE_FILE)
celery worker -A awx -l DEBUG -B -Ofair --autoscale=100,4 --schedule=$(CELERY_SCHEDULE_FILE) -Q tower_scheduler,tower_broadcast_all,$(COMPOSE_HOST),$(AWX_GROUP_QUEUES) -n celery@$(COMPOSE_HOST) --pidfile /tmp/celery_pid
# Run to start the zeromq callback receiver
receiver:
@@ -330,18 +335,18 @@ receiver:
fi; \
$(PYTHON) manage.py run_callback_receiver
socketservice:
@if [ "$(VENV_BASE)" ]; then \
. $(VENV_BASE)/awx/bin/activate; \
fi; \
$(PYTHON) manage.py run_socketio_service
nginx:
nginx -g "daemon off;"
rdb:
$(PYTHON) tools/rdb.py
jupyter:
@if [ "$(VENV_BASE)" ]; then \
. $(VENV_BASE)/awx/bin/activate; \
fi; \
$(MANAGEMENT_COMMAND) shell_plus --notebook
reports:
mkdir -p $@
@@ -495,12 +500,14 @@ ui: clean-ui ui-devel
ui-test-ci: $(UI_DEPS_FLAG_FILE)
$(NPM_BIN) --prefix awx/ui run test:ci
$(NPM_BIN) --prefix awx/ui run unit
testjs_ci:
echo "Update UI unittests later" #ui-test-ci
jshint: $(UI_DEPS_FLAG_FILE)
$(NPM_BIN) run --prefix awx/ui jshint
$(NPM_BIN) run --prefix awx/ui lint
# END UI TASKS
# --------------------------------------
@@ -545,6 +552,7 @@ docker-isolated:
TAG=$(COMPOSE_TAG) DEV_DOCKER_TAG_BASE=$(DEV_DOCKER_TAG_BASE) docker-compose -f tools/docker-compose.yml -f tools/docker-isolated-override.yml create
docker start tools_awx_1
docker start tools_isolated_1
echo "__version__ = '`python setup.py --version`'" | docker exec -i tools_isolated_1 /bin/bash -c "cat > /venv/awx/lib/python2.7/site-packages/awx.py"
if [ "`docker exec -i -t tools_isolated_1 cat /root/.ssh/authorized_keys`" == "`docker exec -t tools_awx_1 cat /root/.ssh/id_rsa.pub`" ]; then \
echo "SSH keys already copied to isolated instance"; \
else \
@@ -600,7 +608,7 @@ clean-elk:
docker rm tools_kibana_1
psql-container:
docker run -it --net tools_default --rm postgres:9.4.1 sh -c 'exec psql -h "postgres" -p "5432" -U postgres'
docker run -it --net tools_default --rm postgres:9.6 sh -c 'exec psql -h "postgres" -p "5432" -U postgres'
VERSION:
@echo $(VERSION_TARGET) > $@

View File

@@ -1,15 +1,17 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.
from __future__ import absolute_import, unicode_literals
import os
import sys
import warnings
from pkg_resources import get_distribution
from .celery import app as celery_app
__version__ = get_distribution('awx').version
__all__ = ['__version__']
__all__ = ['__version__', 'celery_app']
# Check for the presence/absence of "devonly" module to determine if running
# from a source code checkout or release packaage.

View File

@@ -17,7 +17,7 @@ from rest_framework import exceptions
from rest_framework import HTTP_HEADER_ENCODING
# AWX
from awx.main.models import UnifiedJob, AuthToken
from awx.main.models import AuthToken
logger = logging.getLogger('awx.api.authentication')
@@ -137,29 +137,3 @@ class LoggedBasicAuthentication(authentication.BasicAuthentication):
if not settings.AUTH_BASIC_ENABLED:
return
return super(LoggedBasicAuthentication, self).authenticate_header(request)
class TaskAuthentication(authentication.BaseAuthentication):
'''
Custom authentication used for views accessed by the inventory and callback
scripts when running a task.
'''
model = None
def authenticate(self, request):
auth = authentication.get_authorization_header(request).split()
if len(auth) != 2 or auth[0].lower() != 'token' or '-' not in auth[1]:
return None
pk, key = auth[1].split('-', 1)
try:
unified_job = UnifiedJob.objects.get(pk=pk, status='running')
except UnifiedJob.DoesNotExist:
return None
token = unified_job.task_auth_token
if auth[1] != token:
raise exceptions.AuthenticationFailed(_('Invalid task token'))
return (None, token)
def authenticate_header(self, request):
return 'Token'

View File

@@ -22,6 +22,7 @@ from rest_framework.filters import BaseFilterBackend
# AWX
from awx.main.utils import get_type_for_model, to_python_boolean
from awx.main.utils.db import get_all_field_names
from awx.main.models.credential import CredentialType
from awx.main.models.rbac import RoleAncestorEntry
@@ -70,7 +71,7 @@ class TypeFilterBackend(BaseFilterBackend):
types_map[ct_type] = ct.pk
model = queryset.model
model_type = get_type_for_model(model)
if 'polymorphic_ctype' in model._meta.get_all_field_names():
if 'polymorphic_ctype' in get_all_field_names(model):
types_pks = set([v for k,v in types_map.items() if k in types])
queryset = queryset.filter(polymorphic_ctype_id__in=types_pks)
elif model_type in types:
@@ -119,7 +120,7 @@ class FieldLookupBackend(BaseFilterBackend):
'last_updated': 'last_job_run',
}.get(name, name)
if name == 'type' and 'polymorphic_ctype' in model._meta.get_all_field_names():
if name == 'type' and 'polymorphic_ctype' in get_all_field_names(model):
name = 'polymorphic_ctype'
new_parts.append('polymorphic_ctype__model')
else:
@@ -136,7 +137,7 @@ class FieldLookupBackend(BaseFilterBackend):
new_parts.pop()
new_parts.append(name_alt)
else:
field = model._meta.get_field_by_name(name)[0]
field = model._meta.get_field(name)
if isinstance(field, ForeignObjectRel) and getattr(field.field, '__prevent_search__', False):
raise PermissionDenied(_('Filtering on %s is not allowed.' % name))
elif getattr(field, '__prevent_search__', False):
@@ -165,7 +166,13 @@ class FieldLookupBackend(BaseFilterBackend):
elif isinstance(field, models.BooleanField):
return to_python_boolean(value)
elif isinstance(field, (ForeignObjectRel, ManyToManyField, GenericForeignKey, ForeignKey)):
return self.to_python_related(value)
try:
return self.to_python_related(value)
except ValueError:
raise ParseError(_('Invalid {field_name} id: {field_id}').format(
field_name=getattr(field, 'name', 'related field'),
field_id=value)
)
else:
return field.to_python(value)
@@ -242,11 +249,10 @@ class FieldLookupBackend(BaseFilterBackend):
# Search across related objects.
if key.endswith('__search'):
for value in values:
for search_term in force_text(value).replace(',', ' ').split():
search_value, new_keys = self.value_to_python(queryset.model, key, search_term)
assert isinstance(new_keys, list)
for new_key in new_keys:
search_filters.append((new_key, search_value))
search_value, new_keys = self.value_to_python(queryset.model, key, force_text(value))
assert isinstance(new_keys, list)
for new_key in new_keys:
search_filters.append((new_key, search_value))
continue
# Custom chain__ and or__ filters, mutually exclusive (both can
@@ -268,8 +274,10 @@ class FieldLookupBackend(BaseFilterBackend):
# Make legacy v1 Job/Template fields work for backwards compatability
# TODO: remove after API v1 deprecation period
if queryset.model._meta.object_name in ('JobTemplate', 'Job') and key in ('cloud_credential', 'network_credential'):
key = 'extra_credentials'
if queryset.model._meta.object_name in ('JobTemplate', 'Job') and key in (
'credential', 'vault_credential', 'cloud_credential', 'network_credential'
):
key = 'credentials'
# Make legacy v1 Credential fields work for backwards compatability
# TODO: remove after API v1 deprecation period
@@ -375,7 +383,7 @@ class OrderByBackend(BaseFilterBackend):
# given the limited number of views with multiple types,
# sorting on polymorphic_ctype.model is effectively the same.
new_order_by = []
if 'polymorphic_ctype' in queryset.model._meta.get_all_field_names():
if 'polymorphic_ctype' in get_all_field_names(queryset.model):
for field in order_by:
if field == 'type':
new_order_by.append('polymorphic_ctype__model')

View File

@@ -21,7 +21,7 @@ from django.utils.translation import ugettext_lazy as _
# Django REST Framework
from rest_framework.authentication import get_authorization_header
from rest_framework.exceptions import PermissionDenied
from rest_framework.exceptions import PermissionDenied, AuthenticationFailed
from rest_framework import generics
from rest_framework.response import Response
from rest_framework import status
@@ -30,16 +30,19 @@ from rest_framework import views
# AWX
from awx.api.filters import FieldLookupBackend
from awx.main.models import * # noqa
from awx.main.access import access_registry
from awx.main.utils import * # noqa
from awx.main.utils.db import get_all_field_names
from awx.api.serializers import ResourceAccessListElementSerializer
from awx.api.versioning import URLPathVersioning, get_request_version
from awx.api.metadata import SublistAttachDetatchMetadata
__all__ = ['APIView', 'GenericAPIView', 'ListAPIView', 'SimpleListAPIView',
'ListCreateAPIView', 'SubListAPIView', 'SubListCreateAPIView',
'SubListDestroyAPIView',
'SubListCreateAttachDetachAPIView', 'RetrieveAPIView',
'RetrieveUpdateAPIView', 'RetrieveDestroyAPIView',
'RetrieveUpdateDestroyAPIView', 'DestroyAPIView',
'RetrieveUpdateDestroyAPIView',
'SubDetailAPIView',
'ResourceAccessList',
'ParentMixin',
@@ -114,6 +117,10 @@ class APIView(views.APIView):
drf_request = super(APIView, self).initialize_request(request, *args, **kwargs)
request.drf_request = drf_request
try:
request.drf_request_user = getattr(drf_request, 'user', False)
except AuthenticationFailed:
request.drf_request_user = None
return drf_request
def finalize_response(self, request, response, *args, **kwargs):
@@ -139,7 +146,6 @@ class APIView(views.APIView):
response['X-API-Query-Count'] = len(q_times)
response['X-API-Query-Time'] = '%0.3fs' % sum(q_times)
analytics_logger.info("api response", extra=dict(python_objects=dict(request=request, response=response)))
return response
def get_authenticate_header(self, request):
@@ -188,6 +194,7 @@ class APIView(views.APIView):
'new_in_300': getattr(self, 'new_in_300', False),
'new_in_310': getattr(self, 'new_in_310', False),
'new_in_320': getattr(self, 'new_in_320', False),
'new_in_330': getattr(self, 'new_in_330', False),
'new_in_api_v2': getattr(self, 'new_in_api_v2', False),
'deprecated': getattr(self, 'deprecated', False),
}
@@ -267,12 +274,17 @@ class GenericAPIView(generics.GenericAPIView, APIView):
return serializer
def get_queryset(self):
#if hasattr(self.request.user, 'get_queryset'):
# return self.request.user.get_queryset(self.model)
if self.queryset is not None:
return self.queryset._clone()
elif self.model is not None:
return self.model._default_manager.all()
qs = self.model._default_manager
if self.model in access_registry:
access_class = access_registry[self.model]
if access_class.select_related:
qs = qs.select_related(*access_class.select_related)
if access_class.prefetch_related:
qs = qs.prefetch_related(*access_class.prefetch_related)
return qs
else:
return super(GenericAPIView, self).get_queryset()
@@ -321,8 +333,7 @@ class ListAPIView(generics.ListAPIView, GenericAPIView):
return page
def get_description_context(self):
opts = self.model._meta
if 'username' in opts.get_all_field_names():
if 'username' in get_all_field_names(self.model):
order_field = 'username'
else:
order_field = 'name'
@@ -441,6 +452,41 @@ class SubListAPIView(ParentMixin, ListAPIView):
return qs & sublist_qs
class DestroyAPIView(generics.DestroyAPIView):
def has_delete_permission(self, obj):
return self.request.user.can_access(self.model, 'delete', obj)
def perform_destroy(self, instance, check_permission=True):
if check_permission and not self.has_delete_permission(instance):
raise PermissionDenied()
super(DestroyAPIView, self).perform_destroy(instance)
class SubListDestroyAPIView(DestroyAPIView, SubListAPIView):
"""
Concrete view for deleting everything related by `relationship`.
"""
check_sub_obj_permission = True
def destroy(self, request, *args, **kwargs):
instance_list = self.get_queryset()
if (not self.check_sub_obj_permission and
not request.user.can_access(self.parent_model, 'delete', self.get_parent_object())):
raise PermissionDenied()
self.perform_list_destroy(instance_list)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_list_destroy(self, instance_list):
if self.check_sub_obj_permission:
# Check permissions for all before deleting, avoiding half-deleted lists
for instance in instance_list:
if self.has_delete_permission(instance):
raise PermissionDenied()
for instance in instance_list:
self.perform_destroy(instance, check_permission=False)
class SubListCreateAPIView(SubListAPIView, ListCreateAPIView):
# Base class for a sublist view that allows for creating subobjects
# associated with the parent object.
@@ -679,22 +725,11 @@ class RetrieveUpdateAPIView(RetrieveAPIView, generics.RetrieveUpdateAPIView):
pass
class RetrieveDestroyAPIView(RetrieveAPIView, generics.RetrieveDestroyAPIView):
def destroy(self, request, *args, **kwargs):
# somewhat lame that delete has to call it's own permissions check
obj = self.get_object()
if not request.user.can_access(self.model, 'delete', obj):
raise PermissionDenied()
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class RetrieveUpdateDestroyAPIView(RetrieveUpdateAPIView, RetrieveDestroyAPIView):
class RetrieveDestroyAPIView(RetrieveAPIView, DestroyAPIView):
pass
class DestroyAPIView(GenericAPIView, generics.DestroyAPIView):
class RetrieveUpdateDestroyAPIView(RetrieveUpdateAPIView, DestroyAPIView):
pass

View File

@@ -52,14 +52,18 @@ class ModelAccessPermission(permissions.BasePermission):
if not check_user_access(request.user, view.model, 'add', {view.parent_key: parent_obj}):
return False
return True
elif getattr(view, 'is_job_start', False):
elif hasattr(view, 'obj_permission_type'):
# Generic object-centric view permission check without object not needed
if not obj:
return True
return check_user_access(request.user, view.model, 'start', obj)
elif getattr(view, 'is_job_cancel', False):
if not obj:
return True
return check_user_access(request.user, view.model, 'cancel', obj)
# Permission check that happens when get_object() is called
extra_kwargs = {}
if view.obj_permission_type == 'admin':
extra_kwargs['data'] = {}
return check_user_access(
request.user, view.model, view.obj_permission_type, obj,
**extra_kwargs
)
else:
if obj:
return True

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,9 @@
The resulting data structure contains:
{
"count": 99,
"next": null,
"previous": null,
"count": 99,
"next": null,
"previous": null,
"results": [
...
]
@@ -60,6 +60,10 @@ _Added in AWX 1.4_
?related__search=findme
Note: If you want to provide more than one search terms, please use multiple
search fields with the same key, like `?related__search=foo&related__search=bar`,
All search terms with the same key will be ORed together.
## Filtering
Any additional query string parameters may be used to filter the list of
@@ -70,7 +74,7 @@ in the specified value should be url-encoded. For example:
?field=value%20xyz
Fields may also span relations, only for fields and relationships defined in
the database:
the database:
?other__field=value

View File

@@ -10,4 +10,5 @@
{% if new_in_300 %}> _Added in Ansible Tower 3.0.0_{% endif %}
{% if new_in_310 %}> _New in Ansible Tower 3.1.0_{% endif %}
{% if new_in_320 %}> _New in Ansible Tower 3.2.0_{% endif %}
{% if new_in_330 %}> _New in Ansible Tower 3.3.0_{% endif %}
{% endif %}

View File

@@ -0,0 +1,12 @@
Create a schedule based on a job:
Make a POST request to this endpoint to create a schedule that launches
the job template that launched this job, and uses the same
parameters that the job was launched with. These parameters include all
"prompted" resources such as `extra_vars`, `inventory`, `limit`, etc.
Jobs that were launched with user-provided passwords cannot have a schedule
created from them.
Make a GET request for information about what those prompts are and
whether or not a schedule can be created.

View File

@@ -26,9 +26,6 @@ The response will include the following fields:
job_template (array, read-only)
* `survey_enabled`: Flag indicating whether the job_template has an enabled
survey (boolean, read-only)
* `credential_needed_to_start`: Flag indicating the presence of a credential
associated with the job template. If not then one should be supplied when
launching the job (boolean, read-only)
* `inventory_needed_to_start`: Flag indicating the presence of an inventory
associated with the job template. If not then one should be supplied when
launching the job (boolean, read-only)
@@ -36,9 +33,8 @@ The response will include the following fields:
Make a POST request to this resource to launch the job_template. If any
passwords, inventory, or extra variables (extra_vars) are required, they must
be passed via POST data, with extra_vars given as a YAML or JSON string and
escaped parentheses. If `credential_needed_to_start` is `True` then the
`credential` field is required and if the `inventory_needed_to_start` is
`True` then the `inventory` is required as well.
escaped parentheses. If the `inventory_needed_to_start` is `True` then the
`inventory` is required.
If successful, the response status code will be 201. If any required passwords
are not provided, a 400 status code will be returned. If the job cannot be

View File

@@ -0,0 +1,6 @@
{% include "api/sub_list_create_api_view.md" %}
# Delete all {{ model_verbose_name_plural }} of this {{ parent_model_verbose_name|title }}:
Make a DELETE request to this resource to delete all {{ model_verbose_name_plural }} show in the list.
The {{ parent_model_verbose_name|title }} will not be deleted by this request.

View File

@@ -1,420 +0,0 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.
# noqa
from django.conf.urls import include, patterns, url as original_url
def url(regex, view, kwargs=None, name=None, prefix=''):
# Set default name from view name (if a string).
if isinstance(view, basestring) and name is None:
name = view
return original_url(regex, view, kwargs, name, prefix)
organization_urls = patterns('awx.api.views',
url(r'^$', 'organization_list'),
url(r'^(?P<pk>[0-9]+)/$', 'organization_detail'),
url(r'^(?P<pk>[0-9]+)/users/$', 'organization_users_list'),
url(r'^(?P<pk>[0-9]+)/admins/$', 'organization_admins_list'),
url(r'^(?P<pk>[0-9]+)/inventories/$', 'organization_inventories_list'),
url(r'^(?P<pk>[0-9]+)/projects/$', 'organization_projects_list'),
url(r'^(?P<pk>[0-9]+)/workflow_job_templates/$', 'organization_workflow_job_templates_list'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'organization_teams_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', 'organization_credential_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'organization_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates/$', 'organization_notification_templates_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', 'organization_notification_templates_any_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', 'organization_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', 'organization_notification_templates_success_list'),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', 'organization_instance_groups_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', 'organization_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', 'organization_access_list'),
)
user_urls = patterns('awx.api.views',
url(r'^$', 'user_list'),
url(r'^(?P<pk>[0-9]+)/$', 'user_detail'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'user_teams_list'),
url(r'^(?P<pk>[0-9]+)/organizations/$', 'user_organizations_list'),
url(r'^(?P<pk>[0-9]+)/admin_of_organizations/$', 'user_admin_of_organizations_list'),
url(r'^(?P<pk>[0-9]+)/projects/$', 'user_projects_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', 'user_credentials_list'),
url(r'^(?P<pk>[0-9]+)/roles/$', 'user_roles_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'user_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', 'user_access_list'),
)
project_urls = patterns('awx.api.views',
url(r'^$', 'project_list'),
url(r'^(?P<pk>[0-9]+)/$', 'project_detail'),
url(r'^(?P<pk>[0-9]+)/playbooks/$', 'project_playbooks'),
url(r'^(?P<pk>[0-9]+)/inventories/$', 'project_inventories'),
url(r'^(?P<pk>[0-9]+)/scm_inventory_sources/$', 'project_scm_inventory_sources'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'project_teams_list'),
url(r'^(?P<pk>[0-9]+)/update/$', 'project_update_view'),
url(r'^(?P<pk>[0-9]+)/project_updates/$', 'project_updates_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'project_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/schedules/$', 'project_schedules_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', 'project_notification_templates_any_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', 'project_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', 'project_notification_templates_success_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', 'project_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', 'project_access_list'),
)
project_update_urls = patterns('awx.api.views',
url(r'^$', 'project_update_list'),
url(r'^(?P<pk>[0-9]+)/$', 'project_update_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'project_update_cancel'),
url(r'^(?P<pk>[0-9]+)/stdout/$', 'project_update_stdout'),
url(r'^(?P<pk>[0-9]+)/scm_inventory_updates/$', 'project_update_scm_inventory_updates'),
url(r'^(?P<pk>[0-9]+)/notifications/$', 'project_update_notifications_list'),
)
team_urls = patterns('awx.api.views',
url(r'^$', 'team_list'),
url(r'^(?P<pk>[0-9]+)/$', 'team_detail'),
url(r'^(?P<pk>[0-9]+)/projects/$', 'team_projects_list'),
url(r'^(?P<pk>[0-9]+)/users/$', 'team_users_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', 'team_credentials_list'),
url(r'^(?P<pk>[0-9]+)/roles/$', 'team_roles_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', 'team_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'team_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', 'team_access_list'),
)
inventory_urls = patterns('awx.api.views',
url(r'^$', 'inventory_list'),
url(r'^(?P<pk>[0-9]+)/$', 'inventory_detail'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'inventory_hosts_list'),
url(r'^(?P<pk>[0-9]+)/groups/$', 'inventory_groups_list'),
url(r'^(?P<pk>[0-9]+)/root_groups/$', 'inventory_root_groups_list'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'inventory_variable_data'),
url(r'^(?P<pk>[0-9]+)/script/$', 'inventory_script_view'),
url(r'^(?P<pk>[0-9]+)/tree/$', 'inventory_tree_view'),
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'inventory_inventory_sources_list'),
url(r'^(?P<pk>[0-9]+)/update_inventory_sources/$', 'inventory_inventory_sources_update'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'inventory_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/job_templates/$', 'inventory_job_template_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', 'inventory_ad_hoc_commands_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', 'inventory_access_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', 'inventory_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', 'inventory_instance_groups_list'),
#url(r'^(?P<pk>[0-9]+)/single_fact/$', 'inventory_single_fact_view'),
)
host_urls = patterns('awx.api.views',
url(r'^$', 'host_list'),
url(r'^(?P<pk>[0-9]+)/$', 'host_detail'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'host_variable_data'),
url(r'^(?P<pk>[0-9]+)/groups/$', 'host_groups_list'),
url(r'^(?P<pk>[0-9]+)/all_groups/$', 'host_all_groups_list'),
url(r'^(?P<pk>[0-9]+)/job_events/', 'host_job_events_list'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'host_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'host_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'host_inventory_sources_list'),
url(r'^(?P<pk>[0-9]+)/smart_inventories/$', 'host_smart_inventories_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', 'host_ad_hoc_commands_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_command_events/$', 'host_ad_hoc_command_events_list'),
#url(r'^(?P<pk>[0-9]+)/single_fact/$', 'host_single_fact_view'),
url(r'^(?P<pk>[0-9]+)/fact_versions/$', 'host_fact_versions_list'),
url(r'^(?P<pk>[0-9]+)/fact_view/$', 'host_fact_compare_view'),
url(r'^(?P<pk>[0-9]+)/insights/$', 'host_insights'),
)
group_urls = patterns('awx.api.views',
url(r'^$', 'group_list'),
url(r'^(?P<pk>[0-9]+)/$', 'group_detail'),
url(r'^(?P<pk>[0-9]+)/children/$', 'group_children_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'group_hosts_list'),
url(r'^(?P<pk>[0-9]+)/all_hosts/$', 'group_all_hosts_list'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'group_variable_data'),
url(r'^(?P<pk>[0-9]+)/job_events/$', 'group_job_events_list'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'group_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/potential_children/$', 'group_potential_children_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'group_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'group_inventory_sources_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', 'group_ad_hoc_commands_list'),
#url(r'^(?P<pk>[0-9]+)/single_fact/$', 'group_single_fact_view'),
)
inventory_source_urls = patterns('awx.api.views',
url(r'^$', 'inventory_source_list'),
url(r'^(?P<pk>[0-9]+)/$', 'inventory_source_detail'),
url(r'^(?P<pk>[0-9]+)/update/$', 'inventory_source_update_view'),
url(r'^(?P<pk>[0-9]+)/inventory_updates/$', 'inventory_source_updates_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'inventory_source_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/schedules/$', 'inventory_source_schedules_list'),
url(r'^(?P<pk>[0-9]+)/groups/$', 'inventory_source_groups_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'inventory_source_hosts_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', 'inventory_source_notification_templates_any_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', 'inventory_source_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', 'inventory_source_notification_templates_success_list'),
)
inventory_update_urls = patterns('awx.api.views',
url(r'^$', 'inventory_update_list'),
url(r'^(?P<pk>[0-9]+)/$', 'inventory_update_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'inventory_update_cancel'),
url(r'^(?P<pk>[0-9]+)/stdout/$', 'inventory_update_stdout'),
url(r'^(?P<pk>[0-9]+)/notifications/$', 'inventory_update_notifications_list'),
)
inventory_script_urls = patterns('awx.api.views',
url(r'^$', 'inventory_script_list'),
url(r'^(?P<pk>[0-9]+)/$', 'inventory_script_detail'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', 'inventory_script_object_roles_list'),
)
credential_type_urls = patterns('awx.api.views',
url(r'^$', 'credential_type_list'),
url(r'^(?P<pk>[0-9]+)/$', 'credential_type_detail'),
url(r'^(?P<pk>[0-9]+)/credentials/$', 'credential_type_credential_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'credential_type_activity_stream_list'),
)
credential_urls = patterns('awx.api.views',
url(r'^$', 'credential_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'credential_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/$', 'credential_detail'),
url(r'^(?P<pk>[0-9]+)/access_list/$', 'credential_access_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', 'credential_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/owner_users/$', 'credential_owner_users_list'),
url(r'^(?P<pk>[0-9]+)/owner_teams/$', 'credential_owner_teams_list'),
# See also credentials resources on users/teams.
)
role_urls = patterns('awx.api.views',
url(r'^$', 'role_list'),
url(r'^(?P<pk>[0-9]+)/$', 'role_detail'),
url(r'^(?P<pk>[0-9]+)/users/$', 'role_users_list'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'role_teams_list'),
url(r'^(?P<pk>[0-9]+)/parents/$', 'role_parents_list'),
url(r'^(?P<pk>[0-9]+)/children/$', 'role_children_list'),
)
job_template_urls = patterns('awx.api.views',
url(r'^$', 'job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_template_detail'),
url(r'^(?P<pk>[0-9]+)/launch/$', 'job_template_launch'),
url(r'^(?P<pk>[0-9]+)/jobs/$', 'job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/callback/$', 'job_template_callback'),
url(r'^(?P<pk>[0-9]+)/schedules/$', 'job_template_schedules_list'),
url(r'^(?P<pk>[0-9]+)/survey_spec/$', 'job_template_survey_spec'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'job_template_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', 'job_template_notification_templates_any_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', 'job_template_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', 'job_template_notification_templates_success_list'),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', 'job_template_instance_groups_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', 'job_template_access_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', 'job_template_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', 'job_template_label_list'),
)
job_urls = patterns('awx.api.views',
url(r'^$', 'job_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_detail'),
url(r'^(?P<pk>[0-9]+)/start/$', 'job_start'), # TODO: remove in 3.3
url(r'^(?P<pk>[0-9]+)/cancel/$', 'job_cancel'),
url(r'^(?P<pk>[0-9]+)/relaunch/$', 'job_relaunch'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'job_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/job_events/$', 'job_job_events_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'job_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/stdout/$', 'job_stdout'),
url(r'^(?P<pk>[0-9]+)/notifications/$', 'job_notifications_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', 'job_label_list'),
)
job_host_summary_urls = patterns('awx.api.views',
url(r'^(?P<pk>[0-9]+)/$', 'job_host_summary_detail'),
)
job_event_urls = patterns('awx.api.views',
url(r'^$', 'job_event_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_event_detail'),
url(r'^(?P<pk>[0-9]+)/children/$', 'job_event_children_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'job_event_hosts_list'),
)
ad_hoc_command_urls = patterns('awx.api.views',
url(r'^$', 'ad_hoc_command_list'),
url(r'^(?P<pk>[0-9]+)/$', 'ad_hoc_command_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'ad_hoc_command_cancel'),
url(r'^(?P<pk>[0-9]+)/relaunch/$', 'ad_hoc_command_relaunch'),
url(r'^(?P<pk>[0-9]+)/events/$', 'ad_hoc_command_ad_hoc_command_events_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'ad_hoc_command_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notifications/$', 'ad_hoc_command_notifications_list'),
url(r'^(?P<pk>[0-9]+)/stdout/$', 'ad_hoc_command_stdout'),
)
ad_hoc_command_event_urls = patterns('awx.api.views',
url(r'^$', 'ad_hoc_command_event_list'),
url(r'^(?P<pk>[0-9]+)/$', 'ad_hoc_command_event_detail'),
)
system_job_template_urls = patterns('awx.api.views',
url(r'^$', 'system_job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', 'system_job_template_detail'),
url(r'^(?P<pk>[0-9]+)/launch/$', 'system_job_template_launch'),
url(r'^(?P<pk>[0-9]+)/jobs/$', 'system_job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/schedules/$', 'system_job_template_schedules_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', 'system_job_template_notification_templates_any_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', 'system_job_template_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', 'system_job_template_notification_templates_success_list'),
)
system_job_urls = patterns('awx.api.views',
url(r'^$', 'system_job_list'),
url(r'^(?P<pk>[0-9]+)/$', 'system_job_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'system_job_cancel'),
url(r'^(?P<pk>[0-9]+)/notifications/$', 'system_job_notifications_list'),
)
workflow_job_template_urls = patterns('awx.api.views',
url(r'^$', 'workflow_job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', 'workflow_job_template_detail'),
url(r'^(?P<pk>[0-9]+)/workflow_jobs/$', 'workflow_job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/launch/$', 'workflow_job_template_launch'),
url(r'^(?P<pk>[0-9]+)/copy/$', 'workflow_job_template_copy'),
url(r'^(?P<pk>[0-9]+)/schedules/$', 'workflow_job_template_schedules_list'),
url(r'^(?P<pk>[0-9]+)/survey_spec/$', 'workflow_job_template_survey_spec'),
url(r'^(?P<pk>[0-9]+)/workflow_nodes/$', 'workflow_job_template_workflow_nodes_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'workflow_job_template_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', 'workflow_job_template_notification_templates_any_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', 'workflow_job_template_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', 'workflow_job_template_notification_templates_success_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', 'workflow_job_template_access_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', 'workflow_job_template_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', 'workflow_job_template_label_list'),
)
workflow_job_urls = patterns('awx.api.views',
url(r'^$', 'workflow_job_list'),
url(r'^(?P<pk>[0-9]+)/$', 'workflow_job_detail'),
url(r'^(?P<pk>[0-9]+)/workflow_nodes/$', 'workflow_job_workflow_nodes_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', 'workflow_job_label_list'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'workflow_job_cancel'),
url(r'^(?P<pk>[0-9]+)/relaunch/$', 'workflow_job_relaunch'),
url(r'^(?P<pk>[0-9]+)/notifications/$', 'workflow_job_notifications_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'workflow_job_activity_stream_list'),
)
notification_template_urls = patterns('awx.api.views',
url(r'^$', 'notification_template_list'),
url(r'^(?P<pk>[0-9]+)/$', 'notification_template_detail'),
url(r'^(?P<pk>[0-9]+)/test/$', 'notification_template_test'),
url(r'^(?P<pk>[0-9]+)/notifications/$', 'notification_template_notification_list'),
)
notification_urls = patterns('awx.api.views',
url(r'^$', 'notification_list'),
url(r'^(?P<pk>[0-9]+)/$', 'notification_detail'),
)
label_urls = patterns('awx.api.views',
url(r'^$', 'label_list'),
url(r'^(?P<pk>[0-9]+)/$', 'label_detail'),
)
workflow_job_template_node_urls = patterns('awx.api.views',
url(r'^$', 'workflow_job_template_node_list'),
url(r'^(?P<pk>[0-9]+)/$', 'workflow_job_template_node_detail'),
url(r'^(?P<pk>[0-9]+)/success_nodes/$', 'workflow_job_template_node_success_nodes_list'),
url(r'^(?P<pk>[0-9]+)/failure_nodes/$', 'workflow_job_template_node_failure_nodes_list'),
url(r'^(?P<pk>[0-9]+)/always_nodes/$', 'workflow_job_template_node_always_nodes_list'),
)
workflow_job_node_urls = patterns('awx.api.views',
url(r'^$', 'workflow_job_node_list'),
url(r'^(?P<pk>[0-9]+)/$', 'workflow_job_node_detail'),
url(r'^(?P<pk>[0-9]+)/success_nodes/$', 'workflow_job_node_success_nodes_list'),
url(r'^(?P<pk>[0-9]+)/failure_nodes/$', 'workflow_job_node_failure_nodes_list'),
url(r'^(?P<pk>[0-9]+)/always_nodes/$', 'workflow_job_node_always_nodes_list'),
)
schedule_urls = patterns('awx.api.views',
url(r'^$', 'schedule_list'),
url(r'^(?P<pk>[0-9]+)/$', 'schedule_detail'),
url(r'^(?P<pk>[0-9]+)/jobs/$', 'schedule_unified_jobs_list'),
)
activity_stream_urls = patterns('awx.api.views',
url(r'^$', 'activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/$', 'activity_stream_detail'),
)
instance_urls = patterns('awx.api.views',
url(r'^$', 'instance_list'),
url(r'^(?P<pk>[0-9]+)/$', 'instance_detail'),
url(r'^(?P<pk>[0-9]+)/jobs/$', 'instance_unified_jobs_list'),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', 'instance_instance_groups_list'),
)
instance_group_urls = patterns('awx.api.views',
url(r'^$', 'instance_group_list'),
url(r'^(?P<pk>[0-9]+)/$', 'instance_group_detail'),
url(r'^(?P<pk>[0-9]+)/jobs/$', 'instance_group_unified_jobs_list'),
url(r'^(?P<pk>[0-9]+)/instances/$', 'instance_group_instance_list'),
)
v1_urls = patterns('awx.api.views',
url(r'^$', 'api_v1_root_view'),
url(r'^ping/$', 'api_v1_ping_view'),
url(r'^config/$', 'api_v1_config_view'),
url(r'^auth/$', 'auth_view'),
url(r'^authtoken/$', 'auth_token_view'),
url(r'^me/$', 'user_me_list'),
url(r'^dashboard/$', 'dashboard_view'),
url(r'^dashboard/graphs/jobs/$','dashboard_jobs_graph_view'),
url(r'^settings/', include('awx.conf.urls')),
url(r'^instances/', include(instance_urls)),
url(r'^instance_groups/', include(instance_group_urls)),
url(r'^schedules/', include(schedule_urls)),
url(r'^organizations/', include(organization_urls)),
url(r'^users/', include(user_urls)),
url(r'^projects/', include(project_urls)),
url(r'^project_updates/', include(project_update_urls)),
url(r'^teams/', include(team_urls)),
url(r'^inventories/', include(inventory_urls)),
url(r'^hosts/', include(host_urls)),
url(r'^groups/', include(group_urls)),
url(r'^inventory_sources/', include(inventory_source_urls)),
url(r'^inventory_updates/', include(inventory_update_urls)),
url(r'^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)),
url(r'^jobs/', include(job_urls)),
url(r'^job_host_summaries/', include(job_host_summary_urls)),
url(r'^job_events/', include(job_event_urls)),
url(r'^ad_hoc_commands/', include(ad_hoc_command_urls)),
url(r'^ad_hoc_command_events/', include(ad_hoc_command_event_urls)),
url(r'^system_job_templates/', include(system_job_template_urls)),
url(r'^system_jobs/', include(system_job_urls)),
url(r'^notification_templates/', include(notification_template_urls)),
url(r'^notifications/', include(notification_urls)),
url(r'^workflow_job_templates/',include(workflow_job_template_urls)),
url(r'^workflow_jobs/' ,include(workflow_job_urls)),
url(r'^labels/', include(label_urls)),
url(r'^workflow_job_template_nodes/', include(workflow_job_template_node_urls)),
url(r'^workflow_job_nodes/', include(workflow_job_node_urls)),
url(r'^unified_job_templates/$','unified_job_template_list'),
url(r'^unified_jobs/$', 'unified_job_list'),
url(r'^activity_stream/', include(activity_stream_urls)),
)
v2_urls = patterns('awx.api.views',
url(r'^$', 'api_v2_root_view'),
url(r'^credential_types/', include(credential_type_urls)),
url(r'^hosts/(?P<pk>[0-9]+)/ansible_facts/$', 'host_ansible_facts_detail'),
url(r'^jobs/(?P<pk>[0-9]+)/extra_credentials/$', 'job_extra_credentials_list'),
url(r'^job_templates/(?P<pk>[0-9]+)/extra_credentials/$', 'job_template_extra_credentials_list'),
)
urlpatterns = patterns('awx.api.views',
url(r'^$', 'api_root_view'),
url(r'^(?P<version>(v2))/', include(v2_urls)),
url(r'^(?P<version>(v1|v2))/', include(v1_urls))
)

0
awx/api/urls/Pipfile Normal file
View File

7
awx/api/urls/__init__.py Normal file
View File

@@ -0,0 +1,7 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from __future__ import absolute_import, unicode_literals
from .urls import urlpatterns
__all__ = ['urlpatterns']

View File

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

View File

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

View File

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

View File

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

View File

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

37
awx/api/urls/group.py Normal file
View File

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

43
awx/api/urls/host.py Normal file
View File

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

22
awx/api/urls/instance.py Normal file
View File

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

View File

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

45
awx/api/urls/inventory.py Normal file
View File

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

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from awx.api.views import (
InventoryScriptList,
InventoryScriptDetail,
InventoryScriptObjectRolesList,
)
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'),
]
__all__ = ['urls']

View File

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

View File

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

39
awx/api/urls/job.py Normal file
View File

@@ -0,0 +1,39 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from awx.api.views import (
JobList,
JobDetail,
JobStart,
JobCancel,
JobRelaunch,
JobCreateSchedule,
JobJobHostSummariesList,
JobJobEventsList,
JobActivityStreamList,
JobStdout,
JobNotificationsList,
JobLabelList,
JobHostSummaryDetail,
)
urls = [
url(r'^$', JobList.as_view(), name='job_list'),
url(r'^(?P<pk>[0-9]+)/$', JobDetail.as_view(), name='job_detail'),
url(r'^(?P<pk>[0-9]+)/start/$', JobStart.as_view(), name='job_start'), # Todo: Remove In 3.3
url(r'^(?P<pk>[0-9]+)/cancel/$', JobCancel.as_view(), name='job_cancel'),
url(r'^(?P<pk>[0-9]+)/relaunch/$', JobRelaunch.as_view(), name='job_relaunch'),
url(r'^(?P<pk>[0-9]+)/create_schedule/$', JobCreateSchedule.as_view(), name='job_create_schedule'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', JobJobHostSummariesList.as_view(), name='job_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/job_events/$', JobJobEventsList.as_view(), name='job_job_events_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', JobActivityStreamList.as_view(), name='job_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/stdout/$', JobStdout.as_view(), name='job_stdout'),
url(r'^(?P<pk>[0-9]+)/notifications/$', JobNotificationsList.as_view(), name='job_notifications_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', JobLabelList.as_view(), name='job_label_list'),
url(r'^(?P<pk>[0-9]+)/$', JobHostSummaryDetail.as_view(), name='job_host_summary_detail'),
]
__all__ = ['urls']

21
awx/api/urls/job_event.py Normal file
View File

@@ -0,0 +1,21 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from awx.api.views import (
JobEventList,
JobEventDetail,
JobEventChildrenList,
JobEventHostsList,
)
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

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

View File

@@ -0,0 +1,46 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from awx.api.views import (
JobTemplateList,
JobTemplateDetail,
JobTemplateLaunch,
JobTemplateJobsList,
JobTemplateCallback,
JobTemplateSchedulesList,
JobTemplateSurveySpec,
JobTemplateActivityStreamList,
JobTemplateNotificationTemplatesAnyList,
JobTemplateNotificationTemplatesErrorList,
JobTemplateNotificationTemplatesSuccessList,
JobTemplateInstanceGroupsList,
JobTemplateAccessList,
JobTemplateObjectRolesList,
JobTemplateLabelList,
)
urls = [
url(r'^$', JobTemplateList.as_view(), name='job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', JobTemplateDetail.as_view(), name='job_template_detail'),
url(r'^(?P<pk>[0-9]+)/launch/$', JobTemplateLaunch.as_view(), name='job_template_launch'),
url(r'^(?P<pk>[0-9]+)/jobs/$', JobTemplateJobsList.as_view(), name='job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/callback/$', JobTemplateCallback.as_view(), name='job_template_callback'),
url(r'^(?P<pk>[0-9]+)/schedules/$', JobTemplateSchedulesList.as_view(), name='job_template_schedules_list'),
url(r'^(?P<pk>[0-9]+)/survey_spec/$', JobTemplateSurveySpec.as_view(), name='job_template_survey_spec'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', JobTemplateActivityStreamList.as_view(), name='job_template_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', JobTemplateNotificationTemplatesAnyList.as_view(),
name='job_template_notification_templates_any_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', JobTemplateNotificationTemplatesErrorList.as_view(),
name='job_template_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', JobTemplateNotificationTemplatesSuccessList.as_view(),
name='job_template_notification_templates_success_list'),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', JobTemplateInstanceGroupsList.as_view(), name='job_template_instance_groups_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', JobTemplateAccessList.as_view(), name='job_template_access_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', JobTemplateObjectRolesList.as_view(), name='job_template_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', JobTemplateLabelList.as_view(), name='job_template_label_list'),
]
__all__ = ['urls']

17
awx/api/urls/label.py Normal file
View File

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

View File

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

View File

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

View File

@@ -0,0 +1,50 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from django.conf.urls import url
from awx.api.views import (
OrganizationList,
OrganizationDetail,
OrganizationUsersList,
OrganizationAdminsList,
OrganizationInventoriesList,
OrganizationProjectsList,
OrganizationWorkflowJobTemplatesList,
OrganizationTeamsList,
OrganizationCredentialList,
OrganizationActivityStreamList,
OrganizationNotificationTemplatesList,
OrganizationNotificationTemplatesAnyList,
OrganizationNotificationTemplatesErrorList,
OrganizationNotificationTemplatesSuccessList,
OrganizationInstanceGroupsList,
OrganizationObjectRolesList,
OrganizationAccessList,
)
urls = [
url(r'^$', OrganizationList.as_view(), name='organization_list'),
url(r'^(?P<pk>[0-9]+)/$', OrganizationDetail.as_view(), name='organization_detail'),
url(r'^(?P<pk>[0-9]+)/users/$', OrganizationUsersList.as_view(), name='organization_users_list'),
url(r'^(?P<pk>[0-9]+)/admins/$', OrganizationAdminsList.as_view(), name='organization_admins_list'),
url(r'^(?P<pk>[0-9]+)/inventories/$', OrganizationInventoriesList.as_view(), name='organization_inventories_list'),
url(r'^(?P<pk>[0-9]+)/projects/$', OrganizationProjectsList.as_view(), name='organization_projects_list'),
url(r'^(?P<pk>[0-9]+)/workflow_job_templates/$', OrganizationWorkflowJobTemplatesList.as_view(), name='organization_workflow_job_templates_list'),
url(r'^(?P<pk>[0-9]+)/teams/$', OrganizationTeamsList.as_view(), name='organization_teams_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', OrganizationCredentialList.as_view(), name='organization_credential_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', OrganizationActivityStreamList.as_view(), name='organization_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates/$', OrganizationNotificationTemplatesList.as_view(), name='organization_notification_templates_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', OrganizationNotificationTemplatesAnyList.as_view(),
name='organization_notification_templates_any_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', OrganizationNotificationTemplatesErrorList.as_view(),
name='organization_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', OrganizationNotificationTemplatesSuccessList.as_view(),
name='organization_notification_templates_success_list'),
url(r'^(?P<pk>[0-9]+)/instance_groups/$', OrganizationInstanceGroupsList.as_view(), name='organization_instance_groups_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', OrganizationObjectRolesList.as_view(), name='organization_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', OrganizationAccessList.as_view(), name='organization_access_list'),
]
__all__ = ['urls']

44
awx/api/urls/project.py Normal file
View File

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

View File

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

25
awx/api/urls/role.py Normal file
View File

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

21
awx/api/urls/schedule.py Normal file
View File

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

View File

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

View File

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

31
awx/api/urls/team.py Normal file
View File

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

127
awx/api/urls/urls.py Normal file
View File

@@ -0,0 +1,127 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.
from __future__ import absolute_import, unicode_literals
from django.conf.urls import include, url
from awx.api.views import (
ApiRootView,
ApiV1RootView,
ApiV2RootView,
ApiV1PingView,
ApiV1ConfigView,
AuthView,
AuthTokenView,
UserMeList,
DashboardView,
DashboardJobsGraphView,
UnifiedJobTemplateList,
UnifiedJobList,
HostAnsibleFactsDetail,
JobCredentialsList,
JobExtraCredentialsList,
JobTemplateCredentialsList,
JobTemplateExtraCredentialsList,
SchedulePreview,
ScheduleZoneInfo,
)
from .organization import urls as organization_urls
from .user import urls as user_urls
from .project import urls as project_urls
from .project_update import urls as project_update_urls
from .inventory import urls as inventory_urls
from .team import urls as team_urls
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 .role import urls as role_urls
from .job_template import urls as job_template_urls
from .job import urls as job_urls
from .job_host_summary import urls as job_host_summary_urls
from .job_event import urls as job_event_urls
from .ad_hoc_command import urls as ad_hoc_command_urls
from .ad_hoc_command_event import urls as ad_hoc_command_event_urls
from .system_job_template import urls as system_job_template_urls
from .system_job import urls as system_job_urls
from .workflow_job_template import urls as workflow_job_template_urls
from .workflow_job import urls as workflow_job_urls
from .notification_template import urls as notification_template_urls
from .notification import urls as notification_urls
from .label import urls as label_urls
from .workflow_job_template_node import urls as workflow_job_template_node_urls
from .workflow_job_node import urls as workflow_job_node_urls
from .schedule import urls as schedule_urls
from .activity_stream import urls as activity_stream_urls
from .instance import urls as instance_urls
from .instance_group import urls as instance_group_urls
v1_urls = [
url(r'^$', ApiV1RootView.as_view(), name='api_v1_root_view'),
url(r'^ping/$', ApiV1PingView.as_view(), name='api_v1_ping_view'),
url(r'^config/$', ApiV1ConfigView.as_view(), name='api_v1_config_view'),
url(r'^auth/$', AuthView.as_view()),
url(r'^authtoken/$', AuthTokenView.as_view(), name='auth_token_view'),
url(r'^me/$', UserMeList.as_view(), name='user_me_list'),
url(r'^dashboard/$', DashboardView.as_view(), name='dashboard_view'),
url(r'^dashboard/graphs/jobs/$', DashboardJobsGraphView.as_view(), name='dashboard_jobs_graph_view'),
url(r'^settings/', include('awx.conf.urls')),
url(r'^instances/', include(instance_urls)),
url(r'^instance_groups/', include(instance_group_urls)),
url(r'^schedules/', include(schedule_urls)),
url(r'^organizations/', include(organization_urls)),
url(r'^users/', include(user_urls)),
url(r'^projects/', include(project_urls)),
url(r'^project_updates/', include(project_update_urls)),
url(r'^teams/', include(team_urls)),
url(r'^inventories/', include(inventory_urls)),
url(r'^hosts/', include(host_urls)),
url(r'^groups/', include(group_urls)),
url(r'^inventory_sources/', include(inventory_source_urls)),
url(r'^inventory_updates/', include(inventory_update_urls)),
url(r'^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)),
url(r'^jobs/', include(job_urls)),
url(r'^job_host_summaries/', include(job_host_summary_urls)),
url(r'^job_events/', include(job_event_urls)),
url(r'^ad_hoc_commands/', include(ad_hoc_command_urls)),
url(r'^ad_hoc_command_events/', include(ad_hoc_command_event_urls)),
url(r'^system_job_templates/', include(system_job_template_urls)),
url(r'^system_jobs/', include(system_job_urls)),
url(r'^notification_templates/', include(notification_template_urls)),
url(r'^notifications/', include(notification_urls)),
url(r'^workflow_job_templates/', include(workflow_job_template_urls)),
url(r'^workflow_jobs/', include(workflow_job_urls)),
url(r'^labels/', include(label_urls)),
url(r'^workflow_job_template_nodes/', include(workflow_job_template_node_urls)),
url(r'^workflow_job_nodes/', include(workflow_job_node_urls)),
url(r'^unified_job_templates/$', UnifiedJobTemplateList.as_view(), name='unified_job_template_list'),
url(r'^unified_jobs/$', UnifiedJobList.as_view(), name='unified_job_list'),
url(r'^activity_stream/', include(activity_stream_urls)),
]
v2_urls = [
url(r'^$', ApiV2RootView.as_view(), name='api_v2_root_view'),
url(r'^credential_types/', include(credential_type_urls)),
url(r'^hosts/(?P<pk>[0-9]+)/ansible_facts/$', HostAnsibleFactsDetail.as_view(), name='host_ansible_facts_detail'),
url(r'^jobs/(?P<pk>[0-9]+)/extra_credentials/$', JobExtraCredentialsList.as_view(), name='job_extra_credentials_list'),
url(r'^jobs/(?P<pk>[0-9]+)/credentials/$', JobCredentialsList.as_view(), name='job_credentials_list'),
url(r'^job_templates/(?P<pk>[0-9]+)/extra_credentials/$', JobTemplateExtraCredentialsList.as_view(), name='job_template_extra_credentials_list'),
url(r'^job_templates/(?P<pk>[0-9]+)/credentials/$', JobTemplateCredentialsList.as_view(), name='job_template_credentials_list'),
url(r'^schedules/preview/$', SchedulePreview.as_view(), name='schedule_rrule'),
url(r'^schedules/zoneinfo/$', ScheduleZoneInfo.as_view(), name='schedule_zoneinfo'),
]
app_name = 'api'
urlpatterns = [
url(r'^$', ApiRootView.as_view(), name='api_root_view'),
url(r'^(?P<version>(v2))/', include(v2_urls)),
url(r'^(?P<version>(v1|v2))/', include(v1_urls))
]

33
awx/api/urls/user.py Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

23
awx/celery.py Normal file
View File

@@ -0,0 +1,23 @@
# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
try:
import awx.devonly # noqa
MODE = 'development'
except ImportError: # pragma: no cover
MODE = 'production'
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'awx.settings.%s' % MODE)
app = Celery('awx')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
if __name__ == '__main__':
app.start()

View File

@@ -1,6 +1,7 @@
# Python
import logging
import urlparse
from collections import OrderedDict
# Django
from django.core.validators import URLValidator
@@ -53,6 +54,47 @@ class StringListField(ListField):
return super(StringListField, self).to_representation(value)
class StringListBooleanField(ListField):
default_error_messages = {
'type_error': _('Expected None, True, False, a string or list of strings but got {input_type} instead.'),
}
child = CharField()
def to_representation(self, value):
try:
if isinstance(value, (list, tuple)):
return super(StringListBooleanField, self).to_representation(value)
elif value in NullBooleanField.TRUE_VALUES:
return True
elif value in NullBooleanField.FALSE_VALUES:
return False
elif value in NullBooleanField.NULL_VALUES:
return None
elif isinstance(value, basestring):
return self.child.to_representation(value)
except TypeError:
pass
self.fail('type_error', input_type=type(value))
def to_internal_value(self, data):
try:
if isinstance(data, (list, tuple)):
return super(StringListBooleanField, self).to_internal_value(data)
elif data in NullBooleanField.TRUE_VALUES:
return True
elif data in NullBooleanField.FALSE_VALUES:
return False
elif data in NullBooleanField.NULL_VALUES:
return None
elif isinstance(data, basestring):
return self.child.run_validation(data)
except TypeError:
pass
self.fail('type_error', input_type=type(data))
class URLField(CharField):
def __init__(self, **kwargs):
@@ -83,7 +125,7 @@ class URLField(CharField):
else:
netloc = '{}@{}' % (url_parts.username, netloc)
value = urlparse.urlunsplit([url_parts.scheme, netloc, url_parts.path, url_parts.query, url_parts.fragment])
except:
except Exception:
raise # If something fails here, just fall through and let the validators check it.
super(URLField, self).run_validators(value)
@@ -98,5 +140,29 @@ class KeyValueField(DictField):
ret = super(KeyValueField, self).to_internal_value(data)
for value in data.values():
if not isinstance(value, six.string_types + six.integer_types + (float,)):
if isinstance(value, OrderedDict):
value = dict(value)
self.fail('invalid_child', input=value)
return ret
class ListTuplesField(ListField):
default_error_messages = {
'type_error': _('Expected a list of tuples of max length 2 but got {input_type} instead.'),
}
def to_representation(self, value):
if isinstance(value, (list, tuple)):
return super(ListTuplesField, self).to_representation(value)
else:
self.fail('type_error', input_type=type(value))
def to_internal_value(self, data):
if isinstance(data, list):
for x in data:
if not isinstance(x, (list, tuple)) or len(x) > 2:
self.fail('type_error', input_type=type(x))
return super(ListTuplesField, self).to_internal_value(data)
else:
self.fail('type_error', input_type=type(data))

View File

@@ -120,6 +120,9 @@ class SettingsRegistry(object):
def is_setting_read_only(self, setting):
return bool(self._registry.get(setting, {}).get('read_only', False))
def get_setting_category(self, setting):
return self._registry.get(setting, {}).get('category_slug', None)
def get_setting_field(self, setting, mixin_class=None, for_user=False, **kwargs):
from rest_framework.fields import empty
field_kwargs = {}
@@ -159,14 +162,14 @@ class SettingsRegistry(object):
if category_slug == 'user' and for_user:
try:
field_instance.default = original_field_instance.to_representation(getattr(self.settings, setting))
except:
except Exception:
logger.warning('Unable to retrieve default value for user setting "%s".', setting, exc_info=True)
elif not field_instance.read_only or field_instance.default is empty or field_instance.defined_in_file:
try:
field_instance.default = original_field_instance.to_representation(self.settings._awx_conf_settings._get_default(setting))
except AttributeError:
pass
except:
except Exception:
logger.warning('Unable to retrieve default value for setting "%s".', setting, exc_info=True)
# `PENDO_TRACKING_STATE` is disabled for the open source awx license

View File

@@ -16,7 +16,7 @@ class SettingSerializer(BaseSerializer):
class Meta:
model = Setting
fields = ('id', 'key', 'value')
readonly_fields = ('id', 'key', 'value')
read_only_fields = ('id', 'key', 'value')
def __init__(self, instance=None, data=serializers.empty, **kwargs):
if instance is None and data is not serializers.empty and 'key' in data:
@@ -87,8 +87,10 @@ class SettingSingletonSerializer(serializers.Serializer):
if self.instance and not hasattr(self.instance, key):
continue
extra_kwargs = {}
# Make LICENSE read-only here; update via /api/v1/config/ only.
if key == 'LICENSE':
# Make LICENSE and AWX_ISOLATED_KEY_GENERATION read-only here;
# LICENSE is only updated via /api/v1/config/
# AWX_ISOLATED_KEY_GENERATION is only set/unset via the setup playbook
if key in ('LICENSE', 'AWX_ISOLATED_KEY_GENERATION'):
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

@@ -9,10 +9,12 @@ import time
import six
# Django
from django.conf import LazySettings
from django.conf import settings, UserSettingsHolder
from django.core.cache import cache as django_cache
from django.core.exceptions import ImproperlyConfigured
from django.db import ProgrammingError, OperationalError
from django.utils.functional import cached_property
# Django REST Framework
from rest_framework.fields import empty, SkipField
@@ -229,7 +231,8 @@ class SettingsWrapper(UserSettingsHolder):
self.__dict__['cache'] = EncryptedCacheProxy(cache, registry)
self.__dict__['registry'] = registry
def _get_supported_settings(self):
@cached_property
def all_supported_settings(self):
return self.registry.get_registered_settings()
def _preload_cache(self):
@@ -366,7 +369,7 @@ class SettingsWrapper(UserSettingsHolder):
return internal_value
else:
return field.run_validation(value)
except:
except Exception:
logger.warning(
'The current value "%r" for setting "%s" is invalid.',
value, name, exc_info=True)
@@ -381,7 +384,7 @@ class SettingsWrapper(UserSettingsHolder):
def __getattr__(self, name):
value = empty
if name in self._get_supported_settings():
if name in self.all_supported_settings:
with _log_database_error():
value = self._get_local(name)
if value is not empty:
@@ -413,7 +416,7 @@ class SettingsWrapper(UserSettingsHolder):
# post_save handler will delete from cache when changed.
def __setattr__(self, name, value):
if name in self._get_supported_settings():
if name in self.all_supported_settings:
with _log_database_error():
self._set_local(name, value)
else:
@@ -429,7 +432,7 @@ class SettingsWrapper(UserSettingsHolder):
# pre_delete handler will delete from cache.
def __delattr__(self, name):
if name in self._get_supported_settings():
if name in self.all_supported_settings:
with _log_database_error():
self._del_local(name)
else:
@@ -439,7 +442,7 @@ class SettingsWrapper(UserSettingsHolder):
keys = []
with _log_database_error():
for setting in Setting.objects.filter(
key__in=self._get_supported_settings(), user__isnull=True):
key__in=self.all_supported_settings, user__isnull=True):
# Skip returning settings that have been overridden but are
# considered to be "not set".
if setting.value is None and SETTING_CACHE_NOTSET == SETTING_CACHE_NONE:
@@ -453,8 +456,24 @@ class SettingsWrapper(UserSettingsHolder):
def is_overridden(self, setting):
set_locally = False
if setting in self._get_supported_settings():
if setting in self.all_supported_settings:
with _log_database_error():
set_locally = Setting.objects.filter(key=setting, user__isnull=True).exists()
set_on_default = getattr(self.default_settings, 'is_overridden', lambda s: False)(setting)
return (set_locally or set_on_default)
def __getattr_without_cache__(self, name):
# Django 1.10 added an optimization to settings lookup:
# https://code.djangoproject.com/ticket/27625
# https://github.com/django/django/commit/c1b221a9b913315998a1bcec2f29a9361a74d1ac
# This change caches settings lookups on the __dict__ of the LazySettings
# object, which is not okay to do in an environment where settings can
# change in-process (the entire point of awx's custom settings implementation)
# This restores the original behavior that *does not* cache.
if self._wrapped is empty:
self._setup(name)
return getattr(self._wrapped, name)
LazySettings.__getattr__ = __getattr_without_cache__

View File

@@ -0,0 +1,86 @@
import pytest
from rest_framework.fields import ValidationError
from awx.conf.fields import StringListBooleanField, ListTuplesField
class TestStringListBooleanField():
FIELD_VALUES = [
("hello", "hello"),
(("a", "b"), ["a", "b"]),
(["a", "b", 1, 3.13, "foo", "bar", "foobar"], ["a", "b", "1", "3.13", "foo", "bar", "foobar"]),
("True", True),
("TRUE", True),
("true", True),
(True, True),
("False", False),
("FALSE", False),
("false", False),
(False, False),
("", None),
("null", None),
("NULL", None),
]
FIELD_VALUES_INVALID = [
1.245,
{"a": "b"},
]
@pytest.mark.parametrize("value_in, value_known", FIELD_VALUES)
def test_to_internal_value_valid(self, value_in, value_known):
field = StringListBooleanField()
v = field.to_internal_value(value_in)
assert v == value_known
@pytest.mark.parametrize("value", FIELD_VALUES_INVALID)
def test_to_internal_value_invalid(self, value):
field = StringListBooleanField()
with pytest.raises(ValidationError) as e:
field.to_internal_value(value)
assert e.value.detail[0] == "Expected None, True, False, a string or list " \
"of strings but got {} instead.".format(type(value))
@pytest.mark.parametrize("value_in, value_known", FIELD_VALUES)
def test_to_representation_valid(self, value_in, value_known):
field = StringListBooleanField()
v = field.to_representation(value_in)
assert v == value_known
@pytest.mark.parametrize("value", FIELD_VALUES_INVALID)
def test_to_representation_invalid(self, value):
field = StringListBooleanField()
with pytest.raises(ValidationError) as e:
field.to_representation(value)
assert e.value.detail[0] == "Expected None, True, False, a string or list " \
"of strings but got {} instead.".format(type(value))
class TestListTuplesField():
FIELD_VALUES = [
([('a', 'b'), ('abc', '123')], [("a", "b"), ("abc", "123")]),
]
FIELD_VALUES_INVALID = [
("abc", type("abc")),
([('a', 'b', 'c'), ('abc', '123', '456')], type(('a',))),
(['a', 'b'], type('a')),
(123, type(123)),
]
@pytest.mark.parametrize("value_in, value_known", FIELD_VALUES)
def test_to_internal_value_valid(self, value_in, value_known):
field = ListTuplesField()
v = field.to_internal_value(value_in)
assert v == value_known
@pytest.mark.parametrize("value, t", FIELD_VALUES_INVALID)
def test_to_internal_value_invalid(self, value, t):
field = ListTuplesField()
with pytest.raises(ValidationError) as e:
field.to_internal_value(value)
assert e.value.detail[0] == "Expected a list of tuples of max length 2 " \
"but got {} instead.".format(t)

View File

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

View File

@@ -6,10 +6,10 @@ import glob
import os
import shutil
# RedBaron
from redbaron import RedBaron, indent
# AWX
from awx.conf.registry import settings_registry
__all__ = ['comment_assignments']
__all__ = ['comment_assignments', 'conf_to_dict']
def comment_assignments(patterns, assignment_names, dry_run=True, backup_suffix='.old'):
@@ -30,6 +30,8 @@ def comment_assignments(patterns, assignment_names, dry_run=True, backup_suffix=
def comment_assignments_in_file(filename, assignment_names, dry_run=True, backup_filename=None):
from redbaron import RedBaron, indent
if isinstance(assignment_names, basestring):
assignment_names = [assignment_names]
else:
@@ -103,6 +105,13 @@ def comment_assignments_in_file(filename, assignment_names, dry_run=True, backup
return '\n'.join(diff_lines)
def conf_to_dict(obj):
return {
'category': settings_registry.get_setting_category(obj.key),
'name': obj.key,
}
if __name__ == '__main__':
pattern = os.path.join(os.path.dirname(__file__), '..', 'settings', 'local_*.py')
diffs = comment_assignments(pattern, ['AUTH_LDAP_ORGANIZATION_MAP'])

View File

@@ -123,6 +123,8 @@ class EventContext(object):
event_data['job_id'] = int(os.getenv('JOB_ID', '0'))
if os.getenv('AD_HOC_COMMAND_ID', ''):
event_data['ad_hoc_command_id'] = int(os.getenv('AD_HOC_COMMAND_ID', '0'))
if os.getenv('PROJECT_UPDATE_ID', ''):
event_data['project_update_id'] = int(os.getenv('PROJECT_UPDATE_ID', '0'))
event_data.setdefault('pid', os.getpid())
event_data.setdefault('uuid', str(uuid.uuid4()))
event_data.setdefault('created', datetime.datetime.utcnow().isoformat())
@@ -145,7 +147,7 @@ class EventContext(object):
event_data['res'] = {}
event_dict = dict(event=event, event_data=event_data)
for key in event_data.keys():
if key in ('job_id', 'ad_hoc_command_id', 'uuid', 'parent_uuid', 'created',):
if key in ('job_id', 'ad_hoc_command_id', 'project_update_id', 'uuid', 'parent_uuid', 'created',):
event_dict[key] = event_data.pop(key)
elif key in ('verbosity', 'pid'):
event_dict[key] = event_data[key]

View File

@@ -16,7 +16,7 @@ class argv_placeholder(object):
def __del__(self):
try:
argv_ready(sys.argv)
except:
except Exception:
pass

View File

@@ -1,3 +1,8 @@
# Copyright (c) 2017 Ansible by Red Hat
# All Rights Reserved
from __future__ import absolute_import
from collections import OrderedDict
import json
import mock
@@ -23,9 +28,9 @@ with mock.patch.dict(os.environ, {'ANSIBLE_STDOUT_CALLBACK': CALLBACK,
'ANSIBLE_CALLBACK_PLUGINS': PLUGINS}):
from ansible.cli.playbook import PlaybookCLI
from ansible.executor.playbook_executor import PlaybookExecutor
from ansible.inventory import Inventory
from ansible.inventory.manager import InventoryManager
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.vars.manager import VariableManager
# Add awx/lib to sys.path so we can use the plugin
path = os.path.abspath(os.path.join(PLUGINS, '..', '..'))
@@ -62,9 +67,8 @@ def executor(tmpdir_factory, request):
cli.parse()
options = cli.parser.parse_args(['-v'])[0]
loader = DataLoader()
variable_manager = VariableManager()
inventory = Inventory(loader=loader, variable_manager=variable_manager,
host_list=['localhost'])
variable_manager = VariableManager(loader=loader)
inventory = InventoryManager(loader=loader, sources='localhost,')
variable_manager.set_inventory(inventory)
return PlaybookExecutor(playbooks=playbook_files, inventory=inventory,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -70,14 +70,9 @@ register(
label=_('Remote Host Headers'),
help_text=_('HTTP headers and meta keys to search to determine remote host '
'name or IP. Add additional items to this list, such as '
'"HTTP_X_FORWARDED_FOR", if behind a reverse proxy.\n\n'
'Note: The headers will be searched in order and the first '
'found remote host name or IP will be used.\n\n'
'In the below example 8.8.8.7 would be the chosen IP address.\n'
'X-Forwarded-For: 8.8.8.7, 192.168.2.1, 127.0.0.1\n'
'Host: 127.0.0.1\n'
'REMOTE_HOST_HEADERS = [\'HTTP_X_FORWARDED_FOR\', '
'\'REMOTE_ADDR\', \'REMOTE_HOST\']'),
'"HTTP_X_FORWARDED_FOR", if behind a reverse proxy. '
'See the "Proxy Support" section of the Adminstrator guide for'
'more details.'),
category=_('System'),
category_slug='system',
)
@@ -88,9 +83,7 @@ register(
label=_('Proxy IP Whitelist'),
help_text=_("If Tower is behind a reverse proxy/load balancer, use this setting "
"to whitelist the proxy IP addresses from which Tower should trust "
"custom REMOTE_HOST_HEADERS header values\n"
"REMOTE_HOST_HEADERS = ['HTTP_X_FORWARDED_FOR', ''REMOTE_ADDR', 'REMOTE_HOST']\n"
"PROXY_IP_WHITELIST = ['10.0.1.100', '10.0.1.101']\n"
"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')"),
category=_('System'),
@@ -105,7 +98,7 @@ def _load_default_license_from_file():
license_data = json.load(open(license_file))
logger.debug('Read license data from "%s".', license_file)
return license_data
except:
except Exception:
logger.warning('Could not read license from "%s".', license_file, exc_info=True)
return {}
@@ -268,7 +261,8 @@ register(
field_class=fields.IntegerField,
min_value=0,
label=_('Job Event Standard Output Maximum Display Size'),
help_text=_(u'Maximum Size of Standard Output in bytes to display for a single job or ad hoc command event. `stdout` will end with `\u2026` when truncated.'),
help_text=_(
u'Maximum Size of Standard Output in bytes to display for a single job or ad hoc command event. `stdout` will end with `\u2026` when truncated.'),
category=_('Jobs'),
category_slug='jobs',
)

View File

@@ -5,7 +5,9 @@ import re
from django.utils.translation import ugettext_lazy as _
CLOUD_PROVIDERS = ('azure_rm', 'ec2', 'gce', 'vmware', 'openstack', 'satellite6', 'cloudforms')
CLOUD_PROVIDERS = ('azure_rm', 'ec2', 'gce', 'vmware', 'openstack', 'rhv', 'satellite6', 'cloudforms', 'tower')
SCHEDULEABLE_PROVIDERS = CLOUD_PROVIDERS + ('custom', 'scm',)
PRIVILEGE_ESCALATION_METHODS = [ ('sudo', _('Sudo')), ('su', _('Su')), ('pbrun', _('Pbrun')), ('pfexec', _('Pfexec')), ('dzdo', _('DZDO')), ('pmrun', _('Pmrun')), ('runas', _('Runas'))]
PRIVILEGE_ESCALATION_METHODS = [
('sudo', _('Sudo')), ('su', _('Su')), ('pbrun', _('Pbrun')), ('pfexec', _('Pfexec')),
('dzdo', _('DZDO')), ('pmrun', _('Pmrun')), ('runas', _('Runas'))]
ANSI_SGR_PATTERN = re.compile(r'\x1b\[[0-9;]*m')

View File

@@ -24,7 +24,7 @@ def discard_groups(message):
@channel_session
def ws_connect(message):
connect_text = {'accept':False, 'user':None}
message.reply_channel.send({"accept": True})
message.content['method'] = 'FAKE'
request = AsgiRequest(message)
@@ -35,11 +35,12 @@ def ws_connect(message):
auth_token = AuthToken.objects.get(key=token)
if auth_token.in_valid_tokens:
message.channel_session['user_id'] = auth_token.user_id
connect_text['accept'] = True
connect_text['user'] = auth_token.user_id
message.reply_channel.send({"text": json.dumps({"accept": True, "user": auth_token.user_id})})
return None
except AuthToken.DoesNotExist:
logger.error("auth_token provided was invalid.")
message.reply_channel.send({"text": json.dumps(connect_text)})
message.reply_channel.send({"close": True})
return None
@channel_session
@@ -81,7 +82,8 @@ def ws_receive(message):
if access_cls is not None:
user_access = access_cls(user)
if not user_access.get_queryset().filter(pk=oid).exists():
message.reply_channel.send({"text": json.dumps({"error": "access denied to channel {0} for resource id {1}".format(group_name, oid)})})
message.reply_channel.send({"text": json.dumps(
{"error": "access denied to channel {0} for resource id {1}".format(group_name, oid)})})
continue
current_groups.add(name)
Group(name).add(message.reply_channel)

View File

@@ -1,24 +1,36 @@
class AwxTaskError(Exception):
"""Base exception for errors in unified job runs"""
def __init__(self, task, message=None):
# Copyright (c) 2018 Ansible by Red Hat
# All Rights Reserved.
# Celery does not respect exception type when using a serializer different than pickle;
# and awx uses the json serializer
# https://github.com/celery/celery/issues/3586
class _AwxTaskError():
def build_exception(self, task, message=None):
if message is None:
message = "Execution error running {}".format(task.log_format)
super(AwxTaskError, self).__init__(message)
self.task = task
class TaskCancel(AwxTaskError):
"""Canceled flag caused run_pexpect to kill the job run"""
def __init__(self, task, rc):
super(TaskCancel, self).__init__(
task, message="{} was canceled (rc={})".format(task.log_format, rc))
self.rc = rc
e = Exception(message)
e.task = task
e.is_awx_task_error = True
return e
def TaskCancel(self, task, rc):
"""Canceled flag caused run_pexpect to kill the job run"""
message="{} was canceled (rc={})".format(task.log_format, rc)
e = self.build_exception(task, message)
e.rc = rc
e.awx_task_error_type = "TaskCancel"
return e
def TaskError(self, task, rc):
"""Userspace error (non-zero exit code) in run_pexpect subprocess"""
message = "{} encountered an error (rc={}), please see task stdout for details.".format(task.log_format, rc)
e = self.build_exception(task, message)
e.rc = rc
e.awx_task_error_type = "TaskError"
return e
class TaskError(AwxTaskError):
"""Userspace error (non-zero exit code) in run_pexpect subprocess"""
def __init__(self, task, rc):
super(TaskError, self).__init__(
task, message="%s encountered an error (rc=%s), please see task stdout for details.".format(task.log_format, rc))
self.rc = rc
AwxTaskError = _AwxTaskError()

View File

@@ -1,5 +1,4 @@
import base64
import cStringIO
import codecs
import StringIO
import json
@@ -9,6 +8,7 @@ import stat
import tempfile
import time
import logging
from distutils.version import LooseVersion as Version
from django.conf import settings
@@ -142,7 +142,7 @@ class IsolatedManager(object):
# if an ssh private key fifo exists, read its contents and delete it
if self.ssh_key_path:
buff = cStringIO.StringIO()
buff = StringIO.StringIO()
with open(self.ssh_key_path, 'r') as fifo:
for line in fifo:
buff.write(line)
@@ -182,7 +182,7 @@ class IsolatedManager(object):
job_timeout=settings.AWX_ISOLATED_LAUNCH_TIMEOUT,
pexpect_timeout=5
)
output = buff.getvalue()
output = buff.getvalue().encode('utf-8')
playbook_logger.info('Isolated job {} dispatch:\n{}'.format(self.instance.id, output))
if status != 'successful':
self.stdout_handle.write(output)
@@ -282,7 +282,7 @@ class IsolatedManager(object):
status = 'failed'
output = ''
rc = None
buff = cStringIO.StringIO()
buff = StringIO.StringIO()
last_check = time.time()
seek = 0
job_timeout = remaining = self.job_timeout
@@ -303,7 +303,7 @@ class IsolatedManager(object):
time.sleep(1)
continue
buff = cStringIO.StringIO()
buff = StringIO.StringIO()
logger.debug('Checking on isolated job {} with `check_isolated.yml`.'.format(self.instance.id))
status, rc = IsolatedManager.run_pexpect(
args, self.awx_playbook_path(), self.management_env, buff,
@@ -313,7 +313,7 @@ class IsolatedManager(object):
pexpect_timeout=5,
proot_cmd=self.proot_cmd
)
output = buff.getvalue()
output = buff.getvalue().encode('utf-8')
playbook_logger.info('Isolated job {} check:\n{}'.format(self.instance.id, output))
path = self.path_to('artifacts', 'stdout')
@@ -355,14 +355,14 @@ class IsolatedManager(object):
}
args = self._build_args('clean_isolated.yml', '%s,' % self.host, extra_vars)
logger.debug('Cleaning up job {} on isolated host with `clean_isolated.yml` playbook.'.format(self.instance.id))
buff = cStringIO.StringIO()
buff = StringIO.StringIO()
timeout = max(60, 2 * settings.AWX_ISOLATED_CONNECTION_TIMEOUT)
status, rc = IsolatedManager.run_pexpect(
args, self.awx_playbook_path(), self.management_env, buff,
idle_timeout=timeout, job_timeout=timeout,
pexpect_timeout=5
)
output = buff.getvalue()
output = buff.getvalue().encode('utf-8')
playbook_logger.info('Isolated job {} cleanup:\n{}'.format(self.instance.id, output))
if status != 'successful':
@@ -370,7 +370,24 @@ class IsolatedManager(object):
logger.warning('Isolated job {} cleanup error, output:\n{}'.format(self.instance.id, output))
@classmethod
def health_check(cls, instance_qs):
def update_capacity(cls, instance, task_result, awx_application_version):
instance.version = task_result['version']
isolated_version = instance.version.split("-", 1)[0]
cluster_version = awx_application_version.split("-", 1)[0]
if Version(cluster_version) > Version(isolated_version):
err_template = "Isolated instance {} reports version {}, cluster node is at {}, setting capacity to zero."
logger.error(err_template.format(instance.hostname, instance.version, awx_application_version))
instance.capacity = 0
else:
if instance.capacity == 0 and task_result['capacity']:
logger.warning('Isolated instance {} has re-joined.'.format(instance.hostname))
instance.capacity = int(task_result['capacity'])
instance.save(update_fields=['capacity', 'version', 'modified'])
@classmethod
def health_check(cls, instance_qs, awx_application_version):
'''
:param instance_qs: List of Django objects representing the
isolated instances to manage
@@ -388,14 +405,14 @@ class IsolatedManager(object):
env = cls._base_management_env()
env['ANSIBLE_STDOUT_CALLBACK'] = 'json'
buff = cStringIO.StringIO()
buff = StringIO.StringIO()
timeout = max(60, 2 * settings.AWX_ISOLATED_CONNECTION_TIMEOUT)
status, rc = IsolatedManager.run_pexpect(
args, cls.awx_playbook_path(), env, buff,
idle_timeout=timeout, job_timeout=timeout,
pexpect_timeout=5
)
output = buff.getvalue()
output = buff.getvalue().encode('utf-8')
buff.close()
try:
@@ -412,11 +429,7 @@ class IsolatedManager(object):
except (KeyError, IndexError):
task_result = {}
if 'capacity' in task_result:
instance.version = task_result['version']
if instance.capacity == 0 and task_result['capacity']:
logger.warning('Isolated instance {} has re-joined.'.format(instance.hostname))
instance.capacity = int(task_result['capacity'])
instance.save(update_fields=['capacity', 'version', 'modified'])
cls.update_capacity(instance, task_result, awx_application_version)
elif instance.capacity == 0:
logger.debug('Isolated instance {} previously marked as lost, could not re-join.'.format(
instance.hostname))
@@ -431,7 +444,7 @@ class IsolatedManager(object):
instance.hostname, instance.modified))
@staticmethod
def wrap_stdout_handle(instance, private_data_dir, stdout_handle, event_data_key='job_id'):
def get_stdout_handle(instance, private_data_dir, event_data_key='job_id'):
dispatcher = CallbackQueueDispatcher()
def job_event_callback(event_data):
@@ -449,7 +462,7 @@ class IsolatedManager(object):
event_data.get('event', ''), event_data['uuid'], instance.id, event_data))
dispatcher.dispatch(event_data)
return OutputEventFilter(stdout_handle, job_event_callback)
return OutputEventFilter(job_event_callback)
def run(self, instance, host, private_data_dir, proot_temp_dir):
"""

View File

@@ -99,7 +99,6 @@ def run_pexpect(args, cwd, env, logfile,
password_patterns = expect_passwords.keys()
password_values = expect_passwords.values()
logfile_pos = logfile.tell()
child = pexpect.spawn(
args[0], args[1:], cwd=cwd, env=env, ignore_sighup=True,
encoding='utf-8', echo=False,
@@ -116,13 +115,11 @@ def run_pexpect(args, cwd, env, logfile,
password = password_values[result_id]
if password is not None:
child.sendline(password)
if logfile_pos != logfile.tell():
logfile_pos = logfile.tell()
last_stdout_update = time.time()
if cancelled_callback:
try:
canceled = cancelled_callback()
except:
except Exception:
logger.exception('Could not check cancel callback - canceling immediately')
if isinstance(extra_update_fields, dict):
extra_update_fields['job_explanation'] = "System error during job execution, check system logs"
@@ -271,12 +268,8 @@ def __run__(private_data_dir):
if __name__ == '__main__':
__version__ = '3.2.0'
try:
import awx
__version__ = awx.__version__
except ImportError:
pass # in devel, `awx` isn't an installed package
import awx
__version__ = awx.__version__
parser = argparse.ArgumentParser(description='manage a daemonized, isolated ansible playbook')
parser.add_argument('--version', action='version', version=__version__ + '-isolated')
parser.add_argument('command', choices=['start', 'stop', 'is-alive'])

View File

@@ -6,6 +6,7 @@ import copy
import json
import re
import six
import urllib
from jinja2 import Environment, StrictUndefined
from jinja2.exceptions import UndefinedError
@@ -18,12 +19,12 @@ from django.db.models.signals import (
)
from django.db.models.signals import m2m_changed
from django.db import models
from django.db.models.fields.related import (
add_lazy_relation,
SingleRelatedObjectDescriptor,
ReverseSingleRelatedObjectDescriptor,
ManyRelatedObjectsDescriptor,
ReverseManyRelatedObjectsDescriptor,
from django.db.models.fields.related import add_lazy_relation
from django.db.models.fields.related_descriptors import (
ReverseOneToOneDescriptor,
ForwardManyToOneDescriptor,
ManyToManyDescriptor,
ReverseManyToOneDescriptor,
)
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@@ -96,7 +97,7 @@ class JSONBField(upstream_JSONBField):
# https://bitbucket.org/offline/django-annoying/src/a0de8b294db3/annoying/fields.py
class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
class AutoSingleRelatedObjectDescriptor(ReverseOneToOneDescriptor):
"""Descriptor for access to the object from its related class."""
def __get__(self, instance, instance_type=None):
@@ -139,7 +140,7 @@ def resolve_role_field(obj, field):
raise Exception(smart_text('{} refers to a {}, not a Role'.format(field, type(obj))))
ret.append(obj.id)
else:
if type(obj) is ManyRelatedObjectsDescriptor:
if type(obj) is ManyToManyDescriptor:
for o in obj.all():
ret += resolve_role_field(o, field_components[1])
else:
@@ -179,7 +180,7 @@ def is_implicit_parent(parent_role, child_role):
return False
class ImplicitRoleDescriptor(ReverseSingleRelatedObjectDescriptor):
class ImplicitRoleDescriptor(ForwardManyToOneDescriptor):
pass
@@ -230,18 +231,18 @@ class ImplicitRoleField(models.ForeignKey):
field_name, sep, field_attr = field_name.partition('.')
field = getattr(cls, field_name)
if type(field) is ReverseManyRelatedObjectsDescriptor or \
type(field) is ManyRelatedObjectsDescriptor:
if type(field) is ReverseManyToOneDescriptor or \
type(field) is ManyToManyDescriptor:
if '.' in field_attr:
raise Exception('Referencing deep roles through ManyToMany fields is unsupported.')
if type(field) is ReverseManyRelatedObjectsDescriptor:
if type(field) is ReverseManyToOneDescriptor:
sender = field.through
else:
sender = field.related.through
reverse = type(field) is ManyRelatedObjectsDescriptor
reverse = type(field) is ManyToManyDescriptor
m2m_changed.connect(self.m2m_update(field_attr, reverse), sender, weak=False)
def m2m_update(self, field_attr, _reverse):
@@ -352,6 +353,7 @@ class SmartFilterField(models.TextField):
# https://docs.python.org/2/library/stdtypes.html#truth-value-testing
if not value:
return None
value = urllib.unquote(value)
try:
SmartFilter().query_from_string(value)
except RuntimeError, e:
@@ -415,6 +417,13 @@ class JSONSchemaField(JSONBField):
return value
@JSONSchemaField.format_checker.checks('vault_id')
def format_vault_id(value):
if '@' in value:
raise jsonschema.exceptions.FormatError('@ is not an allowed character')
return True
@JSONSchemaField.format_checker.checks('ssh_private_key')
def format_ssh_private_key(value):
# Sanity check: GCE, in particular, provides JSON-encoded private
@@ -754,3 +763,22 @@ class CredentialTypeInjectorField(JSONSchemaField):
code='invalid',
params={'value': value},
)
class AskForField(models.BooleanField):
"""
Denotes whether to prompt on launch for another field on the same template
"""
def __init__(self, allows_field=None, **kwargs):
super(AskForField, self).__init__(**kwargs)
self._allows_field = allows_field
@property
def allows_field(self):
if self._allows_field is None:
try:
return self.name[len('ask_'):-len('_on_launch')]
except AttributeError:
# self.name will be set by the model metaclass, not this field
raise Exception('Corresponding allows_field cannot be accessed until model is initialized.')
return self._allows_field

View File

@@ -2,12 +2,12 @@
# All Rights Reserved
from awx.main.utils import get_licenser
from django.core.management.base import NoArgsCommand
from django.core.management.base import BaseCommand
class Command(NoArgsCommand):
class Command(BaseCommand):
"""Returns license type, e.g., 'enterprise', 'open', 'none'"""
def handle(self, **options):
def handle(self, *args, **options):
super(Command, self).__init__()
return get_licenser().validate().get('license_type', 'none')

View File

@@ -4,29 +4,28 @@
# Python
import datetime
import logging
from optparse import make_option
# Django
from django.core.management.base import NoArgsCommand
from django.core.management.base import BaseCommand
from django.utils.timezone import now
# AWX
from awx.main.models import ActivityStream
class Command(NoArgsCommand):
class Command(BaseCommand):
'''
Management command to purge old activity stream events.
'''
help = 'Remove old activity stream events from the database'
option_list = NoArgsCommand.option_list + (
make_option('--days', dest='days', type='int', default=90, metavar='N',
help='Remove activity stream events more than N days old'),
make_option('--dry-run', dest='dry_run', action='store_true',
default=False, help='Dry run mode (show items that would '
'be removed)'),)
def add_arguments(self, parser):
parser.add_argument('--days', dest='days', type=int, default=90, metavar='N',
help='Remove activity stream events more than N days old')
parser.add_argument('--dry-run', dest='dry_run', action='store_true',
default=False, help='Dry run mode (show items that would '
'be removed)')
def init_logging(self):
log_levels = dict(enumerate([logging.ERROR, logging.INFO,
@@ -61,7 +60,7 @@ class Command(NoArgsCommand):
n_deleted_items += len(pks_to_delete)
self.logger.log(99, "Removed %d items", n_deleted_items)
def handle_noargs(self, **options):
def handle(self, *args, **options):
self.verbosity = int(options.get('verbosity', 1))
self.init_logging()
self.days = int(options.get('days', 30))

View File

@@ -4,7 +4,6 @@
# Python
import re
from dateutil.relativedelta import relativedelta
from optparse import make_option
# Django
from django.core.management.base import BaseCommand, CommandError
@@ -93,19 +92,20 @@ class CleanupFacts(object):
class Command(BaseCommand):
help = 'Cleanup facts. For each host older than the value specified, keep one fact scan for each time window (granularity).'
option_list = BaseCommand.option_list + (
make_option('--older_than',
dest='older_than',
default='30d',
help='Specify the relative time to consider facts older than (w)eek (d)ay or (y)ear (i.e. 5d, 2w, 1y). Defaults to 30d.'),
make_option('--granularity',
dest='granularity',
default='1w',
help='Window duration to group same hosts by for deletion (w)eek (d)ay or (y)ear (i.e. 5d, 2w, 1y). Defaults to 1w.'),
make_option('--module',
dest='module',
default=None,
help='Limit cleanup to a particular module.'),)
def add_arguments(self, parser):
parser.add_argument('--older_than',
dest='older_than',
default='30d',
help='Specify the relative time to consider facts older than (w)eek (d)ay or (y)ear (i.e. 5d, 2w, 1y). Defaults to 30d.')
parser.add_argument('--granularity',
dest='granularity',
default='1w',
help='Window duration to group same hosts by for deletion (w)eek (d)ay or (y)ear (i.e. 5d, 2w, 1y). Defaults to 1w.')
parser.add_argument('--module',
dest='module',
default=None,
help='Limit cleanup to a particular module.')
def __init__(self):
super(Command, self).__init__()

View File

@@ -4,10 +4,9 @@
# Python
import datetime
import logging
from optparse import make_option
# Django
from django.core.management.base import NoArgsCommand, CommandError
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils.timezone import now
@@ -25,41 +24,40 @@ from awx.main.signals import ( # noqa
from django.db.models.signals import post_save, post_delete, m2m_changed # noqa
class Command(NoArgsCommand):
class Command(BaseCommand):
'''
Management command to cleanup old jobs and project updates.
'''
help = 'Remove old jobs, project and inventory updates from the database.'
option_list = NoArgsCommand.option_list + (
make_option('--days', dest='days', type='int', default=90, metavar='N',
help='Remove jobs/updates executed more than N days ago. Defaults to 90.'),
make_option('--dry-run', dest='dry_run', action='store_true',
default=False, help='Dry run mode (show items that would '
'be removed)'),
make_option('--jobs', dest='only_jobs', action='store_true',
default=False,
help='Remove jobs'),
make_option('--ad-hoc-commands', dest='only_ad_hoc_commands',
action='store_true', default=False,
help='Remove ad hoc commands'),
make_option('--project-updates', dest='only_project_updates',
action='store_true', default=False,
help='Remove project updates'),
make_option('--inventory-updates', dest='only_inventory_updates',
action='store_true', default=False,
help='Remove inventory updates'),
make_option('--management-jobs', default=False,
action='store_true', dest='only_management_jobs',
help='Remove management jobs'),
make_option('--notifications', dest='only_notifications',
action='store_true', default=False,
help='Remove notifications'),
make_option('--workflow-jobs', default=False,
action='store_true', dest='only_workflow_jobs',
help='Remove workflow jobs')
)
def add_arguments(self, parser):
parser.add_argument('--days', dest='days', type=int, default=90, metavar='N',
help='Remove jobs/updates executed more than N days ago. Defaults to 90.')
parser.add_argument('--dry-run', dest='dry_run', action='store_true',
default=False, help='Dry run mode (show items that would '
'be removed)')
parser.add_argument('--jobs', dest='only_jobs', action='store_true',
default=False,
help='Remove jobs')
parser.add_argument('--ad-hoc-commands', dest='only_ad_hoc_commands',
action='store_true', default=False,
help='Remove ad hoc commands')
parser.add_argument('--project-updates', dest='only_project_updates',
action='store_true', default=False,
help='Remove project updates')
parser.add_argument('--inventory-updates', dest='only_inventory_updates',
action='store_true', default=False,
help='Remove inventory updates')
parser.add_argument('--management-jobs', default=False,
action='store_true', dest='only_management_jobs',
help='Remove management jobs')
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_jobs(self):
#jobs_qs = Job.objects.exclude(status__in=('pending', 'running'))
@@ -223,7 +221,7 @@ class Command(NoArgsCommand):
return skipped, deleted
@transaction.atomic
def handle_noargs(self, **options):
def handle(self, *args, **options):
self.verbosity = int(options.get('verbosity', 1))
self.init_logging()
self.days = int(options.get('days', 90))

View File

@@ -45,10 +45,10 @@ class Command(BaseCommand):
inventory=i,
variables="ansible_connection: local",
created_by=superuser)
JobTemplate.objects.create(name='Demo Job Template',
playbook='hello_world.yml',
project=p,
inventory=i,
credential=c)
jt = JobTemplate.objects.create(name='Demo Job Template',
playbook='hello_world.yml',
project=p,
inventory=i)
jt.credentials.add(c)
print('Default organization added.')
print('Demo Credential, Inventory, and Job Template added.')

View File

@@ -1,7 +1,6 @@
# Copyright (c) 2016 Ansible, Inc.
# All Rights Reserved
from optparse import make_option
import subprocess
import warnings
@@ -22,12 +21,11 @@ class Command(BaseCommand):
'Specify `--hostname` to use this command.'
)
option_list = BaseCommand.option_list + (
make_option('--hostname', dest='hostname', type='string',
help='Hostname used during provisioning'),
make_option('--name', dest='name', type='string',
help='(PENDING DEPRECIATION) Hostname used during provisioning'),
)
def add_arguments(self, parser):
parser.add_argument('--hostname', dest='hostname', type=str,
help='Hostname used during provisioning')
parser.add_argument('--name', dest='name', type=str,
help='(PENDING DEPRECIATION) Hostname used during provisioning')
@transaction.atomic
def handle(self, *args, **options):

View File

@@ -4,7 +4,6 @@
# Python
import json
import logging
from optparse import make_option
import os
import re
import subprocess
@@ -15,7 +14,7 @@ import shutil
# Django
from django.conf import settings
from django.core.management.base import NoArgsCommand, CommandError
from django.core.management.base import BaseCommand, CommandError
from django.core.exceptions import ImproperlyConfigured
from django.db import connection, transaction
from django.utils.encoding import smart_text
@@ -86,10 +85,8 @@ class AnsibleInventoryLoader(object):
env['ANSIBLE_INVENTORY_UNPARSED_FAILED'] = '1'
venv_libdir = os.path.join(settings.ANSIBLE_VENV_PATH, "lib")
env.pop('PYTHONPATH', None) # default to none if no python_ver matches
for python_ver in ["python2.7", "python2.6"]:
if os.path.isdir(os.path.join(venv_libdir, python_ver)):
env['PYTHONPATH'] = os.path.join(venv_libdir, python_ver, "site-packages") + ":"
break
if os.path.isdir(os.path.join(venv_libdir, "python2.7")):
env['PYTHONPATH'] = os.path.join(venv_libdir, "python2.7", "site-packages") + ":"
return env
def get_base_args(self):
@@ -168,7 +165,7 @@ class AnsibleInventoryLoader(object):
data = json.loads(stdout)
if not isinstance(data, dict):
raise TypeError('Returned JSON must be a dictionary, got %s instead' % str(type(data)))
except:
except Exception:
logger.error('Failed to load JSON from: %s', stdout)
raise
return data
@@ -176,6 +173,7 @@ class AnsibleInventoryLoader(object):
def load(self):
base_args = self.get_base_args()
logger.info('Reading Ansible inventory source: %s', self.source)
data = self.command_to_json(base_args + ['--list'])
# TODO: remove after we run custom scripts through ansible-inventory
@@ -228,6 +226,7 @@ def load_inventory_source(source, group_filter_re=None,
'''
# Sanity check: We sanitize these module names for our API but Ansible proper doesn't follow
# good naming conventions
source = source.replace('rhv.py', 'ovirt4.py')
source = source.replace('satellite6.py', 'foreman.py')
source = source.replace('vmware.py', 'vmware_inventory.py')
if not os.path.exists(source):
@@ -251,7 +250,7 @@ def load_inventory_source(source, group_filter_re=None,
return inventory.all_group
class Command(NoArgsCommand):
class Command(BaseCommand):
'''
Management command to import inventory from a directory, ini file, or
dynamic inventory script.
@@ -259,50 +258,46 @@ class Command(NoArgsCommand):
help = 'Import or sync external inventory sources'
option_list = NoArgsCommand.option_list + (
make_option('--inventory-name', dest='inventory_name', type='str',
default=None, metavar='n',
help='name of inventory to sync'),
make_option('--inventory-id', dest='inventory_id', type='int',
default=None, metavar='i', help='id of inventory to sync'),
make_option('--overwrite', dest='overwrite', action='store_true',
metavar="o", default=False,
help='overwrite the destination hosts and groups'),
make_option('--overwrite-vars', dest='overwrite_vars',
action='store_true', metavar="V", default=False,
help='overwrite (rather than merge) variables'),
make_option('--keep-vars', dest='keep_vars', action='store_true',
metavar="k", default=False,
help='use database variables if set'),
make_option('--custom', dest='custom', action='store_true',
metavar="c", default=False,
help='this is a custom inventory script'),
make_option('--source', dest='source', type='str', default=None,
metavar='s', help='inventory directory, file, or script '
'to load'),
make_option('--enabled-var', dest='enabled_var', type='str',
default=None, metavar='v', help='host variable used to '
'set/clear enabled flag when host is online/offline, may '
'be specified as "foo.bar" to traverse nested dicts.'),
make_option('--enabled-value', dest='enabled_value', type='str',
default=None, metavar='v', help='value of host variable '
'specified by --enabled-var that indicates host is '
'enabled/online.'),
make_option('--group-filter', dest='group_filter', type='str',
default=None, metavar='regex', help='regular expression '
'to filter group name(s); only matches are imported.'),
make_option('--host-filter', dest='host_filter', type='str',
default=None, metavar='regex', help='regular expression '
'to filter host name(s); only matches are imported.'),
make_option('--exclude-empty-groups', dest='exclude_empty_groups',
action='store_true', default=False, help='when set, '
'exclude all groups that have no child groups, hosts, or '
'variables.'),
make_option('--instance-id-var', dest='instance_id_var', type='str',
default=None, metavar='v', help='host variable that '
'specifies the unique, immutable instance ID, may be '
'specified as "foo.bar" to traverse nested dicts.'),
)
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('--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='use database variables if set')
parser.add_argument('--custom', dest='custom', action='store_true', default=False,
help='this is a custom inventory script')
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', dest='enabled_var', type=str,
default=None, metavar='v', help='host variable used to '
'set/clear enabled flag when host is online/offline, may '
'be specified as "foo.bar" to traverse nested dicts.')
parser.add_argument('--enabled-value', dest='enabled_value', type=str,
default=None, metavar='v', help='value of host variable '
'specified by --enabled-var that indicates host is '
'enabled/online.')
parser.add_argument('--group-filter', dest='group_filter', type=str,
default=None, metavar='regex', help='regular expression '
'to filter group name(s); only matches are imported.')
parser.add_argument('--host-filter', dest='host_filter', type=str,
default=None, metavar='regex', help='regular expression '
'to filter host name(s); only matches are imported.')
parser.add_argument('--exclude-empty-groups', dest='exclude_empty_groups',
action='store_true', default=False, help='when set, '
'exclude all groups that have no child groups, hosts, or '
'variables.')
parser.add_argument('--instance-id-var', dest='instance_id_var', type=str,
default=None, metavar='v', help='host variable that '
'specifies the unique, immutable instance ID, may be '
'specified as "foo.bar" to traverse nested dicts.')
def set_logging_level(self):
log_levels = dict(enumerate([logging.WARNING, logging.INFO,
@@ -352,7 +347,12 @@ class Command(NoArgsCommand):
enabled = bool(unicode(enabled_value) == unicode(enabled))
else:
enabled = bool(enabled)
return enabled
if enabled is default:
return None
elif isinstance(enabled, bool):
return enabled
else:
raise NotImplementedError('Value of enabled {} not understood.'.format(enabled))
def load_inventory_from_database(self):
'''
@@ -400,10 +400,10 @@ class Command(NoArgsCommand):
overwrite_vars=self.overwrite_vars,
)
self.inventory_update = self.inventory_source.create_inventory_update(
job_args=json.dumps(sys.argv),
job_env=dict(os.environ.items()),
job_cwd=os.getcwd(),
_eager_fields=dict(
job_args=json.dumps(sys.argv),
job_env=dict(os.environ.items()),
job_cwd=os.getcwd(),
execution_node=settings.CLUSTER_HOST_ID,
instance_group=InstanceGroup.objects.get(name='tower'))
)
@@ -602,27 +602,20 @@ class Command(NoArgsCommand):
def _update_inventory(self):
'''
Update/overwrite variables from "all" group. If importing from a
cloud source attached to a specific group, variables will be set on
the base group, otherwise they will be set on the whole inventory.
Update inventory variables from "all" group.
'''
# FIXME: figure out how "all" variables are handled in the new inventory source system
# TODO: We disable variable overwrite here in case user-defined inventory variables get
# mangled. But we still need to figure out a better way of processing multiple inventory
# update variables mixing with each other.
all_obj = self.inventory
all_name = 'inventory'
db_variables = all_obj.variables_dict
if self.overwrite_vars:
db_variables = self.all_group.variables
else:
db_variables.update(self.all_group.variables)
db_variables.update(self.all_group.variables)
if db_variables != all_obj.variables_dict:
all_obj.variables = json.dumps(db_variables)
all_obj.save(update_fields=['variables'])
if self.overwrite_vars:
logger.info('%s variables replaced from "all" group', all_name.capitalize())
else:
logger.info('%s variables updated from "all" group', all_name.capitalize())
logger.info('Inventory variables updated from "all" group')
else:
logger.info('%s variables unmodified', all_name.capitalize())
logger.info('Inventory variables unmodified')
def _create_update_groups(self):
'''
@@ -927,7 +920,7 @@ class Command(NoArgsCommand):
self.inventory_update.license_error = True
self.inventory_update.save(update_fields=['license_error'])
def handle_noargs(self, **options):
def handle(self, *args, **options):
self.verbosity = int(options.get('verbosity', 1))
self.set_logging_level()
self.inventory_name = options.get('inventory_name', None)

View File

@@ -2,14 +2,14 @@
# All Rights Reserved
from awx.main.models import Instance, InstanceGroup
from django.core.management.base import NoArgsCommand
from django.core.management.base import BaseCommand
class Command(NoArgsCommand):
class Command(BaseCommand):
"""List instances from the Tower database
"""
def handle(self, **options):
def handle(self, *args, **options):
super(Command, self).__init__()
for instance in Instance.objects.all():

View File

@@ -5,7 +5,6 @@ from awx.main.models import Instance
from awx.main.utils.pglock import advisory_lock
from django.conf import settings
from optparse import make_option
from django.db import transaction
from django.core.management.base import BaseCommand, CommandError
@@ -21,10 +20,9 @@ class Command(BaseCommand):
'Specify `--hostname` to use this command.'
)
option_list = BaseCommand.option_list + (
make_option('--hostname', dest='hostname', type='string',
help='Hostname used during provisioning'),
)
def add_arguments(self, parser):
parser.add_argument('--hostname', dest='hostname', type=str,
help='Hostname used during provisioning')
def _register_hostname(self, hostname):
if not hostname:

View File

@@ -5,20 +5,18 @@ import sys
from awx.main.utils.pglock import advisory_lock
from awx.main.models import Instance, InstanceGroup
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--queuename', dest='queuename', type='string',
help='Queue to create/update'),
make_option('--hostnames', dest='hostnames', type='string',
help='Comma-Delimited Hosts to add to the Queue'),
make_option('--controller', dest='controller', type='string', default='',
help='The controlling group (makes this an isolated group)'),
)
def add_arguments(self, parser):
parser.add_argument('--queuename', dest='queuename', type=str,
help='Queue to create/update')
parser.add_argument('--hostnames', dest='hostnames', type=str,
help='Comma-Delimited Hosts to add to the Queue')
parser.add_argument('--controller', dest='controller', type=str,
default='', help='The controlling group (makes this an isolated group)')
def handle(self, **options):
queuename = options.get('queuename')

View File

@@ -3,8 +3,6 @@
import sys
from awx.main.models import Instance, InstanceGroup
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
@@ -14,14 +12,13 @@ class Command(BaseCommand):
"Remove an instance (specified by --hostname) from the specified queue (instance group).\n"
"In order remove the queue, use the `unregister_queue` command.")
option_list = BaseCommand.option_list + (
make_option('--queuename', dest='queuename', type='string',
help='Queue to be removed from'),
make_option('--hostname', dest='hostname', type='string',
help='Host to remove from queue'),
)
def add_arguments(self, parser):
parser.add_argument('--queuename', dest='queuename', type=str,
help='Queue to be removed from')
parser.add_argument('--hostname', dest='hostname', type=str,
help='Host to remove from queue')
def handle(self, **options):
def handle(self, *arg, **options):
if not options.get('queuename'):
raise CommandError('Must specify `--queuename` in order to use command.')
ig = InstanceGroup.objects.filter(name=options.get('queuename'))
@@ -36,4 +33,3 @@ class Command(BaseCommand):
i = i.first()
ig.instances.remove(i)
print("Instance removed from instance group")

View File

@@ -0,0 +1,201 @@
# Copyright (c) 2017 Ansible by Red Hat
# All Rights Reserved.
import sys
import time
import json
from django.utils import timezone
from django.core.management.base import BaseCommand
from awx.main.models import (
UnifiedJob,
Job,
AdHocCommand,
ProjectUpdate,
InventoryUpdate,
SystemJob
)
from awx.main.consumers import emit_channel_notification
from awx.api.serializers import (
JobEventWebSocketSerializer,
AdHocCommandEventWebSocketSerializer,
ProjectUpdateEventWebSocketSerializer,
InventoryUpdateEventWebSocketSerializer,
SystemJobEventWebSocketSerializer
)
class ReplayJobEvents():
recording_start = None
replay_start = None
def now(self):
return timezone.now()
def start(self, first_event_created):
self.recording_start = first_event_created
self.replay_start = self.now()
def lateness(self, now, created):
time_passed = now - self.recording_start
job_event_time = created - self.replay_start
return (time_passed - job_event_time).total_seconds()
def get_job(self, job_id):
try:
unified_job = UnifiedJob.objects.get(id=job_id)
except UnifiedJob.DoesNotExist:
print("UnifiedJob {} not found.".format(job_id))
sys.exit(1)
return unified_job.get_real_instance()
def sleep(self, seconds):
time.sleep(seconds)
def replay_elapsed(self):
return (self.now() - self.replay_start)
def recording_elapsed(self, created):
return (created - self.recording_start)
def replay_offset(self, created, speed):
return self.replay_elapsed().total_seconds() - (self.recording_elapsed(created).total_seconds() * (1.0 / speed))
def get_job_events(self, job):
if type(job) is Job:
job_events = job.job_events.order_by('created')
elif type(job) is AdHocCommand:
job_events = job.ad_hoc_command_events.order_by('created')
elif type(job) is ProjectUpdate:
job_events = job.project_update_events.order_by('created')
elif type(job) is InventoryUpdate:
job_events = job.inventory_update_events.order_by('created')
elif type(job) is SystemJob:
job_events = job.system_job_events.order_by('created')
if job_events.count() == 0:
raise RuntimeError("No events for job id {}".format(job.id))
return job_events
def get_serializer(self, job):
if type(job) is Job:
return JobEventWebSocketSerializer
elif type(job) is AdHocCommand:
return AdHocCommandEventWebSocketSerializer
elif type(job) is ProjectUpdate:
return ProjectUpdateEventWebSocketSerializer
elif type(job) is InventoryUpdate:
return InventoryUpdateEventWebSocketSerializer
elif type(job) is SystemJob:
return SystemJobEventWebSocketSerializer
else:
raise RuntimeError("Job is of type {} and replay is not yet supported.".format(type(job)))
sys.exit(1)
def run(self, job_id, speed=1.0, verbosity=0):
stats = {
'events_ontime': {
'total': 0,
'percentage': 0,
},
'events_late': {
'total': 0,
'percentage': 0,
'lateness_total': 0,
'lateness_average': 0,
},
'events_total': 0,
'events_distance_total': 0,
'events_distance_average': 0,
'recording_start': 0,
'recording_end': 0,
'recording_duration': 0,
'replay_start': 0,
'replay_end': 0,
'replay_duration': 0,
}
try:
job = self.get_job(job_id)
job_events = self.get_job_events(job)
serializer = self.get_serializer(job)
except RuntimeError as e:
print("{}".format(e.message))
sys.exit(1)
je_previous = None
for je_current in job_events:
if not je_previous:
stats['recording_start'] = je_current.created
self.start(je_current.created)
stats['replay_start'] = self.replay_start
je_previous = je_current
je_serialized = serializer(je_current).data
emit_channel_notification('{}-{}'.format(je_serialized['group_name'], job.id), je_serialized)
replay_offset = self.replay_offset(je_previous.created, speed)
recording_diff = (je_current.created - je_previous.created).total_seconds() * (1.0 / speed)
stats['events_distance_total'] += recording_diff
if verbosity >= 3:
print("recording: next job in {} seconds".format(recording_diff))
if replay_offset >= 0:
replay_diff = recording_diff - replay_offset
if replay_diff > 0:
stats['events_ontime']['total'] += 1
if verbosity >= 3:
print("\treplay: sleep for {} seconds".format(replay_diff))
self.sleep(replay_diff)
else:
stats['events_late']['total'] += 1
stats['events_late']['lateness_total'] += (replay_diff * -1)
if verbosity >= 3:
print("\treplay: too far behind to sleep {} seconds".format(replay_diff))
else:
replay_offset = self.replay_offset(je_current.created, speed)
stats['events_late']['lateness_total'] += (replay_offset * -1)
stats['events_late']['total'] += 1
if verbosity >= 3:
print("\treplay: behind by {} seconds".format(replay_offset))
stats['events_total'] += 1
je_previous = je_current
stats['replay_end'] = self.now()
stats['replay_duration'] = (stats['replay_end'] - stats['replay_start']).total_seconds()
stats['replay_start'] = stats['replay_start'].isoformat()
stats['replay_end'] = stats['replay_end'].isoformat()
stats['recording_end'] = je_current.created
stats['recording_duration'] = (stats['recording_end'] - stats['recording_start']).total_seconds()
stats['recording_start'] = stats['recording_start'].isoformat()
stats['recording_end'] = stats['recording_end'].isoformat()
stats['events_ontime']['percentage'] = (stats['events_ontime']['total'] / float(stats['events_total'])) * 100.00
stats['events_late']['percentage'] = (stats['events_late']['total'] / float(stats['events_total'])) * 100.00
stats['events_distance_average'] = stats['events_distance_total'] / stats['events_total']
stats['events_late']['lateness_average'] = stats['events_late']['lateness_total'] / stats['events_late']['total']
if verbosity >= 2:
print(json.dumps(stats, indent=4, sort_keys=True))
class Command(BaseCommand):
help = 'Replay job events over websockets ordered by created on date.'
def add_arguments(self, parser):
parser.add_argument('--job_id', dest='job_id', type=int, metavar='j',
help='Id of the job to replay (job or adhoc)')
parser.add_argument('--speed', dest='speed', type=int, metavar='s',
help='Speedup factor.')
def handle(self, *args, **options):
job_id = options.get('job_id')
speed = options.get('speed') or 1
verbosity = options.get('verbosity') or 0
replayer = ReplayJobEvents()
replayer.run(job_id, speed, verbosity)

View File

@@ -3,26 +3,29 @@
# Python
import logging
import os
import signal
import time
from uuid import UUID
from multiprocessing import Process
from multiprocessing import Queue as MPQueue
from Queue import Empty as QueueEmpty
from Queue import Full as QueueFull
import os
from kombu import Connection, Exchange, Queue
from kombu.mixins import ConsumerMixin
# Django
from django.conf import settings
from django.core.management.base import NoArgsCommand
from django.core.management.base import BaseCommand
from django.db import connection as django_connection
from django.db import DatabaseError
from django.db import DatabaseError, OperationalError
from django.db.utils import InterfaceError, InternalError
from django.core.cache import cache as django_cache
# AWX
from awx.main.models import * # noqa
from awx.main.consumers import emit_channel_notification
logger = logging.getLogger('awx.main.commands.run_callback_receiver')
@@ -39,6 +42,9 @@ class WorkerSignalHandler:
class CallbackBrokerWorker(ConsumerMixin):
MAX_RETRIES = 2
def __init__(self, connection, use_workers=True):
self.connection = connection
self.worker_queues = []
@@ -123,8 +129,17 @@ class CallbackBrokerWorker(ConsumerMixin):
logger.error("Exception on worker thread, restarting: " + str(e))
continue
try:
if 'job_id' not in body and 'ad_hoc_command_id' not in body:
raise Exception('Payload does not have a job_id or ad_hoc_command_id')
event_map = {
'job_id': JobEvent,
'ad_hoc_command_id': AdHocCommandEvent,
'project_update_id': ProjectUpdateEvent,
'inventory_update_id': InventoryUpdateEvent,
'system_job_id': SystemJobEvent,
}
if not any([key in body for key in event_map]):
raise Exception('Payload does not have a job identifier')
if settings.DEBUG:
from pygments import highlight
from pygments.lexers import PythonLexer
@@ -132,14 +147,51 @@ class CallbackBrokerWorker(ConsumerMixin):
from pprint import pformat
logger.info('Body: {}'.format(
highlight(pformat(body, width=160), PythonLexer(), Terminal256Formatter(style='friendly'))
))
try:
if 'job_id' in body:
JobEvent.create_from_data(**body)
elif 'ad_hoc_command_id' in body:
AdHocCommandEvent.create_from_data(**body)
except DatabaseError as e:
logger.error('Database Error Saving Job Event: {}'.format(e))
)[:1024 * 4])
def _save_event_data():
for key, cls in event_map.items():
if key in body:
cls.create_from_data(**body)
job_identifier = 'unknown job'
for key in event_map.keys():
if key in body:
job_identifier = body[key]
break
if body.get('event') == 'EOF':
# EOF events are sent when stdout for the running task is
# closed. don't actually persist them to the database; we
# just use them to report `summary` websocket events as an
# approximation for when a job is "done"
emit_channel_notification(
'jobs-summary',
dict(group_name='jobs', unified_job_id=job_identifier)
)
continue
retries = 0
while retries <= self.MAX_RETRIES:
try:
_save_event_data()
break
except (OperationalError, InterfaceError, InternalError) as e:
if retries >= self.MAX_RETRIES:
logger.exception('Worker could not re-establish database connectivity, shutting down gracefully: Job {}'.format(job_identifier))
os.kill(os.getppid(), signal.SIGINT)
return
delay = 60 * retries
logger.exception('Database Error Saving Job Event, retry #{i} in {delay} seconds:'.format(
i=retries + 1,
delay=delay
))
django_connection.close()
time.sleep(delay)
retries += 1
except DatabaseError as e:
logger.exception('Database Error Saving Job Event for Job {}'.format(job_identifier))
break
except Exception as exc:
import traceback
tb = traceback.format_exc()
@@ -147,7 +199,7 @@ class CallbackBrokerWorker(ConsumerMixin):
logger.error('Detail: {}'.format(tb))
class Command(NoArgsCommand):
class Command(BaseCommand):
'''
Save Job Callback receiver (see awx.plugins.callbacks.job_event_callback)
Runs as a management command and receives job save events. It then hands
@@ -155,8 +207,8 @@ class Command(NoArgsCommand):
'''
help = 'Launch the job callback receiver'
def handle_noargs(self, **options):
with Connection(settings.BROKER_URL) as conn:
def handle(self, *arg, **options):
with Connection(settings.CELERY_BROKER_URL) as conn:
try:
worker = CallbackBrokerWorker(conn)
worker.run()

View File

@@ -1,13 +1,11 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved
from optparse import make_option
# Django
from django.core.management.base import BaseCommand
# AWX
from awx.main.models import * # noqa
from awx.main.models import UnifiedJob
class Command(BaseCommand):
@@ -17,14 +15,13 @@ class Command(BaseCommand):
help = 'Display some simple statistics'
option_list = BaseCommand.option_list + (
make_option('--stat',
action='store',
dest='stat',
type="string",
default="jobs_running",
help='Select which stat to get information for'),
)
def add_arguments(self, parser):
parser.add_argument('--stat',
action='store',
dest='stat',
type=str,
default="jobs_running",
help='Select which stat to get information for')
def job_stats(self, state):
return UnifiedJob.objects.filter(status=state).count()
@@ -34,5 +31,3 @@ class Command(BaseCommand):
self.stdout.write(str(self.job_stats(options['stat'][5:])))
else:
self.stdout.write("Supported stats: jobs_{state}")

View File

@@ -0,0 +1,50 @@
import os
import shutil
import subprocess
import sys
import tempfile
from optparse import make_option
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from awx.main.expect import run
class Command(BaseCommand):
"""Tests SSH connectivity between a controller and target isolated node"""
help = 'Tests SSH connectivity between a controller and target isolated node'
option_list = BaseCommand.option_list + (
make_option('--hostname', dest='hostname', type='string',
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_PROOT_BASE_PATH)
args = [
'ansible', 'all', '-i', '{},'.format(hostname), '-u',
settings.AWX_ISOLATED_USERNAME, '-T5', '-m', 'shell',
'-a', 'hostname', '-vvv'
]
if all([
getattr(settings, 'AWX_ISOLATED_KEY_GENERATION', False) is True,
getattr(settings, 'AWX_ISOLATED_PRIVATE_KEY', None)
]):
ssh_key_path = os.path.join(path, '.isolated')
ssh_auth_sock = os.path.join(path, 'ssh_auth.sock')
run.open_fifo_write(ssh_key_path, settings.AWX_ISOLATED_PRIVATE_KEY)
args = run.wrap_args_with_ssh_agent(args, ssh_key_path, ssh_auth_sock)
try:
print ' '.join(args)
subprocess.check_call(args)
except subprocess.CalledProcessError as e:
sys.exit(e.returncode)
finally:
shutil.rmtree(path)

View File

@@ -5,7 +5,6 @@ import sys
from awx.main.utils.pglock import advisory_lock
from awx.main.models import InstanceGroup
from optparse import make_option
from django.db import transaction
from django.core.management.base import BaseCommand, CommandError
@@ -17,13 +16,12 @@ class Command(BaseCommand):
"Instances inside of queue will continue to exist, \n"
"but jobs will no longer be processed by queue.")
option_list = BaseCommand.option_list + (
make_option('--queuename', dest='queuename', type='string',
help='Queue to create/update'),
)
def add_arguments(self, parser):
parser.add_argument('--queuename', dest='queuename', type=str,
help='Queue to create/update')
@transaction.atomic
def handle(self, **options):
def handle(self, *args, **options):
queuename = options.get('queuename')
if not queuename:
raise CommandError('Must specify `--queuename` in order to use command.')

View File

@@ -1,9 +1,6 @@
# Copyright (c) 2016 Ansible, Inc.
# All Rights Reserved
# Python
from optparse import make_option
# Django
from django.core.management.base import BaseCommand
from django.core.management.base import CommandError
@@ -25,12 +22,11 @@ class UpdatePassword(object):
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--username', dest='username', action='store', type='string', default=None,
help='username to change the password for'),
make_option('--password', dest='password', action='store', type='string', default=None,
help='new password for user'),
)
def add_arguments(self, parser):
parser.add_argument('--username', dest='username', action='store', type=str, default=None,
help='username to change the password for')
parser.add_argument('--password', dest='password', action='store', type=str, default=None,
help='new password for user')
def handle(self, *args, **options):
if not options['username']:
@@ -43,5 +39,3 @@ class Command(BaseCommand):
if res:
return "Password updated"
return "Password not updated"

View File

@@ -21,11 +21,15 @@ class HostManager(models.Manager):
"""Custom manager class for Hosts model."""
def active_count(self):
"""Return count of active, unique hosts for licensing."""
try:
return self.order_by('name').distinct('name').count()
except NotImplementedError: # For unit tests only, SQLite doesn't support distinct('name')
return len(set(self.values_list('name', flat=True)))
"""Return count of active, unique hosts for licensing.
Construction of query involves:
- remove any ordering specified in model's Meta
- Exclude hosts sourced from another Tower
- Restrict the query to only return the name column
- 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()
def get_queryset(self):
"""When the parent instance of the host query set has a `kind=smart` and a `host_filter`

View File

@@ -5,6 +5,10 @@ import logging
import threading
import uuid
import six
import time
import cProfile
import pstats
import os
from django.conf import settings
from django.contrib.auth.models import User
@@ -25,6 +29,40 @@ from awx.conf import fields, register
logger = logging.getLogger('awx.main.middleware')
analytics_logger = logging.getLogger('awx.analytics.activity_stream')
perf_logger = logging.getLogger('awx.analytics.performance')
class TimingMiddleware(threading.local):
dest = '/var/lib/awx/profile'
def process_request(self, request):
self.start_time = time.time()
if settings.AWX_REQUEST_PROFILE:
self.prof = cProfile.Profile()
self.prof.enable()
def process_response(self, request, response):
if not hasattr(self, 'start_time'): # some tools may not invoke process_request
return response
total_time = time.time() - self.start_time
response['X-API-Total-Time'] = '%0.3fs' % total_time
if settings.AWX_REQUEST_PROFILE:
self.prof.disable()
cprofile_file = self.save_profile_file(request)
response['cprofile_file'] = cprofile_file
perf_logger.info('api response times', extra=dict(python_objects=dict(request=request, response=response)))
return response
def save_profile_file(self, request):
if not os.path.isdir(self.dest):
os.makedirs(self.dest)
filename = '%.3fs-%s' % (pstats.Stats(self.prof).total_tt, uuid.uuid4())
filepath = os.path.join(self.dest, filename)
with open(filepath, 'w') as f:
f.write('%s %s\n' % (request.method, request.get_full_path()))
pstats.Stats(self.prof, stream=f).sort_stats('cumulative').print_stats()
return filepath
class ActivityStreamMiddleware(threading.local):

View File

@@ -8,14 +8,9 @@ from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
import awx.main.fields
import jsonfield.fields
def update_dashed_host_variables(apps, schema_editor):
Host = apps.get_model('main', 'Host')
for host in Host.objects.filter(variables='---'):
host.variables = ''
host.save()
import _squashed
from _squashed_30 import SQUASHED_30
class Migration(migrations.Migration):
@@ -27,13 +22,7 @@ class Migration(migrations.Migration):
(b'main', '0025_v300_update_rbac_parents'),
(b'main', '0026_v300_credential_unique'),
(b'main', '0027_v300_team_migrations'),
(b'main', '0028_v300_org_team_cascade'),
(b'main', '0029_v302_add_ask_skip_tags'),
(b'main', '0030_v302_job_survey_passwords'),
(b'main', '0031_v302_migrate_survey_passwords'),
(b'main', '0032_v302_credential_permissions_update'),
(b'main', '0033_v303_v245_host_variable_fix'),]
(b'main', '0028_v300_org_team_cascade')] + _squashed.replaces(SQUASHED_30, applied=True)
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
@@ -130,27 +119,4 @@ class Migration(migrations.Migration):
field=models.ForeignKey(related_name='teams', to='main.Organization'),
preserve_default=False,
),
# add ask skip tags
migrations.AddField(
model_name='jobtemplate',
name='ask_skip_tags_on_launch',
field=models.BooleanField(default=False),
),
# job survery passwords
migrations.AddField(
model_name='job',
name='survey_passwords',
field=jsonfield.fields.JSONField(default={}, editable=False, blank=True),
),
# RBAC credential permission updates
migrations.AlterField(
model_name='credential',
name='admin_role',
field=awx.main.fields.ImplicitRoleField(related_name='+', parent_role=[b'singleton:system_administrator', b'organization.admin_role'], to='main.Role', null=b'True'),
),
migrations.AlterField(
model_name='credential',
name='use_role',
field=awx.main.fields.ImplicitRoleField(related_name='+', parent_role=[b'admin_role'], to='main.Role', null=b'True'),
),
]
] + _squashed.operations(SQUASHED_30, applied=True)

View File

@@ -8,6 +8,9 @@ import django.db.models.deletion
import awx.main.models.workflow
import awx.main.fields
import _squashed
from _squashed_30 import SQUASHED_30
class Migration(migrations.Migration):
@@ -15,11 +18,11 @@ class Migration(migrations.Migration):
('main', '0003_squashed_v300_v303_updates'),
]
replaces = [
replaces = _squashed.replaces(SQUASHED_30) + [
(b'main', '0034_v310_release'),
]
operations = [
operations = _squashed.operations(SQUASHED_30) + [
# Create ChannelGroup table
migrations.CreateModel(
name='ChannelGroup',

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