Initial removal of InventorySource.group

This commit is contained in:
Wayne Witzel III
2017-04-06 13:57:16 -04:00
parent 9747674cb3
commit c784c96449
8 changed files with 36 additions and 94 deletions

View File

@@ -1270,8 +1270,6 @@ class GroupSerializer(BaseSerializerWithVariables):
)) ))
if obj.inventory: if obj.inventory:
res['inventory'] = self.reverse('api:inventory_detail', kwargs={'pk': obj.inventory.pk}) res['inventory'] = self.reverse('api:inventory_detail', kwargs={'pk': obj.inventory.pk})
if obj.inventory_source:
res['inventory_source'] = self.reverse('api:inventory_source_detail', kwargs={'pk': obj.inventory_source.pk})
return res return res
def validate_name(self, value): def validate_name(self, value):
@@ -1432,10 +1430,10 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
class Meta: class Meta:
model = InventorySource model = InventorySource
fields = ('*', 'inventory', 'group', 'update_on_launch', fields = ('*', 'inventory', 'update_on_launch',
'update_cache_timeout') + \ 'update_cache_timeout') + \
('last_update_failed', 'last_updated') # Backwards compatibility. ('last_update_failed', 'last_updated') # Backwards compatibility.
read_only_fields = ('*', 'name', 'inventory', 'group') read_only_fields = ('*', 'name', 'inventory')
def get_related(self, obj): def get_related(self, obj):
res = super(InventorySourceSerializer, self).get_related(obj) res = super(InventorySourceSerializer, self).get_related(obj)

View File

@@ -346,10 +346,6 @@ class BaseAccess(object):
elif display_method == 'copy' and isinstance(obj, WorkflowJobTemplate) and obj.organization_id is None: elif display_method == 'copy' and isinstance(obj, WorkflowJobTemplate) and obj.organization_id is None:
user_capabilities[display_method] = self.user.is_superuser user_capabilities[display_method] = self.user.is_superuser
continue continue
elif display_method in ['start', 'schedule'] and isinstance(obj, Group):
if obj.inventory_source and not obj.inventory_source._can_update():
user_capabilities[display_method] = False
continue
elif display_method in ['start', 'schedule'] and isinstance(obj, (Project)): elif display_method in ['start', 'schedule'] and isinstance(obj, (Project)):
if obj.scm_type == '': if obj.scm_type == '':
user_capabilities[display_method] = False user_capabilities[display_method] = False
@@ -725,9 +721,8 @@ class GroupAccess(BaseAccess):
return True return True
def can_start(self, obj, validate_license=True): def can_start(self, obj, validate_license=True):
# Used as another alias to inventory_source start access for user_capabilities if obj and obj.inventory:
if obj and obj.inventory_source: return self.user.can_access(Inventory, 'start', obj.inventory, validate_license=validate_license)
return self.user.can_access(InventorySource, 'start', obj.inventory_source, validate_license=validate_license)
return False return False
@@ -747,9 +742,7 @@ class InventorySourceAccess(BaseAccess):
Q(group__inventory_id__in=inventory_ids)) Q(group__inventory_id__in=inventory_ids))
def can_read(self, obj): def can_read(self, obj):
if obj and obj.group: if obj and obj.inventory:
return self.user.can_access(Group, 'read', obj.group)
elif obj and obj.inventory:
return self.user.can_access(Inventory, 'read', obj.inventory) return self.user.can_access(Inventory, 'read', obj.inventory)
else: else:
return False return False
@@ -760,9 +753,9 @@ class InventorySourceAccess(BaseAccess):
def can_change(self, obj, data): def can_change(self, obj, data):
# Checks for admin or change permission on group. # Checks for admin or change permission on group.
if obj and obj.group: if obj and obj.inventory:
return ( return (
self.user.can_access(Group, 'change', obj.group, None) and self.user.can_access(Inventory, 'change', obj.inventory, None) and
self.check_related('credential', Credential, data, obj=obj, role_field='use_role') self.check_related('credential', Credential, data, obj=obj, role_field='use_role')
) )
# Can't change inventory sources attached to only the inventory, since # Can't change inventory sources attached to only the inventory, since
@@ -771,9 +764,7 @@ class InventorySourceAccess(BaseAccess):
return False return False
def can_start(self, obj, validate_license=True): def can_start(self, obj, validate_license=True):
if obj and obj.group: if obj and obj.inventory:
return obj.can_update and self.user in obj.group.inventory.update_role
elif obj and obj.inventory:
return obj.can_update and self.user in obj.inventory.update_role return obj.can_update and self.user in obj.inventory.update_role
return False return False

