Support openstack stack export

Heat supports exporting data of stack preparing
for abandon stack. This change supports
'openstack stack export' in client.

Change-Id: I5d3778f307d10174dbb738548282f7495bd9c825
This commit is contained in:
huangtianhua 2017-02-13 18:15:24 +08:00
parent 28cf99603a
commit dedc3ac0af
4 changed files with 88 additions and 0 deletions

View File

@ -874,6 +874,50 @@ class AbandonStack(format_utils.JsonFormat):
return columns, data
class ExportStack(format_utils.JsonFormat):
"""Export stack data json."""
log = logging.getLogger(__name__ + '.ExportStack')
def get_parser(self, prog_name):
parser = super(ExportStack, self).get_parser(prog_name)
parser.add_argument(
'stack',
metavar='<stack>',
help=_('Name or ID of stack to export')
)
parser.add_argument(
'--output-file',
metavar='<output-file>',
help=_('File to output export data')
)
return parser
def take_action(self, parsed_args):
self.log.debug('take_action(%s)', parsed_args)
client = self.app.client_manager.orchestration
try:
data_info = client.stacks.export(stack_id=parsed_args.stack)
except heat_exc.HTTPNotFound:
msg = _('Stack not found: %s') % parsed_args.stack
raise exc.CommandError(msg)
if parsed_args.output_file is not None:
try:
with open(parsed_args.output_file, 'w') as f:
f.write(jsonutils.dumps(data_info, indent=2))
return [], None
except IOError as e:
raise exc.CommandError(str(e))
data = list(six.itervalues(data_info))
columns = list(six.iterkeys(data_info))
return columns, data
class OutputShowStack(command.ShowOne):
"""Show stack output."""

View File

@ -777,6 +777,42 @@ class TestStackAdopt(TestStack):
self.assertRaises(exc.CommandError, self.cmd.take_action, parsed_args)
class TestStackExport(TestStack):
columns = ['stack_name', 'stack_status', 'id']
data = ['my_stack', 'ABANDONED', '1234']
response = dict(zip(columns, data))
def setUp(self):
super(TestStackExport, self).setUp()
self.cmd = stack.ExportStack(self.app, None)
self.stack_client.export.return_value = self.response
def test_stack_export(self):
arglist = ['my_stack']
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
for column in self.columns:
self.assertIn(column, columns)
for datum in self.data:
self.assertIn(datum, data)
@mock.patch('heatclient.osc.v1.stack.open', create=True)
def test_stack_export_output_file(self, mock_open):
arglist = ['my_stack', '--output-file', 'file.json']
mock_open.return_value = mock.MagicMock(spec=io.IOBase)
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
mock_open.assert_called_once_with('file.json', 'w')
self.assertEqual([], columns)
self.assertIsNone(data)
class TestStackAbandon(TestStack):
columns = ['stack_name', 'stack_status', 'id']

View File

@ -208,6 +208,13 @@ class StackManager(StackChildManager):
body = utils.get_response_body(resp)
return body
def export(self, stack_id):
"""Export data of a stack."""
stack_identifier = self._resolve_stack_id(stack_id)
resp = self.client.get('/stacks/%s/export' % stack_identifier)
body = utils.get_response_body(resp)
return body
def snapshot(self, stack_id, name=None):
"""Snapshot a stack."""
stack_identifier = self._resolve_stack_id(stack_id)

View File

@ -50,6 +50,7 @@ openstack.orchestration.v1 =
software_deployment_output_show = heatclient.osc.v1.software_deployment:ShowOutputDeployment
software_deployment_show = heatclient.osc.v1.software_deployment:ShowDeployment
stack_abandon = heatclient.osc.v1.stack:AbandonStack
stack_export = heatclient.osc.v1.stack:ExportStack
stack_adopt = heatclient.osc.v1.stack:AdoptStack
stack_cancel = heatclient.osc.v1.stack:CancelStack
stack_check = heatclient.osc.v1.stack:CheckStack