Add support of labels parameter for dockerng

This commit is contained in:
Nicolas Delaby 2015-10-02 15:39:57 +02:00
parent e47d849af6
commit edf625c8b4
4 changed files with 235 additions and 0 deletions

View File

@ -417,6 +417,9 @@ VALID_CREATE_OPTS = {
'cpuset': { 'cpuset': {
'path': 'Config:Cpuset', 'path': 'Config:Cpuset',
}, },
'labels': {
'path': 'Config:Labels',
},
} }
VALID_RUNTIME_OPTS = { VALID_RUNTIME_OPTS = {
@ -1110,6 +1113,13 @@ def _validate_input(action,
for x in kwargs[key]]): for x in kwargs[key]]):
raise SaltInvocationError(key + ' must be a list of strings') raise SaltInvocationError(key + ' must be a list of strings')
def _valid_dictlist(key): # pylint: disable=unused-variable
'''
Ensure the passed value is a list of dictionaries.
'''
if not salt.utils.is_dictlist(kwargs[key]):
raise SaltInvocationError(key + ' must be a list of dictionaries.')
# Custom validation functions for container creation options # Custom validation functions for container creation options
def _valid_command(): # pylint: disable=unused-variable def _valid_command(): # pylint: disable=unused-variable
''' '''
@ -1644,6 +1654,32 @@ def _validate_input(action,
'pid_mode can only be \'host\', if set' 'pid_mode can only be \'host\', if set'
) )
def _valid_labels(): # pylint: disable=unused-variable
'''
Must be a dict or a list of strings
'''
if kwargs.get('labels') is None:
return
try:
_valid_stringlist('labels')
except SaltInvocationError:
try:
_valid_dictlist('labels')
except SaltInvocationError:
try:
_valid_dict('labels')
except SaltInvocationError:
raise SaltInvocationError(
'labels can only be a list of strings/dict'
' or a dict containing strings')
else:
new_labels = {}
for k, v in six.iteritems(kwargs['labels']):
new_labels[str(k)] = str(v)
kwargs['labels'] = new_labels
else:
kwargs['labels'] = salt.utils.repack_dictlist(kwargs['labels'])
# And now, the actual logic to perform the validation # And now, the actual logic to perform the validation
if action == 'create': if action == 'create':
valid_opts = VALID_CREATE_OPTS valid_opts = VALID_CREATE_OPTS
@ -2640,6 +2676,12 @@ def create(image,
This is only used if Salt needs to pull the requested image. This is only used if Salt needs to pull the requested image.
labels
Add Metadata to the container. Can be a list of strings/dictionaries
or a dictionary of strings (keys and values).
Example: ``labels=LABEL1,LABEL2``,
``labels="{'LABEL1': 'value1', 'LABEL2': 'value2'}"``
**RETURN DATA** **RETURN DATA**

View File

@ -1349,6 +1349,37 @@ def running(name,
This option requires Docker 1.5.0 or newer. This option requires Docker 1.5.0 or newer.
labels
Add Metadata to the container. Can be a list of strings/dictionaries
or a dictionary of strings (keys and values).
.. code-block:: yaml
foo:
dockerng.running:
- image: bar/baz:latest
- labels:
- LABEL1
- LABEL2
.. code-block:: yaml
foo:
dockerng.running:
- image: bar/baz:latest
- labels:
KEY1: VALUE1
KEY2: VALUE2
.. code-block:: yaml
foo:
dockerng.running:
- image: bar/baz:latest
- labels:
- KEY1: VALUE1
- KEY2: VALUE2
start : True start : True
Set to ``False`` to suppress starting of the container if it exists, Set to ``False`` to suppress starting of the container if it exists,
matches the desired configuration, but is not running. This is useful matches the desired configuration, but is not running. This is useful

View File

@ -21,6 +21,7 @@ ensure_in_syspath('../../')
# Import Salt Libs # Import Salt Libs
from salt.modules import dockerng as dockerng_mod from salt.modules import dockerng as dockerng_mod
from salt.exceptions import SaltInvocationError
dockerng_mod.__context__ = {'docker.docker_version': ''} dockerng_mod.__context__ = {'docker.docker_version': ''}
dockerng_mod.__salt__ = {} dockerng_mod.__salt__ = {}
@ -139,6 +140,141 @@ class DockerngTestCase(TestCase):
image='image', image='image',
name='ctn') name='ctn')
@skipIf(_docker_py_version() < (1, 4, 0),
'docker module must be installed to run this test or is too old. >=1.4.0')
@patch.object(dockerng_mod, 'images', MagicMock())
@patch.object(dockerng_mod, 'inspect_image')
@patch.object(dockerng_mod, 'version', Mock(return_value={'ApiVersion': '1.19'}))
def test_create_with_labels_dict(self, *args):
'''
Create container with labels dictionary.
'''
__salt__ = {
'config.get': Mock(),
'mine.send': Mock(),
}
host_config = {}
client = Mock()
client.api_version = '1.19'
client.create_host_config.return_value = host_config
client.create_container.return_value = {}
with patch.dict(dockerng_mod.__dict__,
{'__salt__': __salt__}):
with patch.dict(dockerng_mod.__context__,
{'docker.client': client}):
dockerng_mod.create(
'image',
name='ctn',
labels={'KEY': 'VALUE'},
validate_input=True,
)
client.create_container.assert_called_once_with(
labels={'KEY': 'VALUE'},
host_config=host_config,
image='image',
name='ctn',
)
@skipIf(_docker_py_version() < (1, 4, 0),
'docker module must be installed to run this test or is too old. >=1.4.0')
@patch.object(dockerng_mod, 'images', MagicMock())
@patch.object(dockerng_mod, 'inspect_image')
@patch.object(dockerng_mod, 'version', Mock(return_value={'ApiVersion': '1.19'}))
def test_create_with_labels_list(self, *args):
'''
Create container with labels list.
'''
__salt__ = {
'config.get': Mock(),
'mine.send': Mock(),
}
host_config = {}
client = Mock()
client.api_version = '1.19'
client.create_host_config.return_value = host_config
client.create_container.return_value = {}
with patch.dict(dockerng_mod.__dict__,
{'__salt__': __salt__}):
with patch.dict(dockerng_mod.__context__,
{'docker.client': client}):
dockerng_mod.create(
'image',
name='ctn',
labels=['KEY1', 'KEY2'],
validate_input=True,
)
client.create_container.assert_called_once_with(
labels=['KEY1', 'KEY2'],
host_config=host_config,
image='image',
name='ctn',
)
@skipIf(_docker_py_version() < (1, 4, 0),
'docker module must be installed to run this test or is too old. >=1.4.0')
@patch.object(dockerng_mod, 'images', MagicMock())
@patch.object(dockerng_mod, 'inspect_image')
@patch.object(dockerng_mod, 'version', Mock(return_value={'ApiVersion': '1.19'}))
def test_create_with_labels_error(self, *args):
'''
Create container with invalid labels.
'''
__salt__ = {
'config.get': Mock(),
'mine.send': Mock(),
}
host_config = {}
client = Mock()
client.api_version = '1.19'
client.create_host_config.return_value = host_config
client.create_container.return_value = {}
with patch.dict(dockerng_mod.__dict__,
{'__salt__': __salt__}):
with patch.dict(dockerng_mod.__context__,
{'docker.client': client}):
self.assertRaises(SaltInvocationError,
dockerng_mod.create,
'image',
name='ctn',
labels=22,
validate_input=True,
)
@skipIf(_docker_py_version() < (1, 4, 0),
'docker module must be installed to run this test or is too old. >=1.4.0')
@patch.object(dockerng_mod, 'images', MagicMock())
@patch.object(dockerng_mod, 'inspect_image')
@patch.object(dockerng_mod, 'version', Mock(return_value={'ApiVersion': '1.19'}))
def test_create_with_labels_dictlist(self, *args):
'''
Create container with labels dictlist.
'''
__salt__ = {
'config.get': Mock(),
'mine.send': Mock(),
}
host_config = {}
client = Mock()
client.api_version = '1.19'
client.create_host_config.return_value = host_config
client.create_container.return_value = {}
with patch.dict(dockerng_mod.__dict__,
{'__salt__': __salt__}):
with patch.dict(dockerng_mod.__context__,
{'docker.client': client}):
dockerng_mod.create(
'image',
name='ctn',
labels=[{'KEY1': 'VALUE1'}, {'KEY2': 'VALUE2'}],
validate_input=True,
)
client.create_container.assert_called_once_with(
labels={'KEY1': 'VALUE1', 'KEY2': 'VALUE2'},
host_config=host_config,
image='image',
name='ctn',
)
if __name__ == '__main__': if __name__ == '__main__':
from integration import run_tests from integration import run_tests

View File

@ -434,6 +434,32 @@ class DockerngTestCase(TestCase):
'name': 'cont', 'name': 'cont',
'result': False}) 'result': False})
def test_running_with_labels(self):
'''
Test dockerng.running with labels parameter.
'''
dockerng_create = Mock()
__salt__ = {'dockerng.list_containers': MagicMock(),
'dockerng.list_tags': MagicMock(),
'dockerng.pull': MagicMock(),
'dockerng.state': MagicMock(),
'dockerng.inspect_image': MagicMock(),
'dockerng.create': dockerng_create,
}
with patch.dict(dockerng_state.__dict__,
{'__salt__': __salt__}):
dockerng_state.running(
'cont',
image='image:latest',
labels=['LABEL1', 'LABEL2'],
)
dockerng_create.assert_called_with(
'image:latest',
validate_input=False,
name='cont',
labels=['LABEL1', 'LABEL2'],
client_timeout=60)
if __name__ == '__main__': if __name__ == '__main__':
from integration import run_tests from integration import run_tests