diff --git a/heat/engine/resources/openstack/senlin/cluster.py b/heat/engine/resources/openstack/senlin/cluster.py index bc54c4aa4c..c7b3327152 100644 --- a/heat/engine/resources/openstack/senlin/cluster.py +++ b/heat/engine/resources/openstack/senlin/cluster.py @@ -44,10 +44,10 @@ class Cluster(res_base.BaseSenlinResource): ATTRIBUTES = ( ATTR_NAME, ATTR_METADATA, ATTR_NODES, ATTR_DESIRED_CAPACITY, - ATTR_MIN_SIZE, ATTR_MAX_SIZE, ATTR_POLICIES, + ATTR_MIN_SIZE, ATTR_MAX_SIZE, ATTR_POLICIES, ATTR_COLLECT, ) = ( "name", 'metadata', 'nodes', 'desired_capacity', - 'min_size', 'max_size', 'policies', + 'min_size', 'max_size', 'policies', 'collect', ) _POLICIES = ( @@ -176,6 +176,13 @@ class Cluster(res_base.BaseSenlinResource): type=attributes.Schema.LIST, support_status=support.SupportStatus(version='8.0.0'), ), + ATTR_COLLECT: attributes.Schema( + _("Attributes collected from cluster. According to the jsonpath " + "following this attribute, it will return a list of attributes " + "collected from the nodes of this cluster."), + type=attributes.Schema.LIST, + support_status=support.SupportStatus(version='8.0.0'), + ) } def translation_rules(self, props): @@ -368,6 +375,21 @@ class Cluster(res_base.BaseSenlinResource): } raise exception.StackValidationFailed(message=msg) + def get_attribute(self, key, *path): + if self.resource_id is None: + return None + + if key == self.ATTR_COLLECT: + if not path: + raise exception.InvalidTemplateAttribute( + resource=self.name, key=key) + attrs = self.client().collect_cluster_attrs( + self.resource_id, path[0]) + attr = [attr.attr_value for attr in attrs] + return attributes.select_from_attribute(attr, path[1:]) + else: + return super(Cluster, self).get_attribute(key, *path) + def _show_resource(self): cluster_dict = super(Cluster, self)._show_resource() cluster_dict[self.ATTR_POLICIES] = self.client().cluster_policies( diff --git a/heat/tests/openstack/senlin/test_cluster.py b/heat/tests/openstack/senlin/test_cluster.py index 52a148a22c..c24ce8ef47 100644 --- a/heat/tests/openstack/senlin/test_cluster.py +++ b/heat/tests/openstack/senlin/test_cluster.py @@ -302,6 +302,19 @@ class SenlinClusterTest(common.HeatTestCase): 'Went to status FAILED due to "Unknown"', six.text_type(exc)) + def test_cluster_get_attr_collect(self): + cluster = self._create_cluster(self.t) + self.senlin_mock.collect_cluster_attrs.return_value = [ + mock.Mock(attr_value='ip1')] + attr_path1 = ['details.addresses.private[0].addr'] + self.assertEqual( + ['ip1'], cluster.get_attribute(cluster.ATTR_COLLECT, *attr_path1)) + attr_path2 = ['details.addresses.private[0].addr', 0] + self.assertEqual( + 'ip1', cluster.get_attribute(cluster.ATTR_COLLECT, *attr_path2)) + self.senlin_mock.collect_cluster_attrs.assert_called_with( + cluster.resource_id, attr_path2[0]) + def test_cluster_resolve_attribute(self): excepted_show = { 'id': 'some_id',