Add environment create/delete to openstack CLI
$ openstack environment create [--join-net-id <NET_ID>] [--join-subnet-id <SUBNET_ID>] [--region <REGION_NAME>] <ENVIRONMENT_NAME> $ openstack environment delete [--abandon] <NAME or ID> [<NAME or ID> ...] Partially implements: blueprint openstack-client-plugin-support Change-Id: Ic8d97d8fb79ba5ce9e489b4083f26ef96f4e43e9
This commit is contained in:
parent
9a86110b6d
commit
844e8c7829
|
@ -12,19 +12,22 @@
|
|||
|
||||
"""Application-catalog v1 stack action implementation"""
|
||||
|
||||
import uuid
|
||||
|
||||
from cliff import lister
|
||||
from cliff import show
|
||||
from muranoclient.common import utils as murano_utils
|
||||
from muranoclient.openstack.common.apiclient import exceptions
|
||||
from openstackclient.common import utils
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ListEnvironments(lister.Lister):
|
||||
"""Lists environments"""
|
||||
|
||||
log = logging.getLogger(__name__ + ".ListEnvironments")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListEnvironments, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
|
@ -37,13 +40,12 @@ class ListEnvironments(lister.Lister):
|
|||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action({0})".format(parsed_args))
|
||||
LOG.debug("take_action({0})".format(parsed_args))
|
||||
client = self.app.client_manager.application_catalog
|
||||
data = client.environments.list(parsed_args.all_tenants)
|
||||
|
||||
columns = ('id', 'name', 'created', 'updated')
|
||||
columns = ('id', 'name', 'status', 'created', 'updated')
|
||||
column_headers = [c.capitalize() for c in columns]
|
||||
|
||||
return (
|
||||
column_headers,
|
||||
list(utils.get_item_properties(
|
||||
|
@ -56,8 +58,6 @@ class ListEnvironments(lister.Lister):
|
|||
class ShowEnvironment(show.ShowOne):
|
||||
"""Display environment details"""
|
||||
|
||||
log = logging.getLogger(__name__ + ".ShowEnvironment")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowEnvironment, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
|
@ -81,7 +81,7 @@ class ShowEnvironment(show.ShowOne):
|
|||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action({0})".format(parsed_args))
|
||||
LOG.debug("take_action({0})".format(parsed_args))
|
||||
client = self.app.client_manager.application_catalog
|
||||
|
||||
environment = utils.find_resource(client.environments,
|
||||
|
@ -100,8 +100,6 @@ class ShowEnvironment(show.ShowOne):
|
|||
class RenameEnvironment(lister.Lister):
|
||||
"""Rename an environment."""
|
||||
|
||||
log = logging.getLogger(__name__ + ".RenameEnvironment")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(RenameEnvironment, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
|
@ -118,14 +116,14 @@ class RenameEnvironment(lister.Lister):
|
|||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action({0})".format(parsed_args))
|
||||
LOG.debug("take_action({0})".format(parsed_args))
|
||||
client = self.app.client_manager.application_catalog
|
||||
environment = utils.find_resource(client.environments,
|
||||
parsed_args.id)
|
||||
data = client.environments.update(environment.id,
|
||||
parsed_args.name)
|
||||
|
||||
columns = ('id', 'name', 'created', 'updated')
|
||||
columns = ('id', 'name', 'status', 'created', 'updated')
|
||||
column_headers = [c.capitalize() for c in columns]
|
||||
|
||||
return (
|
||||
|
@ -140,8 +138,6 @@ class RenameEnvironment(lister.Lister):
|
|||
class EnvironmentSessionCreate(show.ShowOne):
|
||||
"""Creates a new configuration session for environment ID."""
|
||||
|
||||
log = logging.getLogger(__name__ + ".EnvironmentSessionCreate")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(EnvironmentSessionCreate, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
|
@ -153,7 +149,7 @@ class EnvironmentSessionCreate(show.ShowOne):
|
|||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action({0})".format(parsed_args))
|
||||
LOG.debug("take_action({0})".format(parsed_args))
|
||||
client = self.app.client_manager.application_catalog
|
||||
|
||||
environment_id = parsed_args.id
|
||||
|
@ -161,3 +157,128 @@ class EnvironmentSessionCreate(show.ShowOne):
|
|||
sessionid = murano_utils.text_wrap_formatter(session_id)
|
||||
|
||||
return (['id'], [sessionid])
|
||||
|
||||
|
||||
class EnvironmentCreate(lister.Lister):
|
||||
"""Create an environment."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(EnvironmentCreate, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'name',
|
||||
metavar="<ENVIRONMENT_ID>",
|
||||
help="Environment name.",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--region',
|
||||
metavar="<REGION_NAME>",
|
||||
help="Name of the target OpenStack region.",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--join-subnet-id',
|
||||
metavar="<SUBNET_ID>",
|
||||
help="Subnetwork id to join.",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--join-net-id',
|
||||
metavar="<NET_ID>",
|
||||
help="Network id to join.",
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
LOG.debug("take_action({0})".format(parsed_args))
|
||||
client = self.app.client_manager.application_catalog
|
||||
|
||||
body = {"name": parsed_args.name, "region": parsed_args.region}
|
||||
if parsed_args.join_net_id or parsed_args.join_subnet_id:
|
||||
res = {
|
||||
'defaultNetworks': {
|
||||
'environment': {
|
||||
'?': {
|
||||
'id': uuid.uuid4().hex,
|
||||
'type':
|
||||
'io.murano.resources.ExistingNeutronNetwork'
|
||||
},
|
||||
},
|
||||
'flat': None
|
||||
}
|
||||
}
|
||||
if parsed_args.join_net_id:
|
||||
res['defaultNetworks']['environment']['internalNetworkName'] \
|
||||
= parsed_args.join_net_id
|
||||
if parsed_args.join_subnet_id:
|
||||
res['defaultNetworks']['environment']['internalSubnetworkName'
|
||||
] = \
|
||||
parsed_args.join_subnet_id
|
||||
|
||||
body.update(res)
|
||||
|
||||
data = client.environments.create(body)
|
||||
|
||||
columns = ('id', 'name', 'status', 'created', 'updated')
|
||||
column_headers = [c.capitalize() for c in columns]
|
||||
|
||||
return (
|
||||
column_headers,
|
||||
[utils.get_item_properties(
|
||||
data,
|
||||
columns,
|
||||
)]
|
||||
)
|
||||
|
||||
|
||||
class EnvironmentDelete(lister.Lister):
|
||||
"""Delete an environment."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(EnvironmentDelete, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'id',
|
||||
metavar="<NAME or ID>",
|
||||
nargs="+",
|
||||
help="Id or name of environment(s) to delete.",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--abandon',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="If set will abandon environment without deleting any of its"
|
||||
" resources.",
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
LOG.debug("take_action({0})".format(parsed_args))
|
||||
client = self.app.client_manager.application_catalog
|
||||
|
||||
abandon = getattr(parsed_args, 'abandon', False)
|
||||
failure_count = 0
|
||||
for environment_id in parsed_args.id:
|
||||
try:
|
||||
environment = murano_utils.find_resource(client.environments,
|
||||
environment_id)
|
||||
client.environments.delete(environment.id, abandon)
|
||||
except exceptions.NotFound:
|
||||
failure_count += 1
|
||||
print("Failed to delete '{0}'; environment not found".
|
||||
format(environment_id))
|
||||
|
||||
if failure_count == len(parsed_args.id):
|
||||
raise exceptions.CommandError("Unable to find and delete any of "
|
||||
"the specified environments.")
|
||||
|
||||
data = client.environments.list()
|
||||
|
||||
columns = ('id', 'name', 'status', 'created', 'updated')
|
||||
column_headers = [c.capitalize() for c in columns]
|
||||
|
||||
return (
|
||||
column_headers,
|
||||
list(utils.get_item_properties(
|
||||
s,
|
||||
columns,
|
||||
) for s in data)
|
||||
)
|
||||
|
|
|
@ -50,7 +50,8 @@ class TestListEnvironment(TestEnvironment):
|
|||
verifylist = []
|
||||
|
||||
mock_util.return_value = ('1234', 'Environment of all tenants',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54'
|
||||
'fake deployed', '2015-12-16T17:31:54',
|
||||
'2015-12-16T17:31:54'
|
||||
)
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
@ -58,12 +59,13 @@ class TestListEnvironment(TestEnvironment):
|
|||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Check that columns are correct
|
||||
expected_columns = ['Id', 'Name', 'Created', 'Updated']
|
||||
expected_columns = ['Id', 'Name', 'Status', 'Created', 'Updated']
|
||||
self.assertEqual(expected_columns, columns)
|
||||
|
||||
# Check that data is correct
|
||||
expected_data = [('1234', 'Environment of all tenants',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')]
|
||||
'fake deployed', '2015-12-16T17:31:54',
|
||||
'2015-12-16T17:31:54')]
|
||||
self.assertEqual(expected_data, data)
|
||||
|
||||
@mock.patch('openstackclient.common.utils.get_item_properties')
|
||||
|
@ -72,7 +74,8 @@ class TestListEnvironment(TestEnvironment):
|
|||
verifylist = [('all_tenants', True)]
|
||||
|
||||
mock_util.return_value = ('1234', 'Environment of all tenants',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54'
|
||||
'fake deployed', '2015-12-16T17:31:54',
|
||||
'2015-12-16T17:31:54'
|
||||
)
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
@ -80,12 +83,13 @@ class TestListEnvironment(TestEnvironment):
|
|||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Check that columns are correct
|
||||
expected_columns = ['Id', 'Name', 'Created', 'Updated']
|
||||
expected_columns = ['Id', 'Name', 'Status', 'Created', 'Updated']
|
||||
self.assertEqual(expected_columns, columns)
|
||||
|
||||
# Check that data is correct
|
||||
expected_data = [('1234', 'Environment of all tenants',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')]
|
||||
'fake deployed', '2015-12-16T17:31:54',
|
||||
'2015-12-16T17:31:54')]
|
||||
self.assertEqual(expected_data, data)
|
||||
|
||||
|
||||
|
@ -175,19 +179,20 @@ class TestRenameEnvironment(TestEnvironment):
|
|||
arglist = ['1234', 'fake-1']
|
||||
verifylist = [('id', '1234'), ('name', 'fake-1')]
|
||||
|
||||
mock_util.return_value = ('1234', 'fake-1', '2015-12-16T17:31:54',
|
||||
'2015-12-16T17:31:54')
|
||||
mock_util.return_value = ('1234', 'fake-1', 'fake deployed',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54'
|
||||
)
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Check that columns are correct
|
||||
expected_columns = ['Id', 'Name', 'Created', 'Updated']
|
||||
expected_columns = ['Id', 'Name', 'Status', 'Created', 'Updated']
|
||||
self.assertEqual(expected_columns, columns)
|
||||
|
||||
# Check that data is correct
|
||||
expected_data = [('1234', 'fake-1',
|
||||
expected_data = [('1234', 'fake-1', 'fake deployed',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')]
|
||||
self.assertEqual(expected_data, data)
|
||||
|
||||
|
@ -217,3 +222,172 @@ class TestEnvironmentSessionCreate(TestEnvironment):
|
|||
# Check that data is correct
|
||||
expected_data = ['1abc2xyz']
|
||||
self.assertEqual(expected_data, data)
|
||||
|
||||
|
||||
class TestEnvironmentCreate(TestEnvironment):
|
||||
def setUp(self):
|
||||
super(TestEnvironmentCreate, self).setUp()
|
||||
self.environment_mock.create.return_value = [api_env.Environment(None,
|
||||
ENV_INFO)]
|
||||
|
||||
# Command to test
|
||||
self.cmd = osc_env.EnvironmentCreate(self.app, None)
|
||||
|
||||
@mock.patch('openstackclient.common.utils.get_item_properties')
|
||||
def test_environment_create_with_no_option(self, mock_util):
|
||||
arglist = ['fake']
|
||||
verifylist = [('name', 'fake')]
|
||||
|
||||
mock_util.return_value = ('1234', 'fake', 'ready',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Check that columns are correct
|
||||
expected_columns = ['Id', 'Name', 'Status', 'Created', 'Updated']
|
||||
self.assertEqual(expected_columns, columns)
|
||||
|
||||
# Check that data is correct
|
||||
expected_data = [('1234', 'fake', 'ready',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')]
|
||||
self.assertEqual(expected_data, data)
|
||||
|
||||
@mock.patch('openstackclient.common.utils.get_item_properties')
|
||||
def test_environment_create_with_region_option(self, mock_util):
|
||||
arglist = ['fake', '--region', 'region_one']
|
||||
verifylist = [('name', 'fake'), ('region', 'region_one')]
|
||||
|
||||
mock_util.return_value = ('1234', 'fake', 'ready',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Check that correct arguments are passed
|
||||
self.environment_mock.create.assert_has_calls([mock.call(
|
||||
{'name': 'fake', 'region': 'region_one'})])
|
||||
|
||||
# Check that columns are correct
|
||||
expected_columns = ['Id', 'Name', 'Status', 'Created', 'Updated']
|
||||
self.assertEqual(expected_columns, columns)
|
||||
|
||||
# Check that data is correct
|
||||
expected_data = [('1234', 'fake', 'ready',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')]
|
||||
self.assertEqual(expected_data, data)
|
||||
|
||||
@mock.patch('openstackclient.common.utils.get_item_properties')
|
||||
def test_environment_create_with_net_option(self, mock_util):
|
||||
arglist = ['fake', '--join-net-id', 'x1y2z3']
|
||||
verifylist = [('name', 'fake'), ('join_net_id', 'x1y2z3')]
|
||||
|
||||
mock_util.return_value = ('1234', 'fake', 'ready',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
expected_call = {
|
||||
'defaultNetworks': {
|
||||
'environment': {
|
||||
'internalNetworkName': 'x1y2z3',
|
||||
'?': {
|
||||
'type': 'io.murano.resources.ExistingNeutronNetwork',
|
||||
'id': mock.ANY
|
||||
}
|
||||
},
|
||||
'flat': None
|
||||
},
|
||||
'name': 'fake',
|
||||
'region': None
|
||||
}
|
||||
|
||||
# Check that correct arguments are passed
|
||||
self.environment_mock.create.assert_called_with(expected_call)
|
||||
|
||||
# Check that columns are correct
|
||||
expected_columns = ['Id', 'Name', 'Status', 'Created', 'Updated']
|
||||
self.assertEqual(expected_columns, columns)
|
||||
|
||||
# Check that data is correct
|
||||
expected_data = [('1234', 'fake', 'ready',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')]
|
||||
self.assertEqual(expected_data, data)
|
||||
|
||||
@mock.patch('openstackclient.common.utils.get_item_properties')
|
||||
def test_environment_create_with_subnet_option(self, mock_util):
|
||||
arglist = ['fake', '--join-subnet-id', 'x1y2z3']
|
||||
verifylist = [('name', 'fake'), ('join_subnet_id', 'x1y2z3')]
|
||||
|
||||
mock_util.return_value = ('1234', 'fake', 'ready',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
expected_call = {
|
||||
'defaultNetworks': {
|
||||
'environment': {
|
||||
'internalSubnetworkName': 'x1y2z3',
|
||||
'?': {
|
||||
'type': 'io.murano.resources.ExistingNeutronNetwork',
|
||||
'id': mock.ANY
|
||||
}
|
||||
},
|
||||
'flat': None
|
||||
},
|
||||
'name': 'fake',
|
||||
'region': None
|
||||
}
|
||||
|
||||
# Check that correct arguments are passed
|
||||
self.environment_mock.create.assert_called_with(expected_call)
|
||||
|
||||
# Check that columns are correct
|
||||
expected_columns = ['Id', 'Name', 'Status', 'Created', 'Updated']
|
||||
self.assertEqual(expected_columns, columns)
|
||||
|
||||
# Check that data is correct
|
||||
expected_data = [('1234', 'fake', 'ready',
|
||||
'2015-12-16T17:31:54', '2015-12-16T17:31:54')]
|
||||
self.assertEqual(expected_data, data)
|
||||
|
||||
|
||||
class TestEnvironmentDelete(TestEnvironment):
|
||||
def setUp(self):
|
||||
super(TestEnvironmentDelete, self).setUp()
|
||||
self.environment_mock.delete.return_value = None
|
||||
self.environment_mock.list.return_value = [api_env.Environment(None,
|
||||
ENV_INFO)]
|
||||
|
||||
# Command to test
|
||||
self.cmd = osc_env.EnvironmentDelete(self.app, None)
|
||||
|
||||
@mock.patch('openstackclient.common.utils.get_item_properties')
|
||||
def test_environment_delete(self, mock_util):
|
||||
arglist = ['fake1', 'fake2']
|
||||
verifylist = [('id', ['fake1', 'fake2'])]
|
||||
|
||||
mock_util.return_value = ('1234', 'Environment of all tenants',
|
||||
'fake deployed', '2015-12-16T17:31:54',
|
||||
'2015-12-16T17:31:54'
|
||||
)
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Check that columns are correct
|
||||
expected_columns = ['Id', 'Name', 'Status', 'Created', 'Updated']
|
||||
self.assertEqual(expected_columns, columns)
|
||||
|
||||
# Check that data is correct
|
||||
expected_data = [('1234', 'Environment of all tenants',
|
||||
'fake deployed', '2015-12-16T17:31:54',
|
||||
'2015-12-16T17:31:54')]
|
||||
self.assertEqual(expected_data, data)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
features:
|
||||
- New OSC command ``environment create [--join-net-id <NET_ID>]
|
||||
[--join-subnet-id <SUBNET_ID>] [--region <REGION_NAME>] <ENVIRONMENT_NAME>``
|
||||
- New OSC command ``environment delete [--abandon] <NAME or ID>
|
||||
[<NAME or ID> ...]``
|
|
@ -38,6 +38,8 @@ openstack.application_catalog.v1 =
|
|||
environment_show = muranoclient.osc.v1.environment:ShowEnvironment
|
||||
environment_rename = muranoclient.osc.v1.environment:RenameEnvironment
|
||||
environment_session_create = muranoclient.osc.v1.environment:EnvironmentSessionCreate
|
||||
environment_create = muranoclient.osc.v1.environment:EnvironmentCreate
|
||||
environment_delete = muranoclient.osc.v1.environment:EnvironmentDelete
|
||||
|
||||
[global]
|
||||
setup-hooks =
|
||||
|
|
Loading…
Reference in New Issue