Compare commits

...

19 Commits

Author SHA1 Message Date
softwarefactory-project-zuul[bot]
aa4ca300f5 Merge pull request #9169 from rooftopcellist/version-1101
Bump version to 17.0.1 & update changelog

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2021-01-26 18:22:28 +00:00
Christian M. Adams
8d8aadb193 Bump version to 17.0.1 & update changelog 2021-01-26 12:35:14 -05:00
softwarefactory-project-zuul[bot]
3194690e5f Merge pull request #9093 from marshmalien/fix-setting-toggle-id
Fix setting toggle on click behavior

Reviewed-by: John Hill <johill@redhat.com>
             https://github.com/unlikelyzero
2021-01-26 17:16:43 +00:00
softwarefactory-project-zuul[bot]
6cc3ac2e99 Merge pull request #9167 from djj106/devel
fix workflow url

Reviewed-by: Ryan Petrello
             https://github.com/ryanpetrello
2021-01-26 15:40:56 +00:00
djj106
c4c1b9799e fix workflow url
Signed-off-by: djj106 <djj106@gmail.com>
2021-01-26 08:48:08 -06:00
softwarefactory-project-zuul[bot]
9f691a048d Merge pull request #9152 from rooftopcellist/awxcompose-perm
Pre-create pgdocker dir ahead of time with proper permissions

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2021-01-25 17:28:46 +00:00
softwarefactory-project-zuul[bot]
da68e613e3 Merge pull request #9155 from sezanzeb/patch-2
document postgres_data_dir

Reviewed-by: awxbot
             https://github.com/awxbot
2021-01-25 16:58:03 +00:00
sezanzeb
b9a9d645de document postgres_data_dir 2021-01-25 17:26:39 +01:00
softwarefactory-project-zuul[bot]
7032927ba3 Merge pull request #9150 from mamercad/mamercad/named_url_typo
Fixing a small typo

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2021-01-25 15:19:36 +00:00
Christian M. Adams
e62035fa5e Pre-create pgdocker dir ahead of time with proper permissions 2021-01-25 09:52:02 -05:00
Mark Mercado
5fe6e75255 Fixing a small typo 2021-01-24 12:40:29 -05:00
softwarefactory-project-zuul[bot]
83372d6f03 Merge pull request #9149 from vladdoster/patch-1
(docs) update README.md

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2021-01-24 00:23:20 +00:00
vlad doster
7c53bf3681 (docs) update README.md
- correct punctuation
- fix spelling
2021-01-23 14:11:40 -06:00
softwarefactory-project-zuul[bot]
e40e646211 Merge pull request #9143 from ryanpetrello/org-host-count
expose active host count on the Organization detail view

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2021-01-22 19:14:58 +00:00
softwarefactory-project-zuul[bot]
b913d8411a Merge pull request #9142 from ryanpetrello/bye-bigint
stop detecting the need for event data migration

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
2021-01-22 18:46:13 +00:00
Ryan Petrello
2017504c51 expose active host count on the Organization detail view 2021-01-22 13:42:27 -05:00
Ryan Petrello
16848e9154 stop detecting the need for event data migration
related: https://github.com/ansible/awx/issues/6010

as noted in the comment removed from this diff, it's probably time
to stop calling this function on every dispatcher service restart
2021-01-22 09:22:00 -05:00
Marliana Lara
ee59ac957a Assert checkbox label click event updates checkbox value 2021-01-21 12:49:57 -05:00
Marliana Lara
6b7d712f9f Give setting toggle form group a unique form field id 2021-01-21 12:36:20 -05:00
16 changed files with 99 additions and 43 deletions

View File

@@ -2,6 +2,10 @@
This is a list of high-level changes for each release of AWX. A full list of commits can be found at `https://github.com/ansible/awx/releases/tag/<version>`.
# 17.0.1 (January 26, 2021)
- Fixed pgdocker directory permissions issue with Local Docker installer: https://github.com/ansible/awx/pull/9152
- Fixed a bug in the UI which caused toggle settings to not be changed when clicked: https://github.com/ansible/awx/pull/9093
# 17.0.0 (January 22, 2021)
- AWX now requires PostgreSQL 12 by default: https://github.com/ansible/awx/pull/8943
**Note:** users who encounter permissions errors at upgrade time should `chown -R ~/.awx/pgdocker` to ensure it's owned by the user running the install playbook

View File

@@ -14,20 +14,20 @@ Contributing
------------
- Refer to the [Contributing guide](./CONTRIBUTING.md) to get started developing, testing, and building AWX.
- All code submissions are done through pull requests against the `devel` branch.
- All contributors must use git commit --signoff for any commit to be merged, and agree that usage of --signoff constitutes agreement with the terms of [DCO 1.1](./DCO_1_1.md)
- Take care to make sure no merge commits are in the submission, and use `git rebase` vs `git merge` for this reason.
- If submitting a large code change, it's a good idea to join the `#ansible-awx` channel on irc.freenode.net, and talk about what you would like to do or add first. This not only helps everyone know what's going on, it also helps save time and effort, if the community decides some changes are needed.
- All code submissions are made through pull requests against the `devel` branch.
- All contributors must use git commit --signoff for any commit to be merged and agree that usage of --signoff constitutes agreement with the terms of [DCO 1.1](./DCO_1_1.md)
- Take care to make sure no merge commits are in the submission, and use `git rebase` vs. `git merge` for this reason.
- If submitting a large code change, it's a good idea to join the `#ansible-awx` channel on irc.freenode.net and talk about what you would like to do or add first. This not only helps everyone know what's going on, but it also helps save time and effort if the community decides some changes are needed.
Reporting Issues
----------------
If you're experiencing a problem that you feel is a bug in AWX, or have ideas for how to improve AWX, we encourage you to open an issue, and share your feedback. But before opening a new issue, we ask that you please take a look at our [Issues guide](./ISSUES.md).
If you're experiencing a problem that you feel is a bug in AWX or have ideas for improving AWX, we encourage you to open an issue and share your feedback. But before opening a new issue, we ask that you please take a look at our [Issues guide](./ISSUES.md).
Code of Conduct
---------------
We ask all of our community members and contributors to adhere to the [Ansible code of conduct](http://docs.ansible.com/ansible/latest/community/code_of_conduct.html). If you have questions, or need assistance, please reach out to our community team at [codeofconduct@ansible.com](mailto:codeofconduct@ansible.com)
We ask all of our community members and contributors to adhere to the [Ansible code of conduct](http://docs.ansible.com/ansible/latest/community/code_of_conduct.html). If you have questions or need assistance, please reach out to our community team at [codeofconduct@ansible.com](mailto:codeofconduct@ansible.com)
Get Involved
------------
@@ -41,4 +41,3 @@ License
-------
[Apache v2](./LICENSE.md)

View File

@@ -1 +1 @@
17.0.0
17.0.1

View File

@@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _
from awx.main.models import (
ActivityStream,
Inventory,
Host,
Project,
JobTemplate,
WorkflowJobTemplate,
@@ -98,6 +99,7 @@ class OrganizationDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAPI
organization__id=org_id).count()
org_counts['job_templates'] = JobTemplate.accessible_objects(**access_kwargs).filter(
organization__id=org_id).count()
org_counts['hosts'] = Host.objects.org_active_count(org_id)
full_context['related_field_counts'] = {}
full_context['related_field_counts'][org_id] = org_counts

View File

@@ -81,10 +81,17 @@ User.add_to_class('accessible_objects', user_accessible_objects)
def enforce_bigint_pk_migration():
#
# NOTE: this function is not actually in use anymore,
# but has been intentionally kept for historical purposes,
# and to serve as an illustration if we ever need to perform
# bulk modification/migration of event data in the future.
#
# see: https://github.com/ansible/awx/issues/6010
# look at all the event tables and verify that they have been fully migrated
# from the *old* int primary key table to the replacement bigint table
# if not, attempt to migrate them in the background
#
for tblname in (
'main_jobevent', 'main_inventoryupdateevent',
'main_projectupdateevent', 'main_adhoccommandevent',

View File

@@ -357,7 +357,7 @@ class JobNotificationMixin(object):
'url': 'https://towerhost/#/jobs/playbook/1010',
'approval_status': 'approved',
'approval_node_name': 'Approve Me',
'workflow_url': 'https://towerhost/#/workflows/1010',
'workflow_url': 'https://towerhost/#/jobs/workflow/1010',
'job_metadata': """{'url': 'https://towerhost/$/jobs/playbook/13',
'traceback': '',
'status': 'running',

View File

@@ -620,7 +620,7 @@ class WorkflowJob(UnifiedJob, WorkflowJobOptions, SurveyJobMixin, JobNotificatio
return reverse('api:workflow_job_detail', kwargs={'pk': self.pk}, request=request)
def get_ui_url(self):
return urljoin(settings.TOWER_URL_BASE, '/#/workflows/{}'.format(self.pk))
return urljoin(settings.TOWER_URL_BASE, '/#/jobs/workflow/{}'.format(self.pk))
def notification_data(self):
result = super(WorkflowJob, self).notification_data()
@@ -752,7 +752,7 @@ class WorkflowApproval(UnifiedJob, JobNotificationMixin):
return None
def get_ui_url(self):
return urljoin(settings.TOWER_URL_BASE, '/#/workflows/{}'.format(self.workflow_job.id))
return urljoin(settings.TOWER_URL_BASE, '/#/jobs/workflow/{}'.format(self.workflow_job.id))
def _get_parent_field_name(self):
return 'workflow_approval_template'
@@ -840,7 +840,7 @@ class WorkflowApproval(UnifiedJob, JobNotificationMixin):
return (msg, body)
def context(self, approval_status):
workflow_url = urljoin(settings.TOWER_URL_BASE, '/#/workflows/{}'.format(self.workflow_job.id))
workflow_url = urljoin(settings.TOWER_URL_BASE, '/#/jobs/workflow/{}'.format(self.workflow_job.id))
return {'approval_status': approval_status,
'approval_node_name': self.workflow_approval_template.name,
'workflow_url': workflow_url,

View File

@@ -60,7 +60,7 @@ from awx.main.models import (
Inventory, InventorySource, SmartInventoryMembership,
Job, AdHocCommand, ProjectUpdate, InventoryUpdate, SystemJob,
JobEvent, ProjectUpdateEvent, InventoryUpdateEvent, AdHocCommandEvent, SystemJobEvent,
build_safe_env, enforce_bigint_pk_migration
build_safe_env
)
from awx.main.constants import ACTIVE_STATES
from awx.main.exceptions import AwxTaskError, PostRunError
@@ -138,12 +138,6 @@ def dispatch_startup():
if Instance.objects.me().is_controller():
awx_isolated_heartbeat()
# at process startup, detect the need to migrate old event records from int
# to bigint; at *some point* in the future, once certain versions of AWX
# and Tower fall out of use/support, we can probably just _assume_ that
# everybody has moved to bigint, and remove this code entirely
enforce_bigint_pk_migration()
# Update Tower's rsyslog.conf file based on loggins settings in the db
reconfigure_rsyslog()
@@ -738,6 +732,12 @@ def update_host_smart_inventory_memberships():
@task(queue=get_local_queuename)
def migrate_legacy_event_data(tblname):
#
# NOTE: this function is not actually in use anymore,
# but has been intentionally kept for historical purposes,
# and to serve as an illustration if we ever need to perform
# bulk modification/migration of event data in the future.
#
if 'event' not in tblname:
return
with advisory_lock(f'bigint_migration_{tblname}', wait=False) as acquired:

View File

@@ -2,7 +2,7 @@ import pytest
from awx.api.versioning import reverse
from awx.main.models import Project
from awx.main.models import Project, Host
@pytest.fixture
@@ -81,6 +81,8 @@ def test_org_counts_detail_admin(resourced_organization, user, get):
assert response.status_code == 200
counts = response.data['summary_fields']['related_field_counts']
assert counts['hosts'] == 0
counts.pop('hosts')
assert counts == COUNTS_PRIMES
@@ -93,6 +95,8 @@ def test_org_counts_detail_member(resourced_organization, user, get):
assert response.status_code == 200
counts = response.data['summary_fields']['related_field_counts']
assert counts['hosts'] == 0
counts.pop('hosts')
assert counts == {
'users': COUNTS_PRIMES['users'], # Policy is that members can see other users and admins
'admins': COUNTS_PRIMES['admins'],
@@ -111,6 +115,7 @@ def test_org_counts_list_admin(resourced_organization, user, get):
assert response.status_code == 200
counts = response.data['results'][0]['summary_fields']['related_field_counts']
assert 'hosts' not in counts # doesn't show in list view
assert counts == COUNTS_PRIMES
@@ -123,6 +128,7 @@ def test_org_counts_list_member(resourced_organization, user, get):
assert response.status_code == 200
counts = response.data['results'][0]['summary_fields']['related_field_counts']
assert 'hosts' not in counts # doesn't show in list view
assert counts == {
'users': COUNTS_PRIMES['users'], # Policy is that members can see other users and admins
@@ -145,6 +151,7 @@ def test_new_org_zero_counts(user, post):
new_org_list = post_response.render().data
counts_dict = new_org_list['summary_fields']['related_field_counts']
assert 'hosts' not in counts_dict # doesn't show in list view
assert counts_dict == COUNTS_ZEROS
@@ -167,6 +174,19 @@ def test_two_organizations(resourced_organization, organizations, user, get):
assert counts[org_id_zero] == COUNTS_ZEROS
@pytest.mark.django_db
def test_hosts_counted(resourced_organization, user, get):
admin_user = user('admin', True)
assert Host.objects.org_active_count(resourced_organization.id) == 0
resourced_organization.inventories.first().hosts.create(name='Some Host')
assert Host.objects.org_active_count(resourced_organization.id) == 1
response = get(reverse('api:organization_detail', kwargs={'pk': resourced_organization.pk}), admin_user)
assert response.status_code == 200
counts = response.data['summary_fields']['related_field_counts']
assert counts['hosts'] == Host.objects.org_active_count(resourced_organization.id) == 1
@pytest.mark.django_db
def test_scan_JT_counted(resourced_organization, user, get):
admin_user = user('admin', True)
@@ -180,7 +200,10 @@ def test_scan_JT_counted(resourced_organization, user, get):
# Test detail view
detail_response = get(reverse('api:organization_detail', kwargs={'pk': resourced_organization.pk}), admin_user)
assert detail_response.status_code == 200
assert detail_response.data['summary_fields']['related_field_counts'] == counts_dict
counts = detail_response.data['summary_fields']['related_field_counts']
assert 'hosts' in counts
counts.pop('hosts')
assert counts == counts_dict
@pytest.mark.django_db
@@ -205,4 +228,7 @@ def test_JT_not_double_counted(resourced_organization, user, get):
# Test detail view
detail_response = get(reverse('api:organization_detail', kwargs={'pk': resourced_organization.pk}), admin_user)
assert detail_response.status_code == 200
assert detail_response.data['summary_fields']['related_field_counts'] == counts_dict
counts = detail_response.data['summary_fields']['related_field_counts']
assert 'hosts' in counts
counts.pop('hosts')
assert counts == counts_dict

View File

@@ -94,7 +94,7 @@ const buildAnchor = (obj, resource, activity) => {
break;
}
case 'workflow_job':
url = `/workflows/${obj.id}/`;
url = `/jobs/workflow/${obj.id}/`;
break;
case 'label':
url = null;

View File

@@ -48,10 +48,10 @@ const SettingGroup = withI18n()(
<FormGroup
fieldId={fieldId}
helperTextInvalid={helperTextInvalid}
id={`${fieldId}-field`}
isRequired={isRequired}
label={label}
validated={validated}
id={fieldId}
labelIcon={
<>
<Popover

View File

@@ -1,5 +1,7 @@
import React from 'react';
import { mount } from 'enzyme';
import { Formik } from 'formik';
import { I18nProvider } from '@lingui/react';
import { act } from 'react-dom/test-utils';
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
import {
@@ -12,28 +14,38 @@ import {
describe('Setting form fields', () => {
test('BooleanField renders the expected content', async () => {
const wrapper = mountWithContexts(
<Formik
initialValues={{
boolean: true,
}}
>
{() => (
<BooleanField
name="boolean"
config={{
label: 'test',
help_text: 'test',
}}
/>
)}
</Formik>
const outerNode = document.createElement('div');
document.body.appendChild(outerNode);
const wrapper = mount(
<I18nProvider>
<Formik
initialValues={{
boolean: true,
}}
>
{() => (
<BooleanField
name="boolean"
config={{
label: 'test',
help_text: 'test',
}}
/>
)}
</Formik>
</I18nProvider>,
{
attachTo: outerNode,
}
);
expect(wrapper.find('Switch')).toHaveLength(1);
expect(wrapper.find('Switch').prop('isChecked')).toBe(true);
expect(wrapper.find('Switch').prop('isDisabled')).toBe(false);
await act(async () => {
wrapper.find('Switch').invoke('onChange')(false);
wrapper
.find('Switch label')
.instance()
.dispatchEvent(new Event('click'));
});
wrapper.update();
expect(wrapper.find('Switch').prop('isChecked')).toBe(false);

View File

@@ -1 +1 @@
17.0.0
17.0.1

View File

@@ -39,7 +39,7 @@ The third part of the format is `<organization.name>`, which indicates that fiel
In the case where `organization` does not exist in the `related` field of label object detail, we append empty string `''` instead, which essentially does not alter the current identifier. So `Foo++` becomes final unique identifier and thus generate named URL to be `/api/v2/labels/Foo++/`.
An important aspect of generating unique identifiers for named URL is dealing with reserved characters. Because the identifier is part of a URL, the following reserved characters by URL standard should be escaped to its percentage encoding: `;/?:@=&[]`. For example, if an organization is named `;/?:@=&[]`, its unique identifier should be `%3B%2F%3F%3A%40%3D%26%5B%5D`. Another special reserved character is `+`, which is not reserved by URL standard but used by named URL to link different parts of an identifier. It is escaped by `[+]`. For example, if an organization is named `[+]`, tis unique identifier is `%5B[+]%5D`, where original `[` and `]` are percent encoded and `+` is converted to `[+]`.
An important aspect of generating unique identifiers for named URL is dealing with reserved characters. Because the identifier is part of a URL, the following reserved characters by URL standard should be escaped to its percentage encoding: `;/?:@=&[]`. For example, if an organization is named `;/?:@=&[]`, its unique identifier should be `%3B%2F%3F%3A%40%3D%26%5B%5D`. Another special reserved character is `+`, which is not reserved by URL standard but used by named URL to link different parts of an identifier. It is escaped by `[+]`. For example, if an organization is named `[+]`, its unique identifier is `%5B[+]%5D`, where original `[` and `]` are percent encoded and `+` is converted to `[+]`.
`NAMED_URL_FORMATS` exclusively lists every resource that can have named URL; any resource not listed there has no named URL. `NAMED_URL_FORMATS` alone should be instructive enough for users to compose human-readable unique identifier and named URL themselves. For more convenience, every object of a resource that can have named URL will have a related field `named_url` that displays that object's named URL. Users can simply copy-paste that field for their custom usages. Also, users are expected to see indications in the help text of the API browser if a resource object has named URL.

View File

@@ -62,6 +62,7 @@ dockerhub_base=ansible
# Common Docker parameters
awx_task_hostname=awx
awx_web_hostname=awxweb
# Local directory that is mounted in the awx_postgres docker container to place the db in
postgres_data_dir="~/.awx/pgdocker"
host_port=80
host_port_ssl=443

View File

@@ -1,5 +1,10 @@
---
- name: Create {{ postgres_data_dir }} directory
file:
path: "{{ postgres_data_dir }}"
state: directory
- name: Get full path of postgres data dir
shell: "echo {{ postgres_data_dir }}"
register: fq_postgres_data_dir