Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix smartos_imgadm doesn't handle orphan images #55137

Merged
merged 3 commits into from
Dec 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions salt/modules/smartos_imgadm.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def _parse_image_meta(image=None, detail=False):

if image and 'Error' in image:
ret = image
elif image and 'manifest' in image:
elif image and 'manifest' in image and 'name' in image['manifest']:
name = image['manifest']['name']
version = image['manifest']['version']
os = image['manifest']['os']
Expand Down Expand Up @@ -97,6 +97,11 @@ def _parse_image_meta(image=None, detail=False):
version=version,
published=published,
)
else:
log.debug("smartos_image - encountered invalid image payload: {}".format(image))
ret = {
'Error': 'This looks like an orphaned image, image payload was invalid.'
}

return ret

Expand All @@ -110,8 +115,7 @@ def _split_docker_uuid(uuid):
if len(uuid) == 2:
tag = uuid[1]
repo = uuid[0]
if len(repo.split('/')) == 2:
return repo, tag
return repo, tag
return None, None


Expand Down
16 changes: 14 additions & 2 deletions salt/states/smartos.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ def _split_docker_uuid(uuid):
if len(uuid) == 2:
tag = uuid[1]
repo = uuid[0]
if len(repo.split('/')) == 2:
return repo, tag
return repo, tag
return None, None


Expand Down Expand Up @@ -810,6 +809,19 @@ def vm_present(name, vmconfig, config=None):
ret['result'] = False
ret['comment'] = 'image {0} not installed'.format(vmconfig['image_uuid'])

# prepare disk.*.image_uuid
for disk in vmconfig['disks'] if 'disks' in vmconfig else []:
if 'image_uuid' in disk and disk['image_uuid'] not in __salt__['imgadm.list']():
if config['auto_import']:
if not __opts__['test']:
res = __salt__['imgadm.import'](disk['image_uuid'])
if disk['image_uuid'] not in res:
ret['result'] = False
ret['comment'] = 'failed to import image {0}'.format(disk['image_uuid'])
else:
ret['result'] = False
ret['comment'] = 'image {0} not installed'.format(disk['image_uuid'])

# docker json-array handling
if 'internal_metadata' in vmconfig:
for var in vmconfig_docker_array:
Expand Down
278 changes: 278 additions & 0 deletions tests/unit/modules/test_smartos_imgadm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: Jorge Schrauwen <info@blackdot.be>
'''

# Import python libs
from __future__ import absolute_import, print_function, unicode_literals

# Import Salt Libs
import salt.modules.smartos_imgadm as imgadm
from salt.modules.smartos_imgadm import _parse_image_meta

# Import Salt Testing Libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import TestCase, skipIf
from tests.support.mock import NO_MOCK, NO_MOCK_REASON

image_orphan = {
"manifest": {
"uuid": "07f360fd-12d5-e624-a279-eb8a15b630f6"
},
"zpool": "zones",
"cloneNames": [],
"clones": 0
}
image_native = {
"manifest": {
"v": 2,
"uuid": "9d91e334-3bcf-11e8-bb0b-e7b49eb01e38",
"owner": "00000000-0000-0000-0000-000000000000",
"name": "pkgbuild",
"version": "18.1.0",
"state": "active",
"disabled": False,
"public": True,
"published_at": "2018-04-09T08:25:52Z",
"type": "zone-dataset",
"os": "smartos",
"files": [
{
"sha1": "5efaf95b7f226eb09c7d5e6c3734f8aa654b811d",
"size": 465411979,
"compression": "gzip"
}
],
"description": "A SmartOS image pre-configured for building pkgsrc packages.",
"homepage": "https://docs.joyent.com/images/smartos/pkgbuild",
"urn": "sdc:sdc:pkgbuild:18.1.0",
"requirements": {
"min_platform": {
"7.0": "20141030T081701Z"
},
"networks": [
{
"name": "net0",
"description": "public"
}
]
},
"tags": {
"role": "os",
"group": "pkgbuild"
}
},
"zpool": "zones",
"source": "https://images.joyent.com",
"cloneNames": [
"zones/dda70f61-70fe-65e7-cf70-d878d69442d4"
],
"clones": 1
}
image_lx = {
"manifest": {
"v": 2,
"uuid": "05140a7e-279f-11e6-aedf-47d4f69d2887",
"owner": "00000000-0000-0000-0000-000000000000",
"name": "ubuntu-16.04",
"version": "20160601",
"state": "active",
"disabled": False,
"public": True,
"published_at": "2016-06-01T02:17:41Z",
"type": "lx-dataset",
"os": "linux",
"files": [
{
"sha1": "d342f137c5ccef0702ec479acb63c196cf81b38a",
"size": 134969110,
"compression": "gzip"
}
],
"description": "Container-native Ubuntu 16.04 64-bit image. Built to run on containers with bare metal speed, while offering all the services of a typical unix host.",
"homepage": "https://docs.joyent.com/images/container-native-linux",
"requirements": {
"networks": [
{
"name": "net0",
"description": "public"
}
],
"min_platform": {
"7.0": "20160225T122859Z"
},
"brand": "lx"
},
"tags": {
"role": "os",
"kernel_version": "4.3.0"
}
},
"zpool": "zones",
"source": "https://images.joyent.com",
"cloneNames": [
"zones/e4c1f6b5-4429-e6c2-ae2a-d6aa58bdeebb"
],
"clones": 1
}
image_zvol = {
"manifest": {
"v": 2,
"uuid": "ac99517a-72ac-44c0-90e6-c7ce3d944a0a",
"owner": "00000000-0000-0000-0000-000000000000",
"name": "ubuntu-certified-18.04",
"version": "20180808",
"state": "active",
"disabled": False,
"public": True,
"published_at": "2018-10-11T12:45:24.804Z",
"type": "zvol",
"os": "linux",
"files": [
{
"sha1": "9f7704969507bd97e160a8f42a3631487644e457",
"size": 372276887,
"compression": "gzip"
}
],
"description": "Ubuntu 18.04 LTS (20180808 64-bit). Certified Ubuntu Server Cloud Image from Canonical. For kvm and bhyve.",
"homepage": "https://docs.joyent.com/images/linux/ubuntu-certified",
"requirements": {
"min_platform": {
"7.0": "20150929T232348Z"
},
"networks": [
{
"name": "net0",
"description": "public"
}
],
"ssh_key": True
},
"nic_driver": "virtio",
"disk_driver": "virtio",
"cpu_type": "host",
"image_size": 10240,
"tags": {
"default_user": "ubuntu",
"role": "os"
}
},
"zpool": "zones",
"source": "https://images.joyent.com",
"cloneNames": [],
"clones": 0
}
image_docker = {
"manifest": {
"v": 2,
"uuid": "4a3db8cb-0e94-ae23-588c-ee7934088927",
"owner": "00000000-0000-0000-0000-000000000000",
"name": "docker-layer",
"version": "62487cf6a7f6",
"disabled": False,
"public": True,
"published_at": "2019-03-23T01:32:25.320Z",
"type": "docker",
"os": "linux",
"description": "/bin/sh -c #(nop) CMD [\"/bin/bash\" \"/opt/start.sh\" \"-bash\"]",
"tags": {
"docker:repo": "busybox42/zimbra-docker-centos",
"docker:id": "sha256:62487cf6a7f698af4edc20707e14b1b3bba13b98bea3375f05af04859a30b222",
"docker:architecture": "amd64",
"docker:tag:latest": True,
"docker:config": {
"Cmd": [
"/bin/bash",
"/opt/start.sh",
"-bash"
],
"Entrypoint": None,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"WorkingDir": ""
}
},
"origin": "2f0c529b-7bab-28d1-ff34-bdc9281b7a4b"
},
"zpool": "zones",
"source": "https://docker.io",
"cloneNames": [],
"clones": 0
}


@skipIf(NO_MOCK, NO_MOCK_REASON)
class ImgadmTestCase(TestCase, LoaderModuleMockMixin):
'''
TestCase for salt.modules.smartos_imgadm module
'''

def setup_loader_modules(self):
return {imgadm: {}}

def test_parse_image_meta_orphan(self):
'''
Test the internal _parse_image_meta methode
Feed it an 'orphan' image as we get it from from imgadm list -j
'''
ret = {'Error': 'This looks like an orphaned image, image payload was invalid.'}
self.assertEqual(_parse_image_meta(image_orphan, True), ret)

def test_parse_image_meta_native(self):
'''
Test the internal _parse_image_meta methode
Feed it an 'native' image as we get it from from imgadm list -j
'''
ret = {'description': 'A SmartOS image pre-configured for building pkgsrc packages.',
'name': 'pkgbuild',
'os': 'smartos',
'published': '2018-04-09T08:25:52Z',
'source': 'https://images.joyent.com',
'version': '18.1.0'}
self.assertEqual(_parse_image_meta(image_native, True), ret)

def test_parse_image_meta_lx(self):
'''
Test the internal _parse_image_meta methode
Feed it an 'lx' image as we get it from from imgadm list -j
'''
ret = {'description': 'Container-native Ubuntu 16.04 64-bit image. Built to run on '
'containers with bare metal speed, while offering all the '
'services of a typical unix host.',
'name': 'ubuntu-16.04',
'os': 'linux',
'published': '2016-06-01T02:17:41Z',
'source': 'https://images.joyent.com',
'version': '20160601'}
self.assertEqual(_parse_image_meta(image_lx, True), ret)

def test_parse_image_meta_zvol(self):
'''
Test the internal _parse_image_meta methode
Feed it an 'zvol' image as we get it from from imgadm list -j
'''
ret = {'description': 'Ubuntu 18.04 LTS (20180808 64-bit). Certified Ubuntu Server '
'Cloud Image from Canonical. For kvm and bhyve.',
'name': 'ubuntu-certified-18.04',
'os': 'linux',
'published': '2018-10-11T12:45:24.804Z',
'source': 'https://images.joyent.com',
'version': '20180808'}
self.assertEqual(_parse_image_meta(image_zvol, True), ret)

def test_parse_image_meta_docker(self):
'''
Test the internal _parse_image_meta methode
Feed it an 'docker' image as we get it from from imgadm list -j
'''
ret = {'description': 'Docker image imported from '
'busybox42/zimbra-docker-centos:latest on '
'2019-03-23T01:32:25.320Z.',
'name': 'busybox42/zimbra-docker-centos:latest',
'os': 'linux',
'published': '2019-03-23T01:32:25.320Z',
'source': 'https://docker.io',
'version': '62487cf6a7f6'}
self.assertEqual(_parse_image_meta(image_docker, True), ret)