View File

@@ -1,44 +0,0 @@
# -*- coding: utf-8 -*-
# Python
from __future__ import unicode_literals
# Django
from django.db import migrations, models
from psycopg2.extensions import AsIs
# AWX
import awx.main.fields
from awx.main.models import FactLatest
class Migration(migrations.Migration):
dependencies = [
('main', '0036_v311_insights'),
]
operations = [
migrations.CreateModel(
name='FactLatest',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('timestamp', models.DateTimeField(default=None, help_text='Date and time of the corresponding fact scan gathering time.', editable=False)),
('module', models.CharField(max_length=128)),
('facts', awx.main.fields.JSONBField(default={}, help_text='Arbitrary JSON structure of module facts captured at timestamp for a single host.', blank=True)),
('host', models.ForeignKey(related_name='facts_latest', to='main.Host', help_text='Host for the facts that the fact scan captured.')),
],
),
migrations.AlterField(
model_name='fact',
name='facts',
field=awx.main.fields.JSONBField(default={}, help_text='Arbitrary JSON structure of module facts captured at timestamp for a single host.', blank=True),
),
migrations.AlterIndexTogether(
name='factlatest',
index_together=set([('timestamp', 'module', 'host')]),
),
migrations.RunSQL([("CREATE INDEX fact_latest_facts_default_gin ON %s USING gin"
"(facts jsonb_path_ops);", [AsIs(FactLatest._meta.db_table)])],
[('DROP INDEX fact_latest_facts_default_gin;', None)]),
]

View File

@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0036_v311_insights'),
]
operations = [
migrations.RemoveField(
model_name='inventorysource',
name='group',
),
]

View File

@@ -19,7 +19,7 @@ from django.utils.timezone import now
# AWX # AWX
from awx.api.versioning import reverse from awx.api.versioning import reverse
from awx.main.constants import CLOUD_PROVIDERS from awx.main.constants import CLOUD_PROVIDERS
from awx.main.fields import AutoOneToOneField, ImplicitRoleField from awx.main.fields import ImplicitRoleField
from awx.main.managers import HostManager from awx.main.managers import HostManager
from awx.main.models.base import * # noqa from awx.main.models.base import * # noqa
from awx.main.models.unified_jobs import * # noqa from awx.main.models.unified_jobs import * # noqa
@@ -1063,14 +1063,6 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions):
editable=False, editable=False,
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
group = AutoOneToOneField(
'Group',
related_name='inventory_source',
null=True,
default=None,
editable=False,
on_delete=models.CASCADE,
)
update_on_launch = models.BooleanField( update_on_launch = models.BooleanField(
default=False, default=False,
) )
@@ -1092,20 +1084,12 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions):
# If update_fields has been specified, add our field names to it, # If update_fields has been specified, add our field names to it,
# if it hasn't been specified, then we're just doing a normal save. # if it hasn't been specified, then we're just doing a normal save.
update_fields = kwargs.get('update_fields', []) update_fields = kwargs.get('update_fields', [])
# Update inventory from group (if available).
if self.group and not self.inventory:
self.inventory = self.group.inventory
if 'inventory' not in update_fields:
update_fields.append('inventory')
# Set name automatically. Include PK (or placeholder) to make sure the names are always unique. # Set name automatically. Include PK (or placeholder) to make sure the names are always unique.
replace_text = '__replace_%s__' % now() replace_text = '__replace_%s__' % now()
old_name_re = re.compile(r'^inventory_source \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.*?$') old_name_re = re.compile(r'^inventory_source \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.*?$')
if not self.name or old_name_re.match(self.name) or '__replace_' in self.name: if not self.name or old_name_re.match(self.name) or '__replace_' in self.name:
if self.inventory and self.group and self.pk: if self.inventory and self.pk:
self.name = '%s (%s - %s)' % (self.group.name, self.inventory.name, self.pk)
elif self.inventory and self.group:
self.name = '%s (%s - %s)' % (self.group.name, self.inventory.name, replace_text)
elif self.inventory and self.pk:
self.name = '%s (%s)' % (self.inventory.name, self.pk) self.name = '%s (%s)' % (self.inventory.name, self.pk)
elif self.inventory: elif self.inventory:
self.name = '%s (%s)' % (self.inventory.name, replace_text) self.name = '%s (%s)' % (self.inventory.name, replace_text)
@@ -1237,10 +1221,7 @@ class InventoryUpdate(UnifiedJob, InventorySourceOptions, JobNotificationMixin):
update_fields = kwargs.get('update_fields', []) update_fields = kwargs.get('update_fields', [])
inventory_source = self.inventory_source inventory_source = self.inventory_source
if inventory_source.inventory and self.name == inventory_source.name: if inventory_source.inventory and self.name == inventory_source.name:
if inventory_source.group: self.name = inventory_source.inventory.name
self.name = '%s (%s)' % (inventory_source.group.name, inventory_source.inventory.name)
else:
self.name = inventory_source.inventory.name
if 'name' not in update_fields: if 'name' not in update_fields:
update_fields.append('name') update_fields.append('name')
super(InventoryUpdate, self).save(*args, **kwargs) super(InventoryUpdate, self).save(*args, **kwargs)

View File

@@ -372,9 +372,6 @@ model_serializer_mapping = {
def activity_stream_create(sender, instance, created, **kwargs): def activity_stream_create(sender, instance, created, **kwargs):
if created and activity_stream_enabled: if created and activity_stream_enabled:
# Skip recording any inventory source directly associated with a group.
if isinstance(instance, InventorySource) and instance.group:
return
object1 = camelcase_to_underscore(instance.__class__.__name__) object1 = camelcase_to_underscore(instance.__class__.__name__)
changes = model_to_dict(instance, model_serializer_mapping) changes = model_to_dict(instance, model_serializer_mapping)
# Special case where Job survey password variables need to be hidden # Special case where Job survey password variables need to be hidden

View File

@@ -343,7 +343,8 @@ def group(inventory):
@pytest.fixture @pytest.fixture
def inventory_source(group, inventory): def inventory_source(group, inventory):
return InventorySource.objects.create(name=group.name, group=group, group.inventory = inventory
return InventorySource.objects.create(name=group.name,
inventory=inventory, source='gce') inventory=inventory, source='gce')

View File

@@ -3,7 +3,7 @@ import pytest
from awx.api.versioning import reverse from awx.api.versioning import reverse
from awx.main.models.notifications import NotificationTemplate, Notification from awx.main.models.notifications import NotificationTemplate, Notification
from awx.main.models.inventory import Inventory, Group from awx.main.models.inventory import Inventory, InventorySource
from awx.main.models.jobs import JobTemplate from awx.main.models.jobs import JobTemplate
@@ -84,8 +84,8 @@ def test_inherited_notification_templates(get, post, user, organization, project
notification_templates.append(response.data['id']) notification_templates.append(response.data['id'])
i = Inventory.objects.create(name='test', organization=organization) i = Inventory.objects.create(name='test', organization=organization)
i.save() i.save()
g = Group.objects.create(name='test', inventory=i) isrc = InventorySource.objects.create(name='test', inventory=i)
g.save() isrc.save()
jt = JobTemplate.objects.create(name='test', inventory=i, project=project, playbook='debug.yml') jt = JobTemplate.objects.create(name='test', inventory=i, project=project, playbook='debug.yml')
jt.save() jt.save()
url = reverse('api:organization_notification_templates_any_list', kwargs={'pk': organization.id}) url = reverse('api:organization_notification_templates_any_list', kwargs={'pk': organization.id})
@@ -99,7 +99,7 @@ def test_inherited_notification_templates(get, post, user, organization, project
assert response.status_code == 204 assert response.status_code == 204
assert len(jt.notification_templates['any']) == 3 assert len(jt.notification_templates['any']) == 3
assert len(project.notification_templates['any']) == 2 assert len(project.notification_templates['any']) == 2
assert len(g.inventory_source.notification_templates['any']) == 1 assert len(isrc.notification_templates['any']) == 1
@pytest.mark.django_db @pytest.mark.django_db