OSC 2/4 Add Cluster Create and List

Add cluster create and cluster list for magnum's OSC plugin.
Add cluster create and list unit tests

Implements: blueprint openstackclient-support
Co-Authored-By: Spyros Trigazis <strigazi@gmail.com>
Change-Id: I815633e45df681e6bf089ae82d7451c2c0df05ef
This commit is contained in:
Stephen Watson 2017-03-15 14:25:28 -07:00 committed by Spyros Trigazis
parent 7768eb6ea2
commit 98c4ed730d
4 changed files with 370 additions and 0 deletions

View File

@ -0,0 +1,127 @@
# Copyright 2016 EasyStack. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from magnumclient.i18n import _
from osc_lib.command import command
from osc_lib import utils
class CreateCluster(command.Command):
_description = _("Create a cluster")
def get_parser(self, prog_name):
parser = super(CreateCluster, self).get_parser(prog_name)
# NOTE: All arguments are positional and, if not provided
# with a default, required.
parser.add_argument('--cluster-template',
dest='cluster_template',
required=True,
metavar='<cluster-template>',
help='ID or name of the cluster template.')
parser.add_argument('--discovery-url',
dest='discovery_url',
metavar='<discovery-url>',
help=('Specifies custom delivery url for '
'node discovery.'))
parser.add_argument('--docker-volume-size',
dest='docker_volume_size',
type=int,
metavar='<docker-volume-size>',
help=('The size in GB for the docker volume to '
'use.'))
parser.add_argument('--keypair',
default=None,
metavar='<keypair>',
help='UUID or name of the keypair to use.')
parser.add_argument('--master-count',
dest='master_count',
type=int,
default=1,
metavar='<master-count>',
help='The number of master nodes for the cluster.')
parser.add_argument('--name',
metavar='<name>',
help='Name of the cluster to create.')
parser.add_argument('--node-count',
dest='node_count',
type=int,
default=1,
metavar='<node-count>',
help='The cluster node count.')
parser.add_argument('--timeout',
type=int,
default=60,
metavar='<timeout>',
help=('The timeout for cluster creation time. The '
'default is 60 minutes.'))
return parser
def take_action(self, parsed_args):
self.log.debug("take_action(%s)", parsed_args)
mag_client = self.app.client_manager.container_infra
args = {
'cluster_template_id': parsed_args.cluster_template,
'create_timeout': parsed_args.timeout,
'discovery_url': parsed_args.discovery_url,
'docker_volume_size': parsed_args.docker_volume_size,
'keypair': parsed_args.keypair,
'master_count': parsed_args.master_count,
'name': parsed_args.name,
'node_count': parsed_args.node_count,
}
cluster = mag_client.clusters.create(**args)
print("Request to create cluster %s accepted"
% cluster.uuid)
class ListCluster(command.Lister):
_description = _("List clusters")
def get_parser(self, prog_name):
parser = super(ListCluster, self).get_parser(prog_name)
parser.add_argument(
'--limit',
metavar='<limit>',
type=int,
help=_('Maximum number of clusters to return'))
parser.add_argument(
'--sort-key',
metavar='<sort-key>',
help=_('Column to sort results by'))
parser.add_argument(
'--sort-dir',
metavar='<sort-dir>',
choices=['desc', 'asc'],
help=_('Direction to sort. "asc" or "desc".'))
return parser
def take_action(self, parsed_args):
self.log.debug("take_action(%s)", parsed_args)
mag_client = self.app.client_manager.container_infra
columns = [
'uuid', 'name', 'keypair', 'node_count', 'master_count', 'status']
clusters = mag_client.clusters.list(limit=parsed_args.limit,
sort_key=parsed_args.sort_key,
sort_dir=parsed_args.sort_dir)
return (
columns,
(utils.get_item_properties(c, columns) for c in clusters)
)

View File

@ -46,6 +46,7 @@ class FakeBaseModelManager(object):
class MagnumFakeContainerInfra(object):
def __init__(self):
self.cluster_templates = FakeBaseModelManager()
self.clusters = FakeBaseModelManager()
class MagnumFakeClientManager(osc_fakes.FakeClientManager):
@ -161,3 +162,48 @@ class FakeClusterTemplate(object):
cts.append(FakeClusterTemplate.create_one_cluster_template(attrs))
return cts
class FakeCluster(object):
"""Fake one or more Cluster."""
@staticmethod
def create_one_cluster(attrs=None):
"""Create a fake Cluster.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with flavor_id, image_id, and so on
"""
attrs = attrs or {}
# set default attributes.
cluster_info = {
'status': 'CREATE_IN_PROGRESS',
'cluster_template_id': 'fake-ct',
'node_addresses': [],
'uuid': '3a369884-b6ba-484f-a206-919b4b718aff',
'stack_id': 'c4554582-77bd-4734-8f1a-72c3c40e5fb4',
'status_reason': None,
'created_at': '2017-03-16T18:40:39+00:00',
'updated_at': '2017-03-16T18:40:45+00:00',
'coe_version': None,
'keypair': 'fakekey',
'api_address': None,
'master_addresses': [],
'create_timeout': 60,
'node_count': 1,
'discovery_url': 'https://fake.cluster',
'master_count': 1,
'container_version': None,
'name': 'fake-cluster'
}
# Overwrite default attributes.
cluster_info.update(attrs)
cluster = osc_fakes.FakeResource(info=copy.deepcopy(cluster_info),
loaded=True)
return cluster

View File

@ -0,0 +1,194 @@
# Copyright 2016 Easystack. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
import copy
import mock
from magnumclient.osc.v1 import clusters as osc_clusters
from magnumclient.tests.osc.unit.v1 import fakes as magnum_fakes
class TestCluster(magnum_fakes.TestMagnumClientOSCV1):
def setUp(self):
super(TestCluster, self).setUp()
self.clusters_mock = self.app.client_manager.container_infra.clusters
class TestClusterCreate(TestCluster):
def setUp(self):
super(TestClusterCreate, self).setUp()
attr = dict()
attr['name'] = 'fake-cluster-1'
self._cluster = magnum_fakes.FakeCluster.create_one_cluster(attr)
self._default_args = {
'cluster_template_id': 'fake-ct',
'create_timeout': 60,
'discovery_url': None,
'docker_volume_size': None,
'keypair': None,
'master_count': 1,
'name': None,
'node_count': 1
}
self.clusters_mock.create = mock.Mock()
self.clusters_mock.create.return_value = self._cluster
self.clusters_mock.get = mock.Mock()
self.clusters_mock.get.return_value = copy.deepcopy(self._cluster)
self.clusters_mock.update = mock.Mock()
self.clusters_mock.update.return_value = self._cluster
# Get the command object to test
self.cmd = osc_clusters.CreateCluster(self.app, None)
self.data = (
self._cluster.status,
self._cluster.cluster_template_id,
self._cluster.node_addresses,
self._cluster.uuid,
self._cluster.stack_id,
self._cluster.status_reason,
self._cluster.created_at,
self._cluster.updated_at,
self._cluster.coe_version,
self._cluster.keypair,
self._cluster.api_address,
self._cluster.master_addresses,
self._cluster.create_timeout,
self._cluster.node_count,
self._cluster.discovery_url,
self._cluster.master_count,
self._cluster.container_version,
self._cluster.name
)
def test_cluster_create_required_args_pass(self):
"""Verifies required arguments."""
arglist = [
'--cluster-template', self._cluster.cluster_template_id
]
verifylist = [
('cluster_template', self._cluster.cluster_template_id)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.clusters_mock.create.assert_called_with(**self._default_args)
def test_cluster_create_missing_required_arg(self):
"""Verifies missing required arguments."""
arglist = [
'--name', self._cluster.name
]
verifylist = [
('name', self._cluster.name)
]
self.assertRaises(magnum_fakes.MagnumParseException,
self.check_parser, self.cmd, arglist, verifylist)
class TestClusterList(TestCluster):
attr = dict()
attr['name'] = 'fake-cluster-1'
_cluster = magnum_fakes.FakeCluster.create_one_cluster(attr)
columns = [
'uuid',
'name',
'keypair',
'node_count',
'master_count',
'status'
]
datalist = (
(
_cluster.uuid,
_cluster.name,
_cluster.keypair,
_cluster.node_count,
_cluster.master_count,
_cluster.status
),
)
def setUp(self):
super(TestClusterList, self).setUp()
self.clusters_mock.list = mock.Mock()
self.clusters_mock.list.return_value = [self._cluster]
# Get the command object to test
self.cmd = osc_clusters.ListCluster(self.app, None)
def test_cluster_list_no_options(self):
arglist = []
verifylist = [
('limit', None),
('sort_key', None),
('sort_dir', None),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.clusters_mock.list.assert_called_with(
limit=None,
sort_dir=None,
sort_key=None,
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, tuple(data))
def test_cluster_list_options(self):
arglist = [
'--limit', '1',
'--sort-key', 'key',
'--sort-dir', 'asc'
]
verifylist = [
('limit', 1),
('sort_key', 'key'),
('sort_dir', 'asc')
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.clusters_mock.list.assert_called_with(
limit=1,
sort_dir='asc',
sort_key='key',
)
def test_cluster_list_bad_sort_dir_fail(self):
arglist = [
'--sort-dir', 'foo'
]
verifylist = [
('limit', None),
('sort_key', None),
('sort_dir', 'foo'),
('fields', None),
]
self.assertRaises(magnum_fakes.MagnumParseException,
self.check_parser, self.cmd, arglist, verifylist)

View File

@ -33,6 +33,9 @@ openstack.container_infra.v1 =
coe_cluster_template_create = magnumclient.osc.v1.cluster_templates:CreateClusterTemplate
coe_cluster_template_list = magnumclient.osc.v1.cluster_templates:ListTemplateCluster
coe_cluster_create = magnumclient.osc.v1.clusters:CreateCluster
coe_cluster_list = magnumclient.osc.v1.clusters:ListCluster
[build_sphinx]
source-dir = doc/source
build-dir = doc/build