mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Provide states for managing docker volumes
This commit is contained in:
parent
dff6fa1fb2
commit
cb9cb463b0
3 changed files with 204 additions and 4 deletions
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue