Add attribute schemas to `OS::Magnum::Cluster`
Add attribute schemas to allow use get_attr for `OS::Magnum::Cluster`. Partial-Bug: #1625757 Change-Id: I714f6dbc3a612425128f18ef3cea0336fdc47090
This commit is contained in:
parent
4992593baa
commit
3c06d0a349
|
@ -15,6 +15,7 @@ import six
|
|||
|
||||
from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
from heat.engine import attributes
|
||||
from heat.engine import constraints
|
||||
from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
|
@ -35,6 +36,85 @@ class Cluster(resource.Resource):
|
|||
|
||||
entity = 'clusters'
|
||||
|
||||
ATTRIBUTES = (
|
||||
API_ADDRESS_ATTR, STACK_ID_ATTR, COE_VERSION_ATTR,
|
||||
MASTER_ADDRESSES_ATTR, STATUS_ATTR, MASTER_COUNT_ATTR,
|
||||
NODE_ADDRESSES_ATTR, STATUS_REASON_ATTR, NODE_COUNT_ATTR,
|
||||
NAME_ATTR, CONTAINER_VERSION_ATTR, DISCOVERY_URL_ATTR,
|
||||
CLUSTER_TEMPLATE_ID_ATTR, KEYPAIR_ATTR, CREATE_TIMEOUT_ATTR
|
||||
) = (
|
||||
'api_address', 'stack_id', 'coe_version',
|
||||
'master_addresses', 'status', 'master_count',
|
||||
'node_addresses', 'status_reason', 'node_count',
|
||||
'name', 'container_version', 'discovery_url',
|
||||
'cluster_template_id', 'keypair', 'create_timeout'
|
||||
)
|
||||
attributes_schema = {
|
||||
API_ADDRESS_ATTR: attributes.Schema(
|
||||
_('The endpoint URL of COE API exposed to end-users.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
STACK_ID_ATTR: attributes.Schema(
|
||||
_('The reference UUID of orchestration stack for this '
|
||||
'COE cluster.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
COE_VERSION_ATTR: attributes.Schema(
|
||||
_('Version info of chosen COE in cluster for helping client '
|
||||
'in picking the right version of client.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
MASTER_ADDRESSES_ATTR: attributes.Schema(
|
||||
_('List of floating IP of all master nodes.'),
|
||||
type=attributes.Schema.LIST
|
||||
),
|
||||
STATUS_ATTR: attributes.Schema(
|
||||
_('The status for this COE cluster.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
MASTER_COUNT_ATTR: attributes.Schema(
|
||||
_('The number of servers that will serve as master for the '
|
||||
'cluster.'),
|
||||
type=attributes.Schema.INTEGER
|
||||
),
|
||||
NODE_ADDRESSES_ATTR: attributes.Schema(
|
||||
_('List of floating IP of all servers that serve as node.'),
|
||||
type=attributes.Schema.LIST
|
||||
),
|
||||
STATUS_REASON_ATTR: attributes.Schema(
|
||||
_('The reason of cluster current status.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
NODE_COUNT_ATTR: attributes.Schema(
|
||||
_('The number of servers that will serve as node in the cluster.'),
|
||||
type=attributes.Schema.INTEGER
|
||||
),
|
||||
NAME_ATTR: attributes.Schema(
|
||||
_('Name of the resource.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
CONTAINER_VERSION_ATTR: attributes.Schema(
|
||||
_('Version info of constainer engine in the chosen COE in cluster '
|
||||
'for helping client in picking the right version of client.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
DISCOVERY_URL_ATTR: attributes.Schema(
|
||||
_('The custom discovery url for node discovery.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
CLUSTER_TEMPLATE_ID_ATTR: attributes.Schema(
|
||||
_('The UUID of the cluster template.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
KEYPAIR_ATTR: attributes.Schema(
|
||||
_('The name of the keypair.'),
|
||||
type=attributes.Schema.STRING
|
||||
),
|
||||
CREATE_TIMEOUT_ATTR: attributes.Schema(
|
||||
_('The timeout for cluster creation in minutes.'),
|
||||
type=attributes.Schema.INTEGER
|
||||
)}
|
||||
|
||||
PROPERTIES = (
|
||||
NAME, CLUSTER_TEMPLATE, KEYPAIR, NODE_COUNT, MASTER_COUNT,
|
||||
DISCOVERY_URL, CREATE_TIMEOUT
|
||||
|
@ -103,6 +183,12 @@ class Cluster(resource.Resource):
|
|||
finder='get_cluster_template')
|
||||
]
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
if self.resource_id is None:
|
||||
return
|
||||
cluster = self.client().clusters.get(self.resource_id)
|
||||
return getattr(cluster, name, None)
|
||||
|
||||
def handle_create(self):
|
||||
args = dict(self.properties.items())
|
||||
|
||||
|
|
|
@ -53,23 +53,65 @@ RESOURCE_TYPE = 'OS::Magnum::Cluster'
|
|||
class TestMagnumCluster(common.HeatTestCase):
|
||||
def setUp(self):
|
||||
super(TestMagnumCluster, self).setUp()
|
||||
|
||||
self.resource_id = '12345'
|
||||
self.fake_name = u'test_cluster'
|
||||
self.fake_keypair = u'key'
|
||||
self.fake_cluster_template = '123456'
|
||||
self.fake_node_count = 5
|
||||
self.fake_master_count = 1
|
||||
self.fake_discovery_url = u'https://discovery.etcd.io'
|
||||
self.fake_create_timeout = 15
|
||||
self.fake_api_address = 'https://192.168.0.249:6443'
|
||||
self.fake_coe_version = 'v1.5.2'
|
||||
self.fake_master_addresses = ['192.168.0.2']
|
||||
self.fake_status = 'bar'
|
||||
self.fake_node_addresses = ['192.168.0.3', '192.168.0.4',
|
||||
'192.168.0.5', '192.168.0.6',
|
||||
'192.168.0.7']
|
||||
self.fake_status_reason = 'foobar'
|
||||
self.fake_stack_id = '22767a68-a7f2-45fe-bc08-335a83e2b919'
|
||||
self.fake_container_version = '1.12.6'
|
||||
|
||||
resource._register_class(RESOURCE_TYPE, cluster.Cluster)
|
||||
t = template_format.parse(magnum_template)
|
||||
self.stack = utils.parse_stack(t)
|
||||
resource_defns = self.stack.t.resource_definitions(self.stack)
|
||||
self.min_rsrc_defn = resource_defns['test_cluster_min']
|
||||
resource_defns = self.stack.t.resource_definitions(self.stack)
|
||||
self.rsrc_defn = resource_defns['test_cluster']
|
||||
self.rsrc_defn = resource_defns[self.fake_name]
|
||||
self.client = mock.Mock()
|
||||
self.patchobject(cluster.Cluster, 'client', return_value=self.client)
|
||||
self.m_fct = self.patchobject(mc.MagnumClientPlugin,
|
||||
'get_cluster_template')
|
||||
self.m_fnk = self.patchobject(nova.NovaClientPlugin,
|
||||
'get_keypair', return_value='key')
|
||||
'get_keypair',
|
||||
return_value=self.fake_keypair)
|
||||
|
||||
def _mock_get_client(self):
|
||||
value = mock.MagicMock()
|
||||
value.name = self.fake_name
|
||||
value.cluster_template_id = self.fake_cluster_template
|
||||
value.uuid = self.resource_id
|
||||
value.coe_version = self.fake_coe_version
|
||||
value.node_count = self.fake_node_count
|
||||
value.master_count = self.fake_master_count
|
||||
value.discovery_url = self.fake_discovery_url
|
||||
value.create_timeout = self.fake_create_timeout
|
||||
value.api_address = self.fake_api_address
|
||||
value.master_addresses = self.fake_master_addresses
|
||||
value.status = self.fake_status
|
||||
value.node_addresses = self.fake_node_addresses
|
||||
value.status_reason = self.fake_status_reason
|
||||
value.stack_id = self.fake_stack_id
|
||||
value.container_version = self.fake_container_version
|
||||
value.keypair = self.fake_keypair
|
||||
value.to_dict.return_value = value.__dict__
|
||||
|
||||
self.client.clusters.get.return_value = value
|
||||
|
||||
def _create_resource(self, name, snippet, stack, stat='CREATE_COMPLETE'):
|
||||
self.resource_id = '12345'
|
||||
self.m_fct.return_value = '123456'
|
||||
self.m_fct.return_value = self.fake_cluster_template
|
||||
value = mock.MagicMock(uuid=self.resource_id)
|
||||
self.client.clusters.create.return_value = value
|
||||
get_rv = mock.MagicMock(status=stat)
|
||||
|
@ -81,37 +123,38 @@ class TestMagnumCluster(common.HeatTestCase):
|
|||
b = self._create_resource('cluster', self.rsrc_defn, self.stack)
|
||||
# validate the properties
|
||||
self.assertEqual(
|
||||
'test_cluster',
|
||||
self.fake_name,
|
||||
b.properties.get(cluster.Cluster.NAME))
|
||||
self.assertEqual(
|
||||
'123456',
|
||||
self.fake_cluster_template,
|
||||
b.properties.get(cluster.Cluster.CLUSTER_TEMPLATE))
|
||||
self.assertEqual(
|
||||
'key',
|
||||
self.fake_keypair,
|
||||
b.properties.get(cluster.Cluster.KEYPAIR))
|
||||
self.assertEqual(
|
||||
5,
|
||||
self.fake_node_count,
|
||||
b.properties.get(cluster.Cluster.NODE_COUNT))
|
||||
self.assertEqual(
|
||||
1,
|
||||
self.fake_master_count,
|
||||
b.properties.get(cluster.Cluster.MASTER_COUNT))
|
||||
self.assertEqual(
|
||||
'https://discovery.etcd.io',
|
||||
self.fake_discovery_url,
|
||||
b.properties.get(cluster.Cluster.DISCOVERY_URL))
|
||||
self.assertEqual(
|
||||
15,
|
||||
self.fake_create_timeout,
|
||||
b.properties.get(cluster.Cluster.CREATE_TIMEOUT))
|
||||
scheduler.TaskRunner(b.create)()
|
||||
self.assertEqual(self.resource_id, b.resource_id)
|
||||
self.assertEqual((b.CREATE, b.COMPLETE), b.state)
|
||||
self.client.clusters.create.assert_called_once_with(
|
||||
name=u'test_cluster',
|
||||
keypair=u'key',
|
||||
cluster_template_id='123456',
|
||||
node_count=5,
|
||||
master_count=1,
|
||||
discovery_url=u'https://discovery.etcd.io',
|
||||
create_timeout=15)
|
||||
name=self.fake_name,
|
||||
keypair=self.fake_keypair,
|
||||
cluster_template_id=self.fake_cluster_template,
|
||||
node_count=self.fake_node_count,
|
||||
master_count=self.fake_master_count,
|
||||
discovery_url=self.fake_discovery_url,
|
||||
create_timeout=self.fake_create_timeout
|
||||
)
|
||||
|
||||
def test_cluster_create_with_default_value(self):
|
||||
b = self._create_resource('cluster', self.min_rsrc_defn,
|
||||
|
@ -121,7 +164,7 @@ class TestMagnumCluster(common.HeatTestCase):
|
|||
None,
|
||||
b.properties.get(cluster.Cluster.NAME))
|
||||
self.assertEqual(
|
||||
'123456',
|
||||
self.fake_cluster_template,
|
||||
b.properties.get(cluster.Cluster.CLUSTER_TEMPLATE))
|
||||
self.assertEqual(
|
||||
None,
|
||||
|
@ -144,7 +187,7 @@ class TestMagnumCluster(common.HeatTestCase):
|
|||
self.client.clusters.create.assert_called_once_with(
|
||||
name=None,
|
||||
keypair=None,
|
||||
cluster_template_id='123456',
|
||||
cluster_template_id=self.fake_cluster_template,
|
||||
node_count=1,
|
||||
master_count=1,
|
||||
discovery_url=None,
|
||||
|
@ -174,9 +217,9 @@ class TestMagnumCluster(common.HeatTestCase):
|
|||
self.client.clusters.get.return_value = status
|
||||
t = template_format.parse(magnum_template)
|
||||
new_t = copy.deepcopy(t)
|
||||
new_t['resources']['test_cluster']['properties']['node_count'] = 10
|
||||
new_t['resources'][self.fake_name]['properties']['node_count'] = 10
|
||||
rsrc_defns = template.Template(new_t).resource_definitions(self.stack)
|
||||
new_bm = rsrc_defns['test_cluster']
|
||||
new_bm = rsrc_defns[self.fake_name]
|
||||
if update_status == 'UPDATE_COMPLETE':
|
||||
scheduler.TaskRunner(b.update, new_bm)()
|
||||
self.assertEqual((b.UPDATE, b.COMPLETE), b.state)
|
||||
|
@ -208,19 +251,62 @@ class TestMagnumCluster(common.HeatTestCase):
|
|||
def test_cluster_get_live_state(self):
|
||||
b = self._create_resource('cluster', self.rsrc_defn, self.stack)
|
||||
scheduler.TaskRunner(b.create)()
|
||||
value = mock.MagicMock()
|
||||
value.to_dict.return_value = {
|
||||
'cluster_template': 123456,
|
||||
'node_count': 5,
|
||||
'master_count': 1,
|
||||
'discovery_url': 'https://discovery.etcd.io',
|
||||
'create_timeout': 15}
|
||||
self.client.clusters.get.return_value = value
|
||||
self._mock_get_client()
|
||||
reality = b.get_live_state(b.properties)
|
||||
self.assertEqual(
|
||||
{'create_timeout': 15,
|
||||
'discovery_url': 'https://discovery.etcd.io',
|
||||
'master_count': 1,
|
||||
'node_count': 5
|
||||
},
|
||||
reality)
|
||||
{
|
||||
cluster.Cluster.CREATE_TIMEOUT: self.fake_create_timeout,
|
||||
cluster.Cluster.DISCOVERY_URL: self.fake_discovery_url,
|
||||
cluster.Cluster.MASTER_COUNT: self.fake_master_count,
|
||||
cluster.Cluster.NODE_COUNT: self.fake_node_count
|
||||
}, reality)
|
||||
|
||||
def test_resolve_attributes(self):
|
||||
b = self._create_resource('cluster', self.rsrc_defn, self.stack)
|
||||
scheduler.TaskRunner(b.create)()
|
||||
self._mock_get_client()
|
||||
self.assertEqual(
|
||||
self.fake_name,
|
||||
b._resolve_attribute(cluster.Cluster.NAME_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_coe_version,
|
||||
b._resolve_attribute(cluster.Cluster.COE_VERSION_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_stack_id,
|
||||
b._resolve_attribute(cluster.Cluster.STACK_ID_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_api_address,
|
||||
b._resolve_attribute(cluster.Cluster.API_ADDRESS_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_master_count,
|
||||
b._resolve_attribute(cluster.Cluster.MASTER_COUNT_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_status,
|
||||
b._resolve_attribute(cluster.Cluster.STATUS_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_master_addresses,
|
||||
b._resolve_attribute(cluster.Cluster.MASTER_ADDRESSES_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_node_addresses,
|
||||
b._resolve_attribute(cluster.Cluster.NODE_ADDRESSES_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_status_reason,
|
||||
b._resolve_attribute(cluster.Cluster.STATUS_REASON_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_node_count,
|
||||
b._resolve_attribute(cluster.Cluster.NODE_COUNT_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_container_version,
|
||||
b._resolve_attribute(cluster.Cluster.CONTAINER_VERSION_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_discovery_url,
|
||||
b._resolve_attribute(cluster.Cluster.DISCOVERY_URL_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_cluster_template,
|
||||
b._resolve_attribute(cluster.Cluster.CLUSTER_TEMPLATE_ID_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_keypair,
|
||||
b._resolve_attribute(cluster.Cluster.KEYPAIR_ATTR))
|
||||
self.assertEqual(
|
||||
self.fake_create_timeout,
|
||||
b._resolve_attribute(cluster.Cluster.CREATE_TIMEOUT_ATTR))
|
||||
|
|
Loading…
Reference in New Issue