Unify common output keys across Heat templates

After this commit, all Heat templates have five common outputs:
* api_address: API endpoint of specific COE.
* kube_masters/swarm_master/mesos_master: Public IP address(es) of
  master node(s).
* kube_masters_private/swarm_master_private/mesos_master_private:
  Private IP address(es) of master node(s).
* kube_minions/swarm_nodes/mesos_slaves: List of public IP addresses
  of worker nodes.
* kube_minions_private/swarm_nodes_private/mesos_slaves_private:
  List of private IP addresses of worker nodes.

Change-Id: Ie44136dafa326db598a5f17978d89adce8e69801
Closes-Bug: #1514252
This commit is contained in:
Hongbin Lu 2015-11-08 18:24:26 -05:00
parent c603b300c8
commit 1b928008bd
9 changed files with 164 additions and 77 deletions

View File

@ -437,10 +437,14 @@ class AtomicK8sTemplateDefinition(BaseTemplateDefinition):
self.add_output('api_address', self.add_output('api_address',
bay_attr='api_address', bay_attr='api_address',
mapping_type=K8sApiAddressOutputMapping) mapping_type=K8sApiAddressOutputMapping)
self.add_output('kube_minions', self.add_output('kube_minions_private',
bay_attr=None) bay_attr=None)
self.add_output('kube_minions_external', self.add_output('kube_minions',
bay_attr='node_addresses') bay_attr='node_addresses')
self.add_output('kube_masters_private',
bay_attr=None)
self.add_output('kube_masters',
bay_attr='master_addresses')
def get_discovery_url(self, bay): def get_discovery_url(self, bay):
if hasattr(bay, 'discovery_url') and bay.discovery_url: if hasattr(bay, 'discovery_url') and bay.discovery_url:
@ -553,9 +557,15 @@ class AtomicSwarmTemplateDefinition(BaseTemplateDefinition):
self.add_parameter('tls_disabled', self.add_parameter('tls_disabled',
baymodel_attr='tls_disabled', baymodel_attr='tls_disabled',
required=True) required=True)
self.add_output('swarm_master', self.add_output('api_address',
bay_attr='api_address') bay_attr='api_address')
self.add_output('swarm_nodes_external', self.add_output('swarm_master_private',
bay_attr=None)
self.add_output('swarm_master',
bay_attr=None)
self.add_output('swarm_nodes_private',
bay_attr=None)
self.add_output('swarm_nodes',
bay_attr='node_addresses') bay_attr='node_addresses')
self.add_output('discovery_url', self.add_output('discovery_url',
bay_attr='discovery_url') bay_attr='discovery_url')
@ -620,8 +630,14 @@ class UbuntuMesosTemplateDefinition(BaseTemplateDefinition):
self.add_parameter('slave_flavor', self.add_parameter('slave_flavor',
baymodel_attr='flavor_id') baymodel_attr='flavor_id')
self.add_output('mesos_master', self.add_output('api_address',
bay_attr='api_address') bay_attr='api_address')
self.add_output('mesos_master_private',
bay_attr=None)
self.add_output('mesos_master',
bay_attr=None)
self.add_output('mesos_slaves_private',
bay_attr=None)
self.add_output('mesos_slaves', self.add_output('mesos_slaves',
bay_attr='node_addresses') bay_attr='node_addresses')

View File

@ -402,13 +402,19 @@ resources:
outputs: outputs:
api_address:
value: {get_attr: [swarm_master_floating, floating_ip_address]}
swarm_master_private:
value: {get_attr: [swarm_master_eth0, fixed_ips, 0, ip_address]}
swarm_master: swarm_master:
value: {get_attr: [swarm_master_floating, floating_ip_address]} value: {get_attr: [swarm_master_floating, floating_ip_address]}
swarm_nodes: swarm_nodes_private:
value: {get_attr: [swarm_nodes, swarm_node_ip]} value: {get_attr: [swarm_nodes, swarm_node_ip]}
swarm_nodes_external: swarm_nodes:
value: {get_attr: [swarm_nodes, swarm_node_external_ip]} value: {get_attr: [swarm_nodes, swarm_node_external_ip]}
discovery_url: discovery_url:

View File

@ -77,7 +77,7 @@ If you enable docker registry v2, you must provide values for:
You can get the ip address of the Kubernetes master using the `heat You can get the ip address of the Kubernetes master using the `heat
output-show` command: output-show` command:
$ heat output-show my-kube-cluster kube_master $ heat output-show my-kube-cluster kube_masters
"192.168.200.86" "192.168.200.86"
You can ssh into that server as the `minion` user: You can ssh into that server as the `minion` user:
@ -93,7 +93,7 @@ And once logged in you can run `kubectl`, etc:
You can log into your minions using the `minion` user as well. You You can log into your minions using the `minion` user as well. You
can get a list of minion addresses by running: can get a list of minion addresses by running:
$ heat output-show my-kube-cluster kube_minions_external $ heat output-show my-kube-cluster kube_minions
[ [
"192.168.200.182" "192.168.200.182"
] ]

View File

@ -225,11 +225,17 @@ resources:
outputs: outputs:
kube_master: api_address:
value: {get_attr: [kube_master, kube_master_external_ip]} value: {get_attr: [kube_master, kube_master_external_ip]}
kube_minions: kube_masters_private:
value: {get_attr: [kube_master, kube_master_ip]}
kube_masters:
value: {get_attr: [kube_master, kube_master_external_ip]}
kube_minions_private:
value: {get_attr: [kube_minions, kube_minion_ip]} value: {get_attr: [kube_minions, kube_minion_ip]}
kube_minions_external: kube_minions:
value: {get_attr: [kube_minions, kube_minion_external_ip]} value: {get_attr: [kube_minions, kube_minion_external_ip]}

View File

@ -162,11 +162,17 @@ resources:
outputs: outputs:
kube_master: api_address:
value: {get_attr: [kube_master, kube_master_external_ip]} value: {get_attr: [kube_master, kube_master_external_ip]}
kube_minions: kube_masters_private:
value: {get_attr: [kube_master, kube_master_ip]}
kube_masters:
value: {get_attr: [kube_master, kube_master_external_ip]}
kube_minions_private:
value: {get_attr: [kube_minions, kube_node_ip]} value: {get_attr: [kube_minions, kube_node_ip]}
kube_minions_external: kube_minions:
value: {get_attr: [kube_minions, kube_node_external_ip]} value: {get_attr: [kube_minions, kube_node_external_ip]}

View File

@ -493,18 +493,23 @@ outputs:
This is the url of docker registry server where you can store docker This is the url of docker registry server where you can store docker
images. images.
kube_masters_private:
value: {get_attr: [kube_masters, kube_master_ip]}
description: >
This is a list of the "private" addresses of all the Kubernetes masters.
kube_masters: kube_masters:
value: {get_attr: [kube_masters, kube_master_external_ip]} value: {get_attr: [kube_masters, kube_master_external_ip]}
description: > description: >
This is a list of "public" ip addresses of all Kubernetes master servers. This is a list of "public" ip addresses of all Kubernetes master servers.
Use these addresses to log in to the Kubernetes masters via ssh. Use these addresses to log in to the Kubernetes masters via ssh.
kube_minions: kube_minions_private:
value: {get_attr: [kube_minions, kube_minion_ip]} value: {get_attr: [kube_minions, kube_minion_ip]}
description: > description: >
This is a list of the "private" addresses of all the Kubernetes minions. This is a list of the "private" addresses of all the Kubernetes minions.
kube_minions_external: kube_minions:
value: {get_attr: [kube_minions, kube_minion_external_ip]} value: {get_attr: [kube_minions, kube_minion_external_ip]}
description: > description: >
This is a list of the "public" addresses of all the Kubernetes minions. Use This is a list of the "public" addresses of all the Kubernetes minions. Use

View File

@ -206,5 +206,8 @@ resources:
outputs: outputs:
kube_master_ip:
value: {get_attr: [kube_master, networks, private, 0]}
kube_master_external_ip: kube_master_external_ip:
value: {get_attr: [kube_master_floating, floating_ip_address]} value: {get_attr: [kube_master_floating, floating_ip_address]}

View File

@ -250,6 +250,12 @@ resources:
outputs: outputs:
api_address:
value: {get_attr: [mesos_master_floating, floating_ip_address]}
mesos_master_private:
value: {get_attr: [mesos_master_eth0, fixed_ips, 0, ip_address]}
mesos_master: mesos_master:
value: {get_attr: [mesos_master_floating, floating_ip_address]} value: {get_attr: [mesos_master_floating, floating_ip_address]}
description: > description: >
@ -257,6 +263,9 @@ outputs:
log in to the Mesos master via ssh or to access the Mesos API log in to the Mesos master via ssh or to access the Mesos API
from outside the cluster. from outside the cluster.
mesos_slaves_private:
value: {get_attr: [mesos_slaves, mesos_slave_ip]}
mesos_slaves: mesos_slaves:
value: {get_attr: [mesos_slaves, mesos_slave_external_ip]} value: {get_attr: [mesos_slaves, mesos_slave_external_ip]}
description: > description: >

View File

@ -153,32 +153,6 @@ class TemplateDefinitionTestCase(base.TestCase):
self.assertIn(mock_mapping_type.return_value, self.assertIn(mock_mapping_type.return_value,
definition.output_mappings) definition.output_mappings)
def test_update_outputs(self):
definition = tdef.TemplateDefinition.get_template_definition(
'vm',
'fedora-atomic',
'kubernetes')
expected_node_addresses = ['ex_minion', 'address']
outputs = [
{"output_value": expected_node_addresses,
"description": "No description given",
"output_key": "kube_minions_external"},
{"output_value": ['any', 'output'],
"description": "No description given",
"output_key": "kube_minions"}
]
mock_stack = mock.MagicMock()
mock_stack.outputs = outputs
mock_bay = mock.MagicMock()
mock_bay.api_address = None
mock_baymodel = mock.MagicMock()
definition.update_outputs(mock_stack, mock_baymodel, mock_bay)
self.assertEqual(expected_node_addresses, mock_bay.node_addresses)
class AtomicK8sTemplateDefinitionTestCase(base.TestCase): class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
@ -328,65 +302,61 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
fake_bay) fake_bay)
def test_update_outputs_api_address(self): def test_update_outputs_api_address(self):
definition = tdef.TemplateDefinition.get_template_definition( self._test_update_outputs(tls_disabled=True,
'vm', expected_protocol='http',
'fedora-atomic', expected_port='8080')
'kubernetes')
address = 'updated_address'
protocol = 'http'
port = '8080'
params = {
'protocol': protocol,
'address': address,
'port': port,
}
expected_api_address = '%(protocol)s://%(address)s:%(port)s' % params
outputs = [
{"output_value": address,
"description": "No description given",
"output_key": "api_address"},
]
mock_stack = mock.MagicMock()
mock_stack.outputs = outputs
mock_bay = mock.MagicMock()
mock_baymodel = mock.MagicMock()
mock_baymodel.tls_disabled = True
definition.update_outputs(mock_stack, mock_baymodel, mock_bay)
self.assertEqual(expected_api_address, mock_bay.api_address)
def test_update_outputs_if_baymodel_is_secure(self): def test_update_outputs_if_baymodel_is_secure(self):
self._test_update_outputs(tls_disabled=False,
expected_protocol='https',
expected_port='6443')
def _test_update_outputs(self, tls_disabled, expected_protocol,
expected_port):
definition = tdef.TemplateDefinition.get_template_definition( definition = tdef.TemplateDefinition.get_template_definition(
'vm', 'vm',
'fedora-atomic', 'fedora-atomic',
'kubernetes') 'kubernetes')
address = 'updated_address' address = 'updated_address'
protocol = 'https'
port = '6443'
params = { params = {
'protocol': protocol, 'protocol': expected_protocol,
'address': address, 'address': address,
'port': port, 'port': expected_port,
} }
expected_api_address = '%(protocol)s://%(address)s:%(port)s' % params expected_api_address = '%(protocol)s://%(address)s:%(port)s' % params
expected_master_addresses = ['ex_master', 'address']
expected_node_addresses = ['ex_minion', 'address']
outputs = [ outputs = [
{"output_value": address, {"output_value": address,
"description": "No description given", "description": "No description given",
"output_key": "api_address"}, "output_key": "api_address"},
{"output_value": ['any', 'output'],
"description": "No description given",
"output_key": "kube_masters_private"},
{"output_value": expected_master_addresses,
"description": "No description given",
"output_key": "kube_masters"},
{"output_value": ['any', 'output'],
"description": "No description given",
"output_key": "kube_minions_private"},
{"output_value": expected_node_addresses,
"description": "No description given",
"output_key": "kube_minions"},
] ]
mock_stack = mock.MagicMock() mock_stack = mock.MagicMock()
mock_stack.outputs = outputs mock_stack.outputs = outputs
mock_bay = mock.MagicMock() mock_bay = mock.MagicMock()
mock_baymodel = mock.MagicMock() mock_baymodel = mock.MagicMock()
mock_baymodel.tls_disabled = False mock_baymodel.tls_disabled = tls_disabled
definition.update_outputs(mock_stack, mock_baymodel, mock_bay) definition.update_outputs(mock_stack, mock_baymodel, mock_bay)
self.assertEqual(expected_api_address, mock_bay.api_address) self.assertEqual(expected_api_address, mock_bay.api_address)
self.assertEqual(expected_master_addresses, mock_bay.master_addresses)
self.assertEqual(expected_node_addresses, mock_bay.node_addresses)
class AtomicSwarmTemplateDefinitionTestCase(base.TestCase): class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
@ -455,6 +425,39 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
heat_param = swarm_def.get_heat_param(bay_attr='node_count') heat_param = swarm_def.get_heat_param(bay_attr='node_count')
self.assertEqual('number_of_nodes', heat_param) self.assertEqual('number_of_nodes', heat_param)
def test_update_outputs(self):
swarm_def = tdef.AtomicSwarmTemplateDefinition()
expected_api_address = 'updated_address'
expected_node_addresses = ['ex_minion', 'address']
outputs = [
{"output_value": expected_api_address,
"description": "No description given",
"output_key": "api_address"},
{"output_value": ['any', 'output'],
"description": "No description given",
"output_key": "swarm_master_private"},
{"output_value": ['any', 'output'],
"description": "No description given",
"output_key": "swarm_master"},
{"output_value": ['any', 'output'],
"description": "No description given",
"output_key": "swarm_nodes_private"},
{"output_value": expected_node_addresses,
"description": "No description given",
"output_key": "swarm_nodes"},
]
mock_stack = mock.MagicMock()
mock_stack.outputs = outputs
mock_bay = mock.MagicMock()
mock_baymodel = mock.MagicMock()
swarm_def.update_outputs(mock_stack, mock_baymodel, mock_bay)
self.assertEqual(expected_api_address, mock_bay.api_address)
self.assertEqual(expected_node_addresses, mock_bay.node_addresses)
class UbuntuMesosTemplateDefinitionTestCase(base.TestCase): class UbuntuMesosTemplateDefinitionTestCase(base.TestCase):
@ -463,3 +466,36 @@ class UbuntuMesosTemplateDefinitionTestCase(base.TestCase):
heat_param = mesos_def.get_heat_param(bay_attr='node_count') heat_param = mesos_def.get_heat_param(bay_attr='node_count')
self.assertEqual('number_of_slaves', heat_param) self.assertEqual('number_of_slaves', heat_param)
def test_update_outputs(self):
mesos_def = tdef.UbuntuMesosTemplateDefinition()
expected_api_address = 'updated_address'
expected_node_addresses = ['ex_minion', 'address']
outputs = [
{"output_value": expected_api_address,
"description": "No description given",
"output_key": "api_address"},
{"output_value": ['any', 'output'],
"description": "No description given",
"output_key": "mesos_master_private"},
{"output_value": ['any', 'output'],
"description": "No description given",
"output_key": "mesos_master"},
{"output_value": ['any', 'output'],
"description": "No description given",
"output_key": "mesos_slaves_private"},
{"output_value": expected_node_addresses,
"description": "No description given",
"output_key": "mesos_slaves"},
]
mock_stack = mock.MagicMock()
mock_stack.outputs = outputs
mock_bay = mock.MagicMock()
mock_baymodel = mock.MagicMock()
mesos_def.update_outputs(mock_stack, mock_baymodel, mock_bay)
self.assertEqual(expected_api_address, mock_bay.api_address)
self.assertEqual(expected_node_addresses, mock_bay.node_addresses)