move the 'freeze' command in a file on its own and implement issue 1515
This commit is contained in:
parent
c82d7c03ad
commit
b2fff384b2
@ -267,7 +267,6 @@ def _staging_get_rings(self, opts):
|
|||||||
ret[entry.attrib['name']] = prj
|
ret[entry.attrib['name']] = prj
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def _staging_one_request(self, rq, opts):
|
def _staging_one_request(self, rq, opts):
|
||||||
if (opts.verbose):
|
if (opts.verbose):
|
||||||
ET.dump(rq)
|
ET.dump(rq)
|
||||||
@ -309,59 +308,6 @@ def _staging_one_request(self, rq, opts):
|
|||||||
|
|
||||||
self._staging_change_review_state(opts, id, 'accepted', by_group='factory-staging', message=msg)
|
self._staging_change_review_state(opts, id, 'accepted', by_group='factory-staging', message=msg)
|
||||||
|
|
||||||
|
|
||||||
def _staging_check_one_source(self, flink, si, opts):
|
|
||||||
package = si.get('package')
|
|
||||||
# we have to check if its a link within the staging project
|
|
||||||
# in this case we need to keep the link as is, and not freezing
|
|
||||||
# the target. Otherwise putting kernel-source into staging prj
|
|
||||||
# won't get updated kernel-default (and many other cases)
|
|
||||||
for linked in si.findall('linked'):
|
|
||||||
if linked.get('project') in self.projectlinks:
|
|
||||||
# take the unexpanded md5 from Factory link
|
|
||||||
url = makeurl(opts.apiurl, ['source', 'openSUSE:Factory', package], { 'view': 'info', 'nofilename': '1' })
|
|
||||||
#print package, linked.get('package'), linked.get('project')
|
|
||||||
f = http_GET(url)
|
|
||||||
proot = ET.parse(f).getroot()
|
|
||||||
ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': proot.get('lsrcmd5'), 'vrev': si.get('vrev') })
|
|
||||||
return package
|
|
||||||
ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': si.get('srcmd5'), 'vrev': si.get('vrev') })
|
|
||||||
return package
|
|
||||||
|
|
||||||
|
|
||||||
def _staging_receive_sources(self, prj, sources, flink, opts):
|
|
||||||
url = makeurl(opts.apiurl, ['source', prj], { 'view': 'info', 'nofilename': '1' } )
|
|
||||||
f = http_GET(url)
|
|
||||||
root = ET.parse(f).getroot()
|
|
||||||
|
|
||||||
for si in root.findall('sourceinfo'):
|
|
||||||
package = self._staging_check_one_source(flink, si, opts)
|
|
||||||
sources[package] = 1
|
|
||||||
return sources
|
|
||||||
|
|
||||||
|
|
||||||
def _staging_freeze_prjlink(self, prj, opts):
|
|
||||||
url = makeurl(opts.apiurl, ['source', prj, '_meta'])
|
|
||||||
f = http_GET(url)
|
|
||||||
root = ET.parse(f).getroot()
|
|
||||||
sources = dict()
|
|
||||||
flink = ET.Element('frozenlinks')
|
|
||||||
links = root.findall('link')
|
|
||||||
links.reverse()
|
|
||||||
self.projectlinks = []
|
|
||||||
for link in links:
|
|
||||||
self.projectlinks.append(link.get('project'))
|
|
||||||
|
|
||||||
for lprj in self.projectlinks:
|
|
||||||
fl = ET.SubElement(flink, 'frozenlink', { 'project': lprj } )
|
|
||||||
sources = self._staging_receive_sources(lprj, sources, fl, opts)
|
|
||||||
|
|
||||||
url = makeurl(opts.apiurl, ['source', prj, '_project', '_frozenlinks'], { 'meta': '1' } )
|
|
||||||
f = http_PUT(url, data=ET.tostring(flink))
|
|
||||||
root = ET.parse(f).getroot()
|
|
||||||
print ET.tostring(root)
|
|
||||||
|
|
||||||
|
|
||||||
@cmdln.option('-e', '--everything', action='store_true',
|
@cmdln.option('-e', '--everything', action='store_true',
|
||||||
help='during check do not stop on first first issue and show them all')
|
help='during check do not stop on first first issue and show them all')
|
||||||
@cmdln.option('-p', '--parent', metavar='TARGETPROJECT',
|
@cmdln.option('-p', '--parent', metavar='TARGETPROJECT',
|
||||||
@ -442,7 +388,8 @@ def do_staging(self, subcmd, opts, *args):
|
|||||||
project = args[1]
|
project = args[1]
|
||||||
self._staging_submit_devel(project, opts)
|
self._staging_submit_devel(project, opts)
|
||||||
elif cmd in ['freeze']:
|
elif cmd in ['freeze']:
|
||||||
self._staging_freeze_prjlink(args[1], opts)
|
import osclib.freeze_command
|
||||||
|
osclib.freeze_command.FreezeCommand(opts.apiurl).perform(args[1])
|
||||||
elif cmd in ['select']:
|
elif cmd in ['select']:
|
||||||
# TODO: have an api call for that
|
# TODO: have an api call for that
|
||||||
stprj = 'openSUSE:Factory:Staging:%s' % args[1]
|
stprj = 'openSUSE:Factory:Staging:%s' % args[1]
|
||||||
|
192
osclib/freeze_command.py
Normal file
192
osclib/freeze_command.py
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
import osc
|
||||||
|
from osc import cmdln
|
||||||
|
from osc.core import *
|
||||||
|
import time
|
||||||
|
|
||||||
|
class FreezeCommand:
|
||||||
|
|
||||||
|
def __init__(self, apiurl):
|
||||||
|
self.apiurl = apiurl
|
||||||
|
|
||||||
|
def set_links(self):
|
||||||
|
url = makeurl(self.apiurl, ['source', self.prj, '_meta'])
|
||||||
|
f = http_GET(url)
|
||||||
|
root = ET.parse(f).getroot()
|
||||||
|
sources = dict()
|
||||||
|
flink = ET.Element('frozenlinks')
|
||||||
|
links = root.findall('link')
|
||||||
|
links.reverse()
|
||||||
|
self.projectlinks = []
|
||||||
|
for link in links:
|
||||||
|
self.projectlinks.append(link.get('project'))
|
||||||
|
|
||||||
|
def set_bootstrap_copy(self):
|
||||||
|
url = makeurl(self.apiurl, ['source', self.prj, '_meta'])
|
||||||
|
meta = self.prj_meta_for_bootstrap_copy(self.prj)
|
||||||
|
http_PUT(url, data=meta)
|
||||||
|
|
||||||
|
def create_bootstrap_aggregate(self):
|
||||||
|
self.create_bootstrap_aggregate_meta()
|
||||||
|
self.create_bootstrap_aggregate_file()
|
||||||
|
|
||||||
|
def bootstrap_packages(self):
|
||||||
|
url = makeurl(self.apiurl, ['source', 'openSUSE:Factory:Rings:0-Bootstrap'])
|
||||||
|
f = http_GET(url)
|
||||||
|
root = ET.parse(f).getroot()
|
||||||
|
l = list()
|
||||||
|
for e in root.findall('entry'):
|
||||||
|
name = e.get('name')
|
||||||
|
if name in ['rpmlint-mini-AGGR']: continue
|
||||||
|
l.append(name)
|
||||||
|
l.sort()
|
||||||
|
return l
|
||||||
|
|
||||||
|
def create_bootstrap_aggregate_file(self):
|
||||||
|
url = makeurl(self.apiurl, ['source', self.prj, 'bootstrap-copy', '_aggregate'])
|
||||||
|
|
||||||
|
root = ET.Element('aggregatelist')
|
||||||
|
a = ET.SubElement(root, 'aggregate', { 'project': "openSUSE:Factory:Rings:0-Bootstrap" } )
|
||||||
|
|
||||||
|
for package in self.bootstrap_packages():
|
||||||
|
p = ET.SubElement(a, 'package')
|
||||||
|
p.text = package
|
||||||
|
|
||||||
|
ET.SubElement(a, 'repository', { 'target': 'bootstrap_copy', 'source': 'standard' } )
|
||||||
|
ET.SubElement(a, 'repository', { 'target': 'standard', 'source': 'nothing' } )
|
||||||
|
ET.SubElement(a, 'repository', { 'target': 'images', 'source': 'nothing' } )
|
||||||
|
|
||||||
|
http_PUT(url, data=ET.tostring(root))
|
||||||
|
|
||||||
|
def create_bootstrap_aggregate_meta(self):
|
||||||
|
url = makeurl(self.apiurl, ['source', self.prj, 'bootstrap-copy', '_meta'])
|
||||||
|
|
||||||
|
root = ET.Element('package', { 'project': self.prj, 'name': 'bootstrap-copy' })
|
||||||
|
ET.SubElement(root, 'title')
|
||||||
|
ET.SubElement(root, 'description')
|
||||||
|
f = ET.SubElement(root, 'build')
|
||||||
|
# this one is to toggle
|
||||||
|
ET.SubElement(f, 'disable', { 'repository': 'bootstrap_copy' })
|
||||||
|
# this one is the global toggle
|
||||||
|
ET.SubElement(f, 'disable')
|
||||||
|
|
||||||
|
http_PUT(url, data=ET.tostring(root))
|
||||||
|
|
||||||
|
def build_switch_bootstrap_copy(self, state):
|
||||||
|
url = makeurl(self.apiurl, ['source', self.prj, 'bootstrap-copy', '_meta'])
|
||||||
|
pkgmeta = ET.parse(http_GET(url)).getroot()
|
||||||
|
|
||||||
|
for f in pkgmeta.find('build'):
|
||||||
|
if f.get('repository', None) == 'bootstrap_copy':
|
||||||
|
f.tag = state
|
||||||
|
pass
|
||||||
|
http_PUT(url, data=ET.tostring(pkgmeta))
|
||||||
|
|
||||||
|
def verify_bootstrap_copy_code(self, code):
|
||||||
|
url = makeurl(self.apiurl, ['build', self.prj, '_result'], { 'package': 'bootstrap-copy' })
|
||||||
|
|
||||||
|
root = ET.parse(http_GET(url)).getroot()
|
||||||
|
for result in root.findall('result'):
|
||||||
|
if result.get('repository') == 'bootstrap_copy':
|
||||||
|
if not result.get('code') in ['published', 'unpublished']:
|
||||||
|
print ET.tostring(result)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if result.find('status').get('code') != code:
|
||||||
|
print ET.tostring(result)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def perform(self, prj):
|
||||||
|
self.prj = prj
|
||||||
|
self.set_links()
|
||||||
|
|
||||||
|
self.freeze_prjlinks()
|
||||||
|
|
||||||
|
if 'openSUSE:Factory:Rings:1-MinimalX' in self.projectlinks \
|
||||||
|
and not 'openSUSE:Factory:Rings:0-Bootstrap' in self.projectlinks:
|
||||||
|
self.set_bootstrap_copy()
|
||||||
|
self.create_bootstrap_aggregate()
|
||||||
|
print "waiting for scheduler to disable..."
|
||||||
|
while not self.verify_bootstrap_copy_code('disabled'):
|
||||||
|
time.sleep(1)
|
||||||
|
self.build_switch_bootstrap_copy('enable')
|
||||||
|
print "waiting for scheduler to copy..."
|
||||||
|
while not self.verify_bootstrap_copy_code('succeeded'):
|
||||||
|
time.sleep(1)
|
||||||
|
self.build_switch_bootstrap_copy('disable')
|
||||||
|
|
||||||
|
def prj_meta_for_bootstrap_copy(self, prj):
|
||||||
|
root = ET.Element('project', { 'name': prj })
|
||||||
|
ET.SubElement(root, 'title')
|
||||||
|
ET.SubElement(root, 'description')
|
||||||
|
ET.SubElement(root, 'link', { 'project': 'openSUSE:Factory:Rings:1-MinimalX' })
|
||||||
|
f = ET.SubElement(root, 'build')
|
||||||
|
# this one stays
|
||||||
|
ET.SubElement(f, 'disable', { 'repository': 'bootstrap_copy' })
|
||||||
|
# this one is the global toggle
|
||||||
|
ET.SubElement(f, 'disable')
|
||||||
|
f = ET.SubElement(root, 'publish')
|
||||||
|
ET.SubElement(f, 'disable')
|
||||||
|
f = ET.SubElement(root, 'debuginfo')
|
||||||
|
ET.SubElement(f, 'enable')
|
||||||
|
|
||||||
|
r = ET.SubElement(root, 'repository', { 'name': 'bootstrap_copy' })
|
||||||
|
ET.SubElement(r, 'path', { 'project': 'openSUSE:Factory', 'repository': 'ports' })
|
||||||
|
a = ET.SubElement(r, 'arch')
|
||||||
|
a.text = 'i586'
|
||||||
|
a = ET.SubElement(r, 'arch')
|
||||||
|
a.text = 'x86_64'
|
||||||
|
|
||||||
|
r = ET.SubElement(root, 'repository', { 'name': 'standard', 'linkedbuild': 'all', 'rebuild': 'direct' })
|
||||||
|
ET.SubElement(r, 'path', { 'project': prj, 'repository': 'bootstrap_copy' })
|
||||||
|
a = ET.SubElement(r, 'arch')
|
||||||
|
a.text = 'i586'
|
||||||
|
a = ET.SubElement(r, 'arch')
|
||||||
|
a.text = 'x86_64'
|
||||||
|
|
||||||
|
r = ET.SubElement(root, 'repository', { 'name': 'images', 'linkedbuild': 'all', 'rebuild': 'direct' })
|
||||||
|
ET.SubElement(r, 'path', { 'project': prj, 'repository': 'standard' })
|
||||||
|
a = ET.SubElement(r, 'arch')
|
||||||
|
a.text = 'x86_64'
|
||||||
|
|
||||||
|
return ET.tostring(root)
|
||||||
|
|
||||||
|
def freeze_prjlinks(self):
|
||||||
|
sources = dict()
|
||||||
|
flink = ET.Element('frozenlinks')
|
||||||
|
|
||||||
|
for lprj in self.projectlinks:
|
||||||
|
fl = ET.SubElement(flink, 'frozenlink', { 'project': lprj } )
|
||||||
|
sources = self.receive_sources(lprj, sources, fl)
|
||||||
|
|
||||||
|
url = makeurl(self.apiurl, ['source', self.prj, '_project', '_frozenlinks'], { 'meta': '1' } )
|
||||||
|
http_PUT(url, data=ET.tostring(flink))
|
||||||
|
|
||||||
|
def receive_sources(self, prj, sources, flink):
|
||||||
|
url = makeurl(self.apiurl, ['source', prj], { 'view': 'info', 'nofilename': '1' } )
|
||||||
|
f = http_GET(url)
|
||||||
|
root = ET.parse(f).getroot()
|
||||||
|
|
||||||
|
for si in root.findall('sourceinfo'):
|
||||||
|
package = self.check_one_source(flink, si)
|
||||||
|
sources[package] = 1
|
||||||
|
return sources
|
||||||
|
|
||||||
|
def check_one_source(self, flink, si):
|
||||||
|
package = si.get('package')
|
||||||
|
# we have to check if its a link within the staging project
|
||||||
|
# in this case we need to keep the link as is, and not freezing
|
||||||
|
# the target. Otherwise putting kernel-source into staging prj
|
||||||
|
# won't get updated kernel-default (and many other cases)
|
||||||
|
for linked in si.findall('linked'):
|
||||||
|
if linked.get('project') in self.projectlinks:
|
||||||
|
# take the unexpanded md5 from Factory link
|
||||||
|
url = makeurl(self.apiurl, ['source', 'openSUSE:Factory', package], { 'view': 'info', 'nofilename': '1' })
|
||||||
|
#print package, linked.get('package'), linked.get('project')
|
||||||
|
f = http_GET(url)
|
||||||
|
proot = ET.parse(f).getroot()
|
||||||
|
ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': proot.get('lsrcmd5'), 'vrev': si.get('vrev') })
|
||||||
|
return package
|
||||||
|
ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': si.get('srcmd5'), 'vrev': si.get('vrev') })
|
||||||
|
return package
|
||||||
|
|
@ -9,6 +9,9 @@ import sys
|
|||||||
import contextlib
|
import contextlib
|
||||||
import unittest
|
import unittest
|
||||||
import httpretty
|
import httpretty
|
||||||
|
import difflib
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
# mock is part of python3.3
|
# mock is part of python3.3
|
||||||
try:
|
try:
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
@ -30,6 +33,15 @@ class TestApiCalls(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
return os.path.join(os.getcwd(), 'tests/fixtures')
|
return os.path.join(os.getcwd(), 'tests/fixtures')
|
||||||
|
|
||||||
|
def _get_fixture_path(self, filename):
|
||||||
|
return os.path.join(self._get_fixtures_dir(), filename)
|
||||||
|
|
||||||
|
def _get_fixture_content(self, filename):
|
||||||
|
response = open(self._get_fixture_path(filename), 'r')
|
||||||
|
content = response.read()
|
||||||
|
response.close()
|
||||||
|
return content
|
||||||
|
|
||||||
def _register_pretty_url_get(self, url, filename):
|
def _register_pretty_url_get(self, url, filename):
|
||||||
"""
|
"""
|
||||||
Register specified get url with specific filename in fixtures
|
Register specified get url with specific filename in fixtures
|
||||||
@ -37,9 +49,7 @@ class TestApiCalls(unittest.TestCase):
|
|||||||
:param filename: name of the fixtures file
|
:param filename: name of the fixtures file
|
||||||
"""
|
"""
|
||||||
|
|
||||||
response = open(os.path.join(self._get_fixtures_dir(), filename), 'r')
|
content = self._get_fixture_content(filename)
|
||||||
content = response.read()
|
|
||||||
response.close()
|
|
||||||
|
|
||||||
httpretty.register_uri(httpretty.GET,
|
httpretty.register_uri(httpretty.GET,
|
||||||
url,
|
url,
|
||||||
@ -274,6 +284,22 @@ class TestApiCalls(unittest.TestCase):
|
|||||||
data = f.read().strip()
|
data = f.read().strip()
|
||||||
self.assertEqual(sys.stdout.getvalue().strip(), data)
|
self.assertEqual(sys.stdout.getvalue().strip(), data)
|
||||||
|
|
||||||
|
def test_bootstrap_copy(self):
|
||||||
|
import osclib.freeze_command
|
||||||
|
fc = osclib.freeze_command.FreezeCommand('http://localhost')
|
||||||
|
|
||||||
|
fp = self._get_fixture_path('staging-meta-for-bootstrap-copy.xml')
|
||||||
|
fixture = subprocess.check_output('/usr/bin/xmllint --format %s' % fp, shell=True)
|
||||||
|
|
||||||
|
f = tempfile.NamedTemporaryFile(delete=False)
|
||||||
|
f.write(fc.prj_meta_for_bootstrap_copy('openSUSE:Factory:Staging:A'))
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
output = subprocess.check_output('/usr/bin/xmllint --format %s' % f.name, shell=True)
|
||||||
|
|
||||||
|
for line in difflib.unified_diff(fixture.split("\n"), output.split("\n")):
|
||||||
|
print line
|
||||||
|
self.assertEqual(output, fixture)
|
||||||
|
|
||||||
# Here place all mockable functions
|
# Here place all mockable functions
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
29
tests/fixtures/staging-meta-for-bootstrap-copy.xml
vendored
Normal file
29
tests/fixtures/staging-meta-for-bootstrap-copy.xml
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<project name="openSUSE:Factory:Staging:A">
|
||||||
|
<title></title>
|
||||||
|
<description></description>
|
||||||
|
<link project="openSUSE:Factory:Rings:1-MinimalX"/>
|
||||||
|
<build>
|
||||||
|
<disable repository="bootstrap_copy"/>
|
||||||
|
<disable/>
|
||||||
|
</build>
|
||||||
|
<publish>
|
||||||
|
<disable/>
|
||||||
|
</publish>
|
||||||
|
<debuginfo>
|
||||||
|
<enable/>
|
||||||
|
</debuginfo>
|
||||||
|
<repository name="bootstrap_copy">
|
||||||
|
<path project="openSUSE:Factory" repository="ports"/>
|
||||||
|
<arch>i586</arch>
|
||||||
|
<arch>x86_64</arch>
|
||||||
|
</repository>
|
||||||
|
<repository linkedbuild="all" name="standard" rebuild="direct">
|
||||||
|
<path project="openSUSE:Factory:Staging:A" repository="bootstrap_copy"/>
|
||||||
|
<arch>i586</arch>
|
||||||
|
<arch>x86_64</arch>
|
||||||
|
</repository>
|
||||||
|
<repository linkedbuild="all" name="images" rebuild="direct">
|
||||||
|
<path project="openSUSE:Factory:Staging:A" repository="standard"/>
|
||||||
|
<arch>x86_64</arch>
|
||||||
|
</repository>
|
||||||
|
</project>
|
Loading…
x
Reference in New Issue
Block a user