Remove stats from the model, move it to hosts

The stats table was redundant - it linked the stats for a host to
a playbook. The hosts are already linked to the playbooks.

Change-Id: I47dd903b73f9b6e9007c8fdfbc0c99dfa6f3f703
This commit is contained in:
David Moreau Simard
2019-03-18 20:44:10 -04:00
parent fe3e20d26a
commit 874f0b3691
8 changed files with 11 additions and 176 deletions

View File

@@ -1,4 +1,4 @@
# Generated by Django 2.1.7 on 2019-02-22 19:43
# Generated by Django 2.1.7 on 2019-03-19 00:42
from django.db import migrations, models
import django.db.models.deletion
@@ -47,6 +47,11 @@ class Migration(migrations.Migration):
('name', models.CharField(max_length=255)),
('facts', models.BinaryField(max_length=4294967295)),
('alias', models.CharField(max_length=255, null=True)),
('changed', models.IntegerField(default=0)),
('failed', models.IntegerField(default=0)),
('ok', models.IntegerField(default=0)),
('skipped', models.IntegerField(default=0)),
('unreachable', models.IntegerField(default=0)),
],
options={
'db_table': 'hosts',
@@ -133,24 +138,6 @@ class Migration(migrations.Migration):
'db_table': 'results',
},
),
migrations.CreateModel(
name='Stats',
fields=[
('id', models.BigAutoField(editable=False, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('changed', models.IntegerField(default=0)),
('failed', models.IntegerField(default=0)),
('ok', models.IntegerField(default=0)),
('skipped', models.IntegerField(default=0)),
('unreachable', models.IntegerField(default=0)),
('host', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stats', to='api.Host')),
('playbook', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stats', to='api.Playbook')),
],
options={
'db_table': 'stats',
},
),
migrations.CreateModel(
name='Task',
fields=[
@@ -198,10 +185,6 @@ class Migration(migrations.Migration):
name='playbook',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='api.Playbook'),
),
migrations.AlterUniqueTogether(
name='stats',
unique_together={('host', 'playbook')},
),
migrations.AlterUniqueTogether(
name='record',
unique_together={('key', 'playbook')},

View File

@@ -220,34 +220,17 @@ class Host(Base):
# The logic for supplying aliases does not live here, it's provided by the
# clients and consumers.
alias = models.CharField(max_length=255, null=True)
playbook = models.ForeignKey(Playbook, on_delete=models.CASCADE, related_name="hosts")
def __str__(self):
return "<Host %s:%s>" % (self.id, self.name)
class Stats(Base):
"""
Stats for a host for a playbook.
"""
class Meta:
db_table = "stats"
unique_together = ("host", "playbook")
playbook = models.ForeignKey(Playbook, on_delete=models.CASCADE, related_name="stats")
host = models.ForeignKey(Host, on_delete=models.CASCADE, related_name="stats")
changed = models.IntegerField(default=0)
failed = models.IntegerField(default=0)
ok = models.IntegerField(default=0)
skipped = models.IntegerField(default=0)
unreachable = models.IntegerField(default=0)
playbook = models.ForeignKey(Playbook, on_delete=models.CASCADE, related_name="hosts")
def __str__(self):
# Verbose because it's otherwise kind of useless
return "<Stats for {host} ({id}) in playbook {playbook}>".format(
host=self.host.name, id=self.host.id, playbook=self.playbook.id
)
return "<Host %s:%s>" % (self.id, self.name)
class Result(Duration):

View File

@@ -148,12 +148,6 @@ class SimplePlaySerializer(serializers.ModelSerializer):
fields = "__all__"
class StatsSerializer(serializers.ModelSerializer):
class Meta:
model = models.Stats
fields = "__all__"
class PlaybookSerializer(DurationSerializer):
class Meta:
model = models.Playbook

View File

@@ -121,16 +121,3 @@ class RecordFactory(factory.DjangoModelFactory):
value = utils.compressed_obj(RECORD_LIST)
type = "list"
playbook = factory.SubFactory(PlaybookFactory)
class StatsFactory(factory.DjangoModelFactory):
class Meta:
model = models.Stats
changed = 1
failed = 0
ok = 2
skipped = 1
unreachable = 0
playbook = factory.SubFactory(PlaybookFactory)
host = factory.SubFactory(HostFactory)

View File

@@ -1,103 +0,0 @@
# Copyright (c) 2018 Red Hat, Inc.
#
# This file is part of ARA Records Ansible.
#
# ARA is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ARA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ARA. If not, see <http://www.gnu.org/licenses/>.
from rest_framework.test import APITestCase
from ara.api import models, serializers
from ara.api.tests import factories
class StatsTestCase(APITestCase):
def test_stats_factory(self):
stats = factories.StatsFactory(changed=2, failed=1, ok=3, skipped=2, unreachable=1)
self.assertEqual(stats.changed, 2)
self.assertEqual(stats.failed, 1)
self.assertEqual(stats.ok, 3)
self.assertEqual(stats.skipped, 2)
self.assertEqual(stats.unreachable, 1)
def test_stats_serializer(self):
playbook = factories.PlaybookFactory()
host = factories.HostFactory()
serializer = serializers.StatsSerializer(data=dict(playbook=playbook.id, host=host.id, ok=9001))
serializer.is_valid()
stats = serializer.save()
stats.refresh_from_db()
self.assertEqual(stats.playbook.id, playbook.id)
self.assertEqual(stats.host.id, host.id)
self.assertEqual(stats.ok, 9001)
def test_create_stats(self):
playbook = factories.PlaybookFactory()
host = factories.HostFactory()
self.assertEqual(0, models.Stats.objects.count())
request = self.client.post("/api/v1/stats", dict(playbook=playbook.id, host=host.id, ok=9001))
self.assertEqual(201, request.status_code)
self.assertEqual(1, models.Stats.objects.count())
def test_get_no_stats(self):
request = self.client.get("/api/v1/stats")
self.assertEqual(0, len(request.data["results"]))
def test_get_stats(self):
stats = factories.StatsFactory()
request = self.client.get("/api/v1/stats")
self.assertEqual(1, len(request.data["results"]))
self.assertEqual(stats.ok, request.data["results"][0]["ok"])
def test_get_stats_by_playbook(self):
playbook = factories.PlaybookFactory()
host_one = factories.HostFactory(name="one")
host_two = factories.HostFactory(name="two")
stats = factories.StatsFactory(host=host_one, playbook=playbook, ok=9001)
factories.StatsFactory(host=host_two, playbook=playbook)
request = self.client.get("/api/v1/stats?playbook=%s" % playbook.id)
self.assertEqual(2, len(request.data["results"]))
self.assertEqual(host_one.id, request.data["results"][0]["id"])
self.assertEqual(stats.ok, request.data["results"][0]["ok"])
self.assertEqual(host_two.id, request.data["results"][1]["id"])
def test_get_stats_by_host(self):
playbook = factories.PlaybookFactory()
host_one = factories.HostFactory(name="one")
host_two = factories.HostFactory(name="two")
stats = factories.StatsFactory(host=host_one, playbook=playbook, ok=9001)
factories.StatsFactory(host=host_two, playbook=playbook)
request = self.client.get("/api/v1/stats?host=%s" % host_one.id)
self.assertEqual(1, len(request.data["results"]))
self.assertEqual(stats.ok, request.data["results"][0]["ok"])
self.assertEqual(host_one.id, request.data["results"][0]["id"])
def test_get_stats_id(self):
stats = factories.StatsFactory()
request = self.client.get("/api/v1/stats/%s" % stats.id)
self.assertEqual(stats.ok, request.data["ok"])
def test_partial_update_stats(self):
stats = factories.StatsFactory()
self.assertNotEqual(9001, stats.ok)
request = self.client.patch("/api/v1/stats/%s" % stats.id, dict(ok=9001))
self.assertEqual(200, request.status_code)
stats_updated = models.Stats.objects.get(id=stats.id)
self.assertEqual(9001, stats_updated.ok)
def test_delete_stats(self):
stats = factories.StatsFactory()
self.assertEqual(1, models.Stats.objects.all().count())
request = self.client.delete("/api/v1/stats/%s" % stats.id)
self.assertEqual(204, request.status_code)
self.assertEqual(0, models.Stats.objects.all().count())

View File

@@ -28,7 +28,6 @@ router.register("hosts", views.HostViewSet, base_name="host")
router.register("results", views.ResultViewSet, base_name="result")
router.register("files", views.FileViewSet, base_name="file")
router.register("records", views.RecordViewSet, base_name="record")
router.register("stats", views.StatsViewSet, base_name="stats")
router.register("info", views.InfoView, base_name="info")
urlpatterns = router.urls

View File

@@ -83,9 +83,3 @@ class RecordViewSet(viewsets.ModelViewSet):
queryset = models.Record.objects.all()
serializer_class = serializers.RecordSerializer
filter_fields = ("playbook", "key")
class StatsViewSet(viewsets.ModelViewSet):
queryset = models.Stats.objects.all()
serializer_class = serializers.StatsSerializer
filter_fields = ("playbook", "host")