Provide states for managing docker volumes

This commit is contained in:
Nicolas Delaby 2015-12-01 14:09:04 +01:00
parent dff6fa1fb2
commit cb9cb463b0
3 changed files with 204 additions and 4 deletions

View file

@ -1421,10 +1421,14 @@ def _validate_input(kwargs,
raise SaltInvocationError(err)
if not os.path.isabs(host_path):
raise SaltInvocationError(
'Host path {0} in bind {1} is not absolute'
.format(host_path, bind)
)
if os.path.sep in host_path:
raise SaltInvocationError(
'Host path {0} in bind {1} is not absolute'
.format(container_path, bind)
)
log.warn('Host path {0} in bind {1} is not absolute,'
' assuming it is a docker volume.'.format(host_path,
bind))
if not os.path.isabs(container_path):
raise SaltInvocationError(
'Container path {0} in bind {1} is not absolute'

View file

@ -2081,6 +2081,132 @@ def network_absent(name, driver=None):
return ret
def volume_present(name, driver=None, driver_opts=None):
'''
Ensure that a volume is present.
.. versionadded:: 2015.8.4
name
Name of the volume
driver
Type of driver for that volume.
driver_opts
Option for tha volume driver
Usage Examples:
.. code-block:: yaml
volume_foo:
dockerng.volume_present
.. code-block:: yaml
volume_bar:
dockerng.volume_present
- name: bar
- driver: local
- driver_opts:
foo: bar
.. code-block:: yaml
volume_bar:
dockerng.volume_present
- name: bar
- driver: local
- driver_opts:
- foo: bar
- option: value
'''
ret = {'name': name,
'changes': {},
'result': False,
'comment': ''}
if salt.utils.is_dictlist(driver_opts):
driver_opts = salt.utils.repack_dictlist(driver_opts)
volumes = [v for v in __salt__['dockerng.volumes']()['Volumes'] if v['Name'] == name]
if not volumes:
try:
ret['changes']['created'] = __salt__['dockerng.create_volume'](
name, driver=driver, driver_opts=driver_opts)
except Exception as exc:
ret['comment'] = ('Failed to create volume \'{0}\': {1}'
.format(name, exc))
return ret
else:
result = True
ret['result'] = result
return ret
# volume exits, check if driver is the same.
volume = volumes[0]
if volume['Driver'] != driver:
try:
ret['changes']['removed'] = __salt__['dockerng.remove_volume'](name)
except Exception as exc:
ret['comment'] = ('Failed to remove volume \'{0}\': {1}'
.format(name, exc))
return ret
else:
try:
ret['changes']['created'] = __salt__['dockerng.create_volume'](
name, driver=driver, driver_opts=driver_opts)
except Exception as exc:
ret['comment'] = ('Failed to create volume \'{0}\': {1}'
.format(name, exc))
return ret
else:
result = True
ret['result'] = result
return ret
ret['result'] = True
ret['comment'] = 'Volume \'{0}\' already exists.'.format(name)
return ret
def volume_absent(name, driver=None):
'''
Ensure that a volume is absent.
.. versionadded:: 2015.8.4
name
Name of the volume
Usage Examples:
.. code-block:: yaml
volume_foo:
dockerng.volume_absent
'''
ret = {'name': name,
'changes': {},
'result': False,
'comment': ''}
volumes = [v for v in __salt__['dockerng.volumes']()['Volumes'] if v['Name'] == name]
if not volumes:
ret['result'] = True
ret['comment'] = 'Volume \'{0}\' already absent'.format(name)
return ret
try:
ret['changes']['removed'] = __salt__['dockerng.remove_volume'](name)
ret['result'] = True
except Exception as exc:
ret['comment'] = ('Failed to remove volume \'{0}\': {1}'
.format(name, exc))
return ret
def mod_watch(name, sfun=None, **kwargs):
if sfun == 'running':
watch_kwargs = copy.deepcopy(kwargs)

View file

@ -502,6 +502,76 @@ class DockerngTestCase(TestCase):
'removed': 'removed'},
'result': True})
def test_volume_present(self):
'''
Test dockerng.volume_present
'''
dockerng_create_volume = Mock(return_value='created')
__salt__ = {'dockerng.create_volume': dockerng_create_volume,
'dockerng.volumes': Mock(return_value={'Volumes': []}),
}
with patch.dict(dockerng_state.__dict__,
{'__salt__': __salt__}):
ret = dockerng_state.volume_present(
'volume_foo',
)
dockerng_create_volume.assert_called_with('volume_foo',
driver=None,
driver_opts=None)
self.assertEqual(ret, {'name': 'volume_foo',
'comment': '',
'changes': {'created': 'created'},
'result': True})
def test_volume_present_with_another_driver(self):
'''
Test dockerng.volume_present
'''
dockerng_create_volume = Mock(return_value='created')
dockerng_remove_volume = Mock(return_value='removed')
__salt__ = {'dockerng.create_volume': dockerng_create_volume,
'dockerng.remove_volume': dockerng_remove_volume,
'dockerng.volumes': Mock(return_value={
'Volumes': [{'Name': 'volume_foo',
'Driver': 'foo'}]}),
}
with patch.dict(dockerng_state.__dict__,
{'__salt__': __salt__}):
ret = dockerng_state.volume_present(
'volume_foo',
driver='bar'
)
dockerng_remove_volume.assert_called_with('volume_foo')
dockerng_create_volume.assert_called_with('volume_foo',
driver='bar',
driver_opts=None)
self.assertEqual(ret, {'name': 'volume_foo',
'comment': '',
'changes': {'created': 'created',
'removed': 'removed'},
'result': True})
def test_volume_absent(self):
'''
Test dockerng.volume_absent
'''
dockerng_remove_volume = Mock(return_value='removed')
__salt__ = {'dockerng.remove_volume': dockerng_remove_volume,
'dockerng.volumes': Mock(return_value={
'Volumes': [{'Name': 'volume_foo'}]}),
}
with patch.dict(dockerng_state.__dict__,
{'__salt__': __salt__}):
ret = dockerng_state.volume_absent(
'volume_foo',
)
dockerng_remove_volume.assert_called_with('volume_foo')
self.assertEqual(ret, {'name': 'volume_foo',
'comment': '',
'changes': {'removed': 'removed'},
'result': True})
if __name__ == '__main__':
from integration import run_tests
run_tests(DockerngTestCase, needs_daemon=False)