Support image uploads in 'info' CLI command

Change the 'info' command output to include image upload data.
For each image, we'll now output each build and the uploads for the build.

Change-Id: Ib25ce30d30ed718b2b6083c2127fdb214c3691f4
This commit is contained in:
David Shrewsbury 2020-03-12 15:32:47 -04:00
parent c0d7c96f76
commit 394d549c07
4 changed files with 80 additions and 14 deletions

View File

@ -316,16 +316,19 @@ class NodePoolCmd(NodepoolApp):
def info(self):
provider_name = self.args.provider
provider_builds = self.zk.getProviderBuilds(provider_name)
provider_uploads = self.zk.getProviderUploads(provider_name)
provider_nodes = self.zk.getProviderNodes(provider_name)
print("ZooKeeper data for provider %s\n" % provider_name)
print("Image builds:")
t = PrettyTable(['Image Name', 'Build IDs'])
print("Image data:")
t = PrettyTable(['Image Name', 'Build ID', 'Upload IDs'])
t.align = 'l'
for image, builds in provider_builds.items():
t.add_row([image, ','.join(builds)])
for image in sorted(provider_uploads):
for build in sorted(provider_uploads[image]):
uploads = provider_uploads[image][build]
upload_ids = sorted([u.id for u in uploads])
t.add_row([image, build, ','.join(upload_ids)])
print(t)
print("\nNodes:")

View File

@ -51,7 +51,7 @@ class TestNodepoolCMD(tests.DBTestCase):
if col_count:
self.assertEquals(len(row), col_count)
log.debug(row)
if row[col] == val:
if col < len(row) and row[col] == val:
rows_with_val += 1
self.assertEquals(rows_with_val, count)
break
@ -320,6 +320,7 @@ class TestNodepoolCMD(tests.DBTestCase):
self.useBuilder(configfile)
pool.start()
p1_image = self.waitForImage('fake-provider', 'fake-image')
p2_image = self.waitForImage('fake-provider2', 'fake-image')
p1_nodes = self.waitForNodes('fake-label')
p2_nodes = self.waitForNodes('fake-label2')
@ -328,33 +329,47 @@ class TestNodepoolCMD(tests.DBTestCase):
# recreate the data.
self.replace_config(configfile, 'info_cmd_two_provider_remove.yaml')
IMAGE_NAME_COL = 0
BUILD_ID_COL = 1
UPLOAD_ID_COL = 2
NODE_ID_COL = 0
# Verify that the second provider image is listed
self.assert_listed(
configfile,
['info', 'fake-provider2'],
0, 'fake-image', 1)
# Verify that the second provider node is listed.
IMAGE_NAME_COL, 'fake-image', 1)
self.assert_listed(
configfile,
['info', 'fake-provider2'],
0, p2_nodes[0].id, 1)
BUILD_ID_COL, p2_image.build_id, 1)
self.assert_listed(
configfile,
['info', 'fake-provider2'],
UPLOAD_ID_COL, p2_image.id, 1)
# Verify that the second provider node is listed in the second table.
self.assert_listed(
configfile,
['info', 'fake-provider2'],
NODE_ID_COL, p2_nodes[0].id, 1)
# Erase the data for the second provider
self.patch_argv(
"-c", configfile, 'erase', 'fake-provider2', '--force')
nodepoolcmd.main()
# Verify that no build or node for the second provider is listed
# after the previous erase
# Verify that no image or node for the second provider is listed
# after the previous erase. With no build data, the image name should
# not even show up.
self.assert_listed(
configfile,
['info', 'fake-provider2'],
0, 'fake-image', 0)
IMAGE_NAME_COL, 'fake-image', 0)
self.assert_listed(
configfile,
['info', 'fake-provider2'],
0, p2_nodes[0].id, 0)
NODE_ID_COL, p2_nodes[0].id, 0)
# Verify that we did not affect the first provider
image = self.waitForImage('fake-provider', 'fake-image')

View File

@ -373,6 +373,25 @@ class TestZooKeeper(tests.DBTestCase):
d = self.zk.getMostRecentImageUpload(image, provider, zk.READY)
self.assertEqual(upload2.state_time, d.state_time)
def test_getProviderUploads(self):
image = "ubuntu-trusty"
provider = "rax"
build = zk.ImageBuild()
build.state = zk.READY
bnum = self.zk.storeBuild(image, build)
upload = zk.ImageUpload()
upload.state = zk.READY
upnum = self.zk.storeImageUpload(image, bnum, provider, upload)
d = self.zk.getProviderUploads(provider)
self.assertIn(image, d)
self.assertIn(bnum, d[image])
self.assertEqual(1, len(d[image][bnum]))
self.assertIsInstance(d[image][bnum][0], zk.ImageUpload)
self.assertEqual(upnum, d[image][bnum][0].id)
def test_getBuilds_any(self):
image = "ubuntu-trusty"
path = self.zk._imageBuildsPath(image)

View File

@ -2184,6 +2184,35 @@ class ZooKeeper(object):
provider_builds[image].append(build)
return provider_builds
def getProviderUploads(self, provider_name):
'''
Get all uploads for a provider for each image.
:param str provider_name: The provider name.
:returns: A dict, keyed by image name and build ID, of a list of
ImageUpload objects.
'''
provider_uploads = {}
image_names = self.getImageNames()
for image in image_names:
build_numbers = self.getBuildNumbers(image)
for build in build_numbers:
# If this build is not valid for this provider, move along.
if provider_name not in self.getBuildProviders(image, build):
continue
# We've determined that we at least have a build for this
# provider so init with an empty upload list.
if image not in provider_uploads:
provider_uploads[image] = {}
provider_uploads[image][build] = []
# Add any uploads we might have for this provider.
uploads = self.getUploads(image, build, provider_name)
for upload in uploads:
provider_uploads[image][build].append(upload)
return provider_uploads
def getProviderNodes(self, provider_name):
'''
Get all nodes for a provider.