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

SmartOS imgadm module and state did not like docker images #48046

Merged
merged 2 commits into from Jun 12, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -25,51 +25,115 @@
__virtualname__ = 'imgadm'


def _exit_status(retcode):
def __virtual__():
'''
Provides imgadm only on SmartOS
'''
if salt.utils.platform.is_smartos_globalzone() and \
salt.utils.path.which('imgadm'):
return __virtualname__
return (
False,
'{0} module can only be loaded on SmartOS compute nodes'.format(
__virtualname__
)
)


def _exit_status(retcode, stderr=None):
'''
Translate exit status of imgadm
'''
ret = {0: 'Successful completion.',
1: 'An error occurred.',
1: 'An error occurred.' if not stderr else stderr,
2: 'Usage error.',
3: 'Image not installed.'}[retcode]
return ret


def _parse_image_meta(image=None, detail=False):
if not image:
return {}

if detail:
return {
'name': image['manifest']['name'],
'version': image['manifest']['version'],
'os': image['manifest']['os'],
'description': image['manifest']['description'],
'published': image['manifest']['published_at'],
'source': image['source']
}
else:
return '{name}@{version} [{date}]'.format(
name=image['manifest']['name'],
version=image['manifest']['version'],
date=image['manifest']['published_at'],
ret = None

if image and 'Error' in image:
ret = image
elif image:
name = image['manifest']['name']
version = image['manifest']['version']
os = image['manifest']['os']
description = image['manifest']['description']
published = image['manifest']['published_at']
source = image['source']
if image['manifest']['name'] == 'docker-layer':
# NOTE: skip docker-layer unless it has a docker:repo and docker:tag
name = None
docker_repo = None
docker_tag = None
for tag in image['manifest']['tags']:
if tag.startswith('docker:tag:') and image['manifest']['tags'][tag]:
docker_tag = tag.split(':')[-1]
elif tag == 'docker:repo':
docker_repo = image['manifest']['tags'][tag]

if docker_repo and docker_tag:
name = '{}:{}'.format(docker_repo, docker_tag)
description = 'Docker image imported from {repo}:{tag} on {date}.'.format(
repo=docker_repo,
tag=docker_tag,
date=published,
)

if name and detail:
ret = {
'name': name,
'version': version,
'os': os,
'description': description,
'published': published,
'source': source,
}
elif name:
ret = '{name}@{version} [{published}]'.format(
name=name,
version=version,
published=published,
)

return ret


def __virtual__():
def _split_docker_uuid(uuid):
'''
Provides imgadm only on SmartOS
Split a smartos docker uuid into repo and tag
'''
if salt.utils.platform.is_smartos_globalzone() and \
salt.utils.path.which('imgadm'):
return __virtualname__
return (
False,
'{0} module can only be loaded on SmartOS compute nodes'.format(
__virtualname__
)
)
if uuid:
uuid = uuid.split(':')
if len(uuid) == 2:
tag = uuid[1]
repo = uuid[0]
if len(repo.split('/')) == 2:
return repo, tag
return None, None


def _is_uuid(uuid):
'''
Check if uuid is a valid smartos uuid
Example: e69a0918-055d-11e5-8912-e3ceb6df4cf8
'''
if uuid and list((len(x) for x in uuid.split('-'))) == [8, 4, 4, 4, 12]:
return True
return False


def _is_docker_uuid(uuid):
'''
Check if uuid is a valid smartos docker uuid
Example plexinc/pms-docker:plexpass
'''
repo, tag = _split_docker_uuid(uuid)
return not (not repo and not tag)


def version():
@@ -89,6 +153,22 @@ def version():
return ret[-1]


def docker_to_uuid(uuid):
'''
Get the image uuid from an imported docker image
.. versionadded:: Fluorine
'''
if _is_uuid(uuid):
return uuid
if _is_docker_uuid(uuid):
images = list_installed(verbose=True)
for image_uuid in images:
if images[image_uuid]['name'] == uuid:
return image_uuid
return None


def update_installed(uuid=''):
'''
Gather info on unknown image(s) (locally installed)
@@ -127,7 +207,6 @@ def avail(search=None, verbose=False):
cmd = 'imgadm avail -j'
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
result = {}
if retcode != 0:
ret['Error'] = _exit_status(retcode)
return ret
@@ -138,9 +217,12 @@ def avail(search=None, verbose=False):
if search and search not in image['manifest']['name']:
# we skip if we are searching but don't have a match
continue
result[image['manifest']['uuid']] = _parse_image_meta(image, verbose)
uuid = image['manifest']['uuid']
data = _parse_image_meta(image, verbose)
if data:
ret[uuid] = data

return result
return ret


def list_installed(verbose=False):
@@ -150,25 +232,33 @@ def list_installed(verbose=False):
verbose : boolean (False)
toggle verbose output
.. versionchanged:: Fluorine
Docker images are now also listed
CLI Example:
.. code-block:: bash
salt '*' imgadm.list [verbose=True]
salt '*' imgadm.list
salt '*' imgadm.list docker=True
salt '*' imgadm.list verbose=True
'''
ret = {}
cmd = 'imgadm list -j'
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
result = {}
if retcode != 0:
ret['Error'] = _exit_status(retcode)
return ret

for image in salt.utils.json.loads(res['stdout']):
result[image['manifest']['uuid']] = _parse_image_meta(image, verbose)
uuid = image['manifest']['uuid']
data = _parse_image_meta(image, verbose)
if data:
ret[uuid] = data

return result
return ret


def show(uuid):
@@ -183,15 +273,21 @@ def show(uuid):
.. code-block:: bash
salt '*' imgadm.show e42f8c84-bbea-11e2-b920-078fab2aab1f
salt '*' imgadm.show plexinc/pms-docker:plexpass
'''
ret = {}
cmd = 'imgadm show {0}'.format(uuid)
res = __salt__['cmd.run_all'](cmd, python_shell=False)
retcode = res['retcode']
if retcode != 0:
ret['Error'] = _exit_status(retcode)
return ret
ret = salt.utils.json.loads(res['stdout'])

if _is_uuid(uuid) or _is_docker_uuid(uuid):
cmd = 'imgadm show {0}'.format(uuid)
res = __salt__['cmd.run_all'](cmd, python_shell=False)
retcode = res['retcode']
if retcode != 0:
ret['Error'] = _exit_status(retcode, res['stderr'])
else:
ret = salt.utils.json.loads(res['stdout'])
else:
ret['Error'] = "{} is not a valid uuid.".format(uuid)

return ret


@@ -207,15 +303,24 @@ def get(uuid):
.. code-block:: bash
salt '*' imgadm.get e42f8c84-bbea-11e2-b920-078fab2aab1f
salt '*' imgadm.get plexinc/pms-docker:plexpass
'''
ret = {}
cmd = 'imgadm get {0}'.format(uuid)
res = __salt__['cmd.run_all'](cmd, python_shell=False)
retcode = res['retcode']
if retcode != 0:
ret['Error'] = _exit_status(retcode)
return ret
ret = salt.utils.json.loads(res['stdout'])

if _is_docker_uuid(uuid):
uuid = docker_to_uuid(uuid)

if _is_uuid(uuid):
cmd = 'imgadm get {0}'.format(uuid)
res = __salt__['cmd.run_all'](cmd, python_shell=False)
retcode = res['retcode']
if retcode != 0:
ret['Error'] = _exit_status(retcode, res['stderr'])
else:
ret = salt.utils.json.loads(res['stdout'])
else:
ret['Error'] = "{} is not a valid uuid.".format(uuid)

return ret


@@ -242,7 +347,9 @@ def import_image(uuid, verbose=False):
ret['Error'] = _exit_status(retcode)
return ret

return {uuid: _parse_image_meta(get(uuid), verbose)}
uuid = docker_to_uuid(uuid)
data = _parse_image_meta(get(uuid), verbose)
return {uuid: data}


def delete(uuid):
@@ -308,4 +415,97 @@ def vacuum(verbose=False):
return list(result.keys())


def sources(verbose=False):
'''
Return a list of available sources

This comment has been minimized.

Copy link
@rallytime

rallytime Jun 11, 2018

Contributor

This new function, as well as all of the the other new functions below, should have a versionadded tag for Fluorine. :)

This comment has been minimized.

Copy link
@sjorge

sjorge Jun 11, 2018

Author Contributor

Done

verbose : boolean (False)
toggle verbose output
.. versionadded:: Fluorine
CLI Example:
.. code-block:: bash
salt '*' imgadm.sources
'''
ret = {}
cmd = 'imgadm sources -j'
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
if retcode != 0:
ret['Error'] = _exit_status(retcode)
return ret

for src in salt.utils.json.loads(res['stdout']):
ret[src['url']] = src
del src['url']

if not verbose:
ret = list(ret)

return ret


def source_delete(source):
'''
Delete a source
source : string
source url to delete
.. versionadded:: Fluorine
CLI Example:
.. code-block:: bash
salt '*' imgadm.source_delete https://updates.joyent.com
'''
ret = {}
cmd = 'imgadm sources -d {0}'.format(source)
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
if retcode != 0:
ret['Error'] = _exit_status(retcode, res['stderr'])
return ret

return sources(False)


def source_add(source, source_type='imgapi'):
'''
Add a new source
source : string
source url to add
source_trype : string (imgapi)
source type, either imgapi or docker
.. versionadded:: Fluorine
CLI Example:
.. code-block:: bash
salt '*' imgadm.source_add https://updates.joyent.com
salt '*' imgadm.source_add https://docker.io docker
'''
ret = {}

# NOTE: there are some undocumented deprecated source types
# so we just warn instead of error on those
if source_type not in ['imgapi', 'docker']:
log.warning('Possible unsupported imgage source type specified!')

cmd = 'imgadm sources -a {0} -t {1}'.format(source, source_type)
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
if retcode != 0:
ret['Error'] = _exit_status(retcode, res['stderr'])
return ret

return sources(False)

# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.