diff --git a/senlinclient/osc/v1/profile.py b/senlinclient/osc/v1/profile.py index 7e8b273e..b5e4dd76 100644 --- a/senlinclient/osc/v1/profile.py +++ b/senlinclient/osc/v1/profile.py @@ -195,3 +195,60 @@ class DeleteProfile(command.Command): {'count': failure_count, 'total': len(parsed_args.id)}) print('Profile deleted: %s' % parsed_args.id) + + +class CreateProfile(show.ShowOne): + """Create a profile.""" + + log = logging.getLogger(__name__ + ".CreateProfile") + + def get_parser(self, prog_name): + parser = super(CreateProfile, self).get_parser(prog_name) + parser.add_argument( + '--spec-file', + metavar='', + required=True, + help=_('The spec file used to create the profile') + ) + parser.add_argument( + '--metadata', + metavar='', + help=_('Metadata values to be attached to the profile. ' + 'This can be specified multiple times, or once with ' + 'key-value pairs separated by a semicolon'), + action='append' + ) + parser.add_argument( + 'name', + metavar='', + help=_('Name of the profile to create') + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + senlin_client = self.app.client_manager.clustering + + spec = senlin_utils.get_spec_content(parsed_args.spec_file) + type_name = spec.get('type', None) + type_version = spec.get('version', None) + properties = spec.get('properties', None) + if type_name is None: + raise exc.CommandError(_("Missing 'type' key in spec file.")) + if type_version is None: + raise exc.CommandError(_("Missing 'version' key in spec file.")) + if properties is None: + raise exc.CommandError(_("Missing 'properties' key in spec file.")) + + if type_name == 'os.heat.stack': + stack_properties = senlin_utils.process_stack_spec(properties) + spec['properties'] = stack_properties + + params = { + 'name': parsed_args.name, + 'spec': spec, + 'metadata': senlin_utils.format_parameters(parsed_args.metadata), + } + + profile = senlin_client.create_profile(**params) + return _show_profile(senlin_client, profile_id=profile.id) diff --git a/senlinclient/tests/test_specs/nova_server.yaml b/senlinclient/tests/test_specs/nova_server.yaml new file mode 100644 index 00000000..07fa0301 --- /dev/null +++ b/senlinclient/tests/test_specs/nova_server.yaml @@ -0,0 +1,6 @@ +type: os.nova.server +version: 1.0 +properties: + name: cirros_server + flavor: 1 + image: cirros-0.3.4-x86_64-uec diff --git a/senlinclient/tests/unit/osc/v1/test_profile.py b/senlinclient/tests/unit/osc/v1/test_profile.py index 772a2e65..4aa7eefa 100644 --- a/senlinclient/tests/unit/osc/v1/test_profile.py +++ b/senlinclient/tests/unit/osc/v1/test_profile.py @@ -273,3 +273,60 @@ class TestProfileDelete(TestProfile): mock_stdin.readline.assert_called_with() self.mock_client.delete_profile.assert_not_called() + + +class TestProfileCreate(TestProfile): + + spec_path = 'senlinclient/tests/test_specs/nova_server.yaml' + response = {"profile": { + "created_at": "2016-02-17T12:10:57", + "domain": None, + "id": "e3057c77-a178-4265-bafd-16b2fae50eea", + "metadata": {}, + "name": "pro-nova", + "project": "5f1cc92b578e4e25a3b284179cf20a9b", + "spec": {"properties": { + "flavor": 1, + "image": "cirros-0.3.4-x86_64-uec", + "name": "cirros_server"}, + "type": "os.nova.server", + "version": 1.0}, + "type": "os.nova.server-1.0", + "updated_at": None, + "user": "2d7aca950f3e465d8ef0c81720faf6ff"}} + + defaults = {"spec": { + "version": 1.0, + "type": "os.nova.server", + "properties": { + "flavor": 1, + "name": "cirros_server", + "image": "cirros-0.3.4-x86_64-uec"} + }, + "name": "my_profile", + "metadata": {} + } + + def setUp(self): + super(TestProfileCreate, self).setUp() + self.cmd = osc_profile.CreateProfile(self.app, None) + self.mock_client.create_profile = mock.Mock( + return_value=sdk_profile.Profile(None, self.response)) + self.mock_client.get_profile = mock.Mock( + return_value=sdk_profile.Profile(None, self.response)) + utils.get_dict_properties = mock.Mock(return_value='') + + def test_profile_create_defaults(self): + arglist = ['my_profile', '--spec-file', self.spec_path] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.mock_client.create_profile.assert_called_with(**self.defaults) + + def test_profile_create_metadata(self): + arglist = ['my_profile', '--spec-file', self.spec_path, + '--metadata', 'key1=value1'] + kwargs = copy.deepcopy(self.defaults) + kwargs['metadata'] = {'key1': 'value1'} + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.mock_client.create_profile.assert_called_with(**kwargs) diff --git a/setup.cfg b/setup.cfg index 0b5f2ea4..196e5a0f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,6 +30,7 @@ openstack.cli.extension = clustering = senlinclient.osc.plugin openstack.clustering.v1 = + cluster_profile_create = senlinclient.osc.v1.profile:CreateProfile cluster_profile_delete = senlinclient.osc.v1.profile:DeleteProfile cluster_profile_list = senlinclient.osc.v1.profile:ListProfile cluster_profile_show = senlinclient.osc.v1.profile:ShowProfile