mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-04-01 18:01:40 +08:00
Add ModuleBuild methods for getting list of streams, last build in a name:stream and all builds in name:stream:version.
This commit is contained in:
@@ -38,10 +38,12 @@ from module_build_service import db, log, get_url_for, app, conf
|
||||
import module_build_service.messaging
|
||||
|
||||
from sqlalchemy.orm import lazyload
|
||||
from sqlalchemy import func, and_
|
||||
import gi
|
||||
gi.require_version('Modulemd', '1.0') # noqa
|
||||
from gi.repository import Modulemd
|
||||
|
||||
|
||||
# Just like koji.BUILD_STATES, except our own codes for modules.
|
||||
BUILD_STATES = {
|
||||
# This is (obviously) the first state a module build enters.
|
||||
@@ -241,6 +243,42 @@ class ModuleBuild(MBSBase):
|
||||
if component.batch <= self.batch
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def get_last_build_in_all_streams(session, name):
|
||||
"""
|
||||
Returns list of all last ModuleBuilds in "ready" state for all
|
||||
streams for given module `name`.
|
||||
"""
|
||||
subq = session.query(
|
||||
func.max(ModuleBuild.id).label('id')
|
||||
).group_by(ModuleBuild.name, ModuleBuild.stream).filter_by(
|
||||
name=name, state=BUILD_STATES["ready"]).subquery('t2')
|
||||
query = session.query(ModuleBuild).join(
|
||||
subq, and_(ModuleBuild.id == subq.c.id))
|
||||
return query.all()
|
||||
|
||||
@staticmethod
|
||||
def get_last_build_in_stream(session, name, stream):
|
||||
"""
|
||||
Returns the last build in "ready" state for given name:stream.
|
||||
"""
|
||||
query = session.query(ModuleBuild)
|
||||
query = query.filter_by(name=name, stream=stream,
|
||||
state=BUILD_STATES["ready"])
|
||||
query = query.order_by(ModuleBuild.id.desc())
|
||||
return query.first()
|
||||
|
||||
@staticmethod
|
||||
def get_builds_in_version(session, name, stream, version):
|
||||
"""
|
||||
Returns list of all module builds in "ready" state for given
|
||||
name:stream:version - it means all the contexts of this module.
|
||||
"""
|
||||
query = session.query(ModuleBuild)
|
||||
query = query.filter_by(name=name, stream=stream, version=version,
|
||||
state=BUILD_STATES["ready"])
|
||||
return query.all()
|
||||
|
||||
def mmd(self):
|
||||
try:
|
||||
mmd = Modulemd.Module().new_from_string(self.modulemd)
|
||||
|
||||
@@ -24,6 +24,7 @@ import os
|
||||
from datetime import datetime, timedelta
|
||||
from mock import patch
|
||||
import time
|
||||
import hashlib
|
||||
from traceback import extract_stack
|
||||
|
||||
import gi
|
||||
@@ -92,75 +93,86 @@ def clean_database():
|
||||
db.create_all()
|
||||
|
||||
|
||||
def init_data(data_size=10):
|
||||
def init_data(data_size=10, contexts=False):
|
||||
"""
|
||||
Creates data_size * 3 modules in database in different states and
|
||||
with different component builds. See _populate_data for more info.
|
||||
|
||||
:param bool contexts: If True, multiple streams and contexts in each stream
|
||||
are generated for 'nginx' module.
|
||||
"""
|
||||
clean_database()
|
||||
with make_session(conf) as session:
|
||||
_populate_data(session, data_size)
|
||||
_populate_data(session, data_size, contexts=contexts)
|
||||
|
||||
|
||||
def _populate_data(session, data_size=10):
|
||||
def _populate_data(session, data_size=10, contexts=False):
|
||||
num_contexts = 2 if contexts else 1
|
||||
for index in range(data_size):
|
||||
build_one = ModuleBuild()
|
||||
build_one.name = 'nginx'
|
||||
build_one.stream = '1'
|
||||
build_one.version = 2
|
||||
build_one.state = BUILD_STATES['done']
|
||||
with open(os.path.join(base_dir, "staged_data", "nginx_mmd.yaml")) as mmd:
|
||||
build_one.modulemd = mmd.read()
|
||||
build_one.koji_tag = 'module-nginx-1.2'
|
||||
build_one.scmurl = ('git://pkgs.domain.local/modules/nginx?'
|
||||
'#ba95886c7a443b36a9ce31abda1f9bef22f2f8c9')
|
||||
build_one.batch = 2
|
||||
# https://www.youtube.com/watch?v=iQGwrK_yDEg
|
||||
build_one.owner = 'Moe Szyslak'
|
||||
build_one.time_submitted = \
|
||||
datetime(2016, 9, 3, 11, 23, 20) + timedelta(minutes=(index * 10))
|
||||
build_one.time_modified = \
|
||||
datetime(2016, 9, 3, 11, 25, 32) + timedelta(minutes=(index * 10))
|
||||
build_one.time_completed = \
|
||||
datetime(2016, 9, 3, 11, 25, 32) + timedelta(minutes=(index * 10))
|
||||
build_one.rebuild_strategy = 'changed-and-after'
|
||||
session.add(build_one)
|
||||
session.commit()
|
||||
build_one_component_release = get_rpm_release(build_one)
|
||||
for context in range(num_contexts):
|
||||
build_one = ModuleBuild()
|
||||
build_one.name = 'nginx'
|
||||
build_one.stream = '1'
|
||||
build_one.version = 2 + index
|
||||
build_one.state = BUILD_STATES['ready']
|
||||
if contexts:
|
||||
build_one.stream = str(index)
|
||||
unique_hash = hashlib.sha1("%s:%s:%d:%d" % (
|
||||
build_one.name, build_one.stream, build_one.version, context)).hexdigest()
|
||||
build_one.build_context = unique_hash
|
||||
build_one.runtime_context = unique_hash
|
||||
with open(os.path.join(base_dir, "staged_data", "nginx_mmd.yaml")) as mmd:
|
||||
build_one.modulemd = mmd.read()
|
||||
build_one.koji_tag = 'module-nginx-1.2'
|
||||
build_one.scmurl = ('git://pkgs.domain.local/modules/nginx?'
|
||||
'#ba95886c7a443b36a9ce31abda1f9bef22f2f8c9')
|
||||
build_one.batch = 2
|
||||
# https://www.youtube.com/watch?v=iQGwrK_yDEg
|
||||
build_one.owner = 'Moe Szyslak'
|
||||
build_one.time_submitted = \
|
||||
datetime(2016, 9, 3, 11, 23, 20) + timedelta(minutes=(index * 10))
|
||||
build_one.time_modified = \
|
||||
datetime(2016, 9, 3, 11, 25, 32) + timedelta(minutes=(index * 10))
|
||||
build_one.time_completed = \
|
||||
datetime(2016, 9, 3, 11, 25, 32) + timedelta(minutes=(index * 10))
|
||||
build_one.rebuild_strategy = 'changed-and-after'
|
||||
session.add(build_one)
|
||||
session.commit()
|
||||
build_one_component_release = get_rpm_release(build_one)
|
||||
|
||||
component_one_build_one = ComponentBuild()
|
||||
component_one_build_one.package = 'nginx'
|
||||
component_one_build_one.scmurl = \
|
||||
('git://pkgs.domain.local/rpms/nginx?'
|
||||
'#ga95886c8a443b36a9ce31abda1f9bed22f2f8c3')
|
||||
component_one_build_one.format = 'rpms'
|
||||
component_one_build_one.task_id = 12312345 + index
|
||||
component_one_build_one.state = koji.BUILD_STATES['COMPLETE']
|
||||
component_one_build_one.nvr = 'nginx-1.10.1-2.{0}'.format(build_one_component_release)
|
||||
component_one_build_one.batch = 1
|
||||
component_one_build_one.module_id = 1 + index * 3
|
||||
component_one_build_one.tagged = True
|
||||
component_one_build_one.tagged_in_final = True
|
||||
component_one_build_one = ComponentBuild()
|
||||
component_one_build_one.package = 'nginx'
|
||||
component_one_build_one.scmurl = \
|
||||
('git://pkgs.domain.local/rpms/nginx?'
|
||||
'#ga95886c8a443b36a9ce31abda1f9bed22f2f8c3')
|
||||
component_one_build_one.format = 'rpms'
|
||||
component_one_build_one.task_id = 12312345 + index
|
||||
component_one_build_one.state = koji.BUILD_STATES['COMPLETE']
|
||||
component_one_build_one.nvr = 'nginx-1.10.1-2.{0}'.format(build_one_component_release)
|
||||
component_one_build_one.batch = 1
|
||||
component_one_build_one.module_id = 1 + index * 3
|
||||
component_one_build_one.tagged = True
|
||||
component_one_build_one.tagged_in_final = True
|
||||
|
||||
component_two_build_one = ComponentBuild()
|
||||
component_two_build_one.package = 'module-build-macros'
|
||||
component_two_build_one.scmurl = \
|
||||
('/tmp/module_build_service-build-macrosWZUPeK/SRPMS/'
|
||||
'module-build-macros-0.1-1.module_nginx_1_2.src.rpm')
|
||||
component_two_build_one.format = 'rpms'
|
||||
component_two_build_one.task_id = 12312321 + index
|
||||
component_two_build_one.state = koji.BUILD_STATES['COMPLETE']
|
||||
component_two_build_one.nvr = \
|
||||
'module-build-macros-01-1.{0}'.format(build_one_component_release)
|
||||
component_two_build_one.batch = 2
|
||||
component_two_build_one.module_id = 1 + index * 3
|
||||
component_two_build_one.tagged = True
|
||||
component_two_build_one.tagged_in_final = True
|
||||
component_two_build_one = ComponentBuild()
|
||||
component_two_build_one.package = 'module-build-macros'
|
||||
component_two_build_one.scmurl = \
|
||||
('/tmp/module_build_service-build-macrosWZUPeK/SRPMS/'
|
||||
'module-build-macros-0.1-1.module_nginx_1_2.src.rpm')
|
||||
component_two_build_one.format = 'rpms'
|
||||
component_two_build_one.task_id = 12312321 + index
|
||||
component_two_build_one.state = koji.BUILD_STATES['COMPLETE']
|
||||
component_two_build_one.nvr = \
|
||||
'module-build-macros-01-1.{0}'.format(build_one_component_release)
|
||||
component_two_build_one.batch = 2
|
||||
component_two_build_one.module_id = 1 + index * 3
|
||||
component_two_build_one.tagged = True
|
||||
component_two_build_one.tagged_in_final = True
|
||||
|
||||
build_two = ModuleBuild()
|
||||
build_two.name = 'postgressql'
|
||||
build_two.stream = '1'
|
||||
build_two.version = 2
|
||||
build_two.version = 2 + index
|
||||
build_two.state = BUILD_STATES['done']
|
||||
build_two.modulemd = '' # Skipping since no tests rely on it
|
||||
build_two.koji_tag = 'module-postgressql-1.2'
|
||||
@@ -211,7 +223,7 @@ def _populate_data(session, data_size=10):
|
||||
build_three = ModuleBuild()
|
||||
build_three.name = 'testmodule'
|
||||
build_three.stream = '4.3.43'
|
||||
build_three.version = 6
|
||||
build_three.version = 6 + index
|
||||
build_three.state = BUILD_STATES['wait']
|
||||
build_three.modulemd = '' # Skipping because no tests rely on it
|
||||
build_three.koji_tag = None
|
||||
|
||||
@@ -27,6 +27,7 @@ gi.require_version('Modulemd', '1.0') # noqa
|
||||
from gi.repository import Modulemd
|
||||
|
||||
from tests.test_models import init_data
|
||||
from tests import init_data as init_data_contexts
|
||||
from module_build_service import conf
|
||||
from module_build_service.models import ComponentBuild, ModuleBuild, make_session
|
||||
|
||||
@@ -74,3 +75,30 @@ class TestModels:
|
||||
assert build.build_context == 'f6e2aeec7576196241b9afa0b6b22acf2b6873d7'
|
||||
assert build.runtime_context == '1739827b08388842fc90ccc0b6070c59b7d856fc'
|
||||
assert build.context == 'e7a3d35e'
|
||||
|
||||
class TestModelsGetStreamsContexts:
|
||||
def setup_method(self, test_method):
|
||||
init_data_contexts(contexts=True)
|
||||
|
||||
def test_get_last_build_in_all_streams(self):
|
||||
with make_session(conf) as session:
|
||||
builds = ModuleBuild.get_last_build_in_all_streams(
|
||||
session, "nginx")
|
||||
builds = ["%s:%s:%s" % (build.name, build.stream, str(build.version))
|
||||
for build in builds]
|
||||
assert builds == ["nginx:%d:%d" % (i, i + 2) for i in range(10)]
|
||||
|
||||
def test_get_last_build_in_stream(self):
|
||||
with make_session(conf) as session:
|
||||
build = ModuleBuild.get_last_build_in_stream(
|
||||
session, "nginx", "1")
|
||||
build = "%s:%s:%s" % (build.name, build.stream, str(build.version))
|
||||
assert build == 'nginx:1:3'
|
||||
|
||||
def test_get_builds_in_version(self):
|
||||
with make_session(conf) as session:
|
||||
builds = ModuleBuild.get_builds_in_version(
|
||||
session, "nginx", "1", "3")
|
||||
builds = ["%s:%s:%s:%s" % (build.name, build.stream, str(build.version),
|
||||
build.context) for build in builds]
|
||||
assert builds == ['nginx:1:3:d5a6c0fa', 'nginx:1:3:795e97c1']
|
||||
|
||||
@@ -124,7 +124,7 @@ class TestViews:
|
||||
assert data['name'] == 'nginx'
|
||||
assert data['owner'] == 'Moe Szyslak'
|
||||
assert data['stream'] == '1'
|
||||
assert data['state'] == 3
|
||||
assert data['state'] == 5
|
||||
assert data['state_reason'] is None
|
||||
assert data['tasks'] == {
|
||||
'rpms': {
|
||||
@@ -154,8 +154,8 @@ class TestViews:
|
||||
assert data['id'] == 1
|
||||
assert data['context'] == '00000000'
|
||||
assert data['name'] == 'nginx'
|
||||
assert data['state'] == 3
|
||||
assert data['state_name'] == 'done'
|
||||
assert data['state'] == 5
|
||||
assert data['state_name'] == 'ready'
|
||||
assert data['stream'] == '1'
|
||||
assert data['version'] == '2'
|
||||
|
||||
@@ -174,8 +174,8 @@ class TestViews:
|
||||
assert data['owner'] == 'Moe Szyslak'
|
||||
assert data['scmurl'] == ('git://pkgs.domain.local/modules/nginx'
|
||||
'?#ba95886c7a443b36a9ce31abda1f9bef22f2f8c9')
|
||||
assert data['state'] == 3
|
||||
assert data['state_name'] == 'done'
|
||||
assert data['state'] == 5
|
||||
assert data['state_name'] == 'ready'
|
||||
assert data['state_reason'] is None
|
||||
# State trace is empty because we directly created these builds and didn't have them
|
||||
# transition, which creates these entries
|
||||
@@ -240,18 +240,18 @@ class TestViews:
|
||||
"state": 1,
|
||||
"state_reason": None,
|
||||
"task_id": 47383994,
|
||||
"nvr": "module-build-macros-01-1.module+6+8d3cee59"
|
||||
"nvr": "module-build-macros-01-1.module+6+f95651e2"
|
||||
},
|
||||
"rubygem-rails": {
|
||||
"state": 3,
|
||||
"state_reason": None,
|
||||
"task_id": 2433434,
|
||||
"nvr": "postgresql-9.5.3-4.module+6+8d3cee59"
|
||||
"nvr": "postgresql-9.5.3-4.module+6+f95651e2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"owner": "some_other_user",
|
||||
"version": "6",
|
||||
"version": "7",
|
||||
"state_reason": None,
|
||||
"state": 1,
|
||||
"stream": "4.3.43",
|
||||
@@ -274,18 +274,18 @@ class TestViews:
|
||||
"state": 1,
|
||||
"state_reason": None,
|
||||
"task_id": 47383994,
|
||||
"nvr": "module-build-macros-01-1.module+5+0557c87d"
|
||||
"nvr": "module-build-macros-01-1.module+5+fa947d31"
|
||||
},
|
||||
"postgresql": {
|
||||
"state": 1,
|
||||
"state_reason": None,
|
||||
"task_id": 2433434,
|
||||
"nvr": "postgresql-9.5.3-4.module+5+0557c87d"
|
||||
"nvr": "postgresql-9.5.3-4.module+5+fa947d31"
|
||||
}
|
||||
}
|
||||
},
|
||||
"owner": "some_user",
|
||||
"version": "2",
|
||||
"version": "3",
|
||||
"state_reason": None,
|
||||
"state": 3,
|
||||
"stream": "1",
|
||||
@@ -300,6 +300,7 @@ class TestViews:
|
||||
"koji_tag": "module-postgressql-1.2"
|
||||
}
|
||||
]
|
||||
|
||||
assert items == expected
|
||||
|
||||
def test_query_builds_with_id_error(self):
|
||||
@@ -439,7 +440,7 @@ class TestViews:
|
||||
rv = self.client.get(
|
||||
'/module-build-service/1/module-builds/?state=3')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 4
|
||||
assert data['meta']['total'] == 2
|
||||
|
||||
def test_query_builds_two_filters(self):
|
||||
rv = self.client.get('/module-build-service/1/module-builds/?owner=Moe%20Szyslak'
|
||||
@@ -451,12 +452,11 @@ class TestViews:
|
||||
rv = self.client.get(
|
||||
'/module-build-service/1/module-builds/?name=postgressql&stream=1&version=2')
|
||||
data = json.loads(rv.data)
|
||||
# TODO: The nsv should really be unique in the test data
|
||||
for item in data['items']:
|
||||
assert item['name'] == 'postgressql'
|
||||
assert item['stream'] == '1'
|
||||
assert item['version'] == '2'
|
||||
assert data['meta']['total'] == 2
|
||||
assert data['meta']['total'] == 1
|
||||
|
||||
def test_query_builds_filter_invalid_date(self):
|
||||
rv = self.client.get(
|
||||
|
||||
Reference in New Issue
Block a user