summaryrefslogtreecommitdiffstats
path: root/docker/services/containers-common.yaml
blob: 973d99945b9289ea1e092c83c7f45523cf85a59b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
heat_template_version: pike

description: >
  Contains a static list of common things necessary for containers

outputs:
  volumes:
    description: Common volumes for the containers.
    value:
      - /etc/hosts:/etc/hosts:ro
      - /etc/localtime:/etc/localtime:ro
      # required for bootstrap_host_exec
      - /etc/puppet:/etc/puppet:ro
      # OpenSSL trusted CAs
      - /etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro
      - /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro
      - /etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro
      - /etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro
      # Syslog socket
      - /dev/log:/dev/log
      - /etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro
e.Exception */ .highlight .nf { color: #a6e22e } /* Name.Function */ .highlight .nl { color: #f8f8f2 } /* Name.Label */ .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ .highlight .nx { color: #a6e22e } /* Name.Other */ .highlight .py { color: #f8f8f2 } /* Name.Property */ .highlight .nt { color: #f92672 } /* Name.Tag */ .highlight .nv { color: #f8f8f2 } /* Name.Variable */ .highlight .ow { color: #f92672 } /* Operator.Word */ .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
#    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 os

from toscaparser.common import exception
from toscaparser.substitution_mappings import SubstitutionMappings
from toscaparser.tests.base import TestCase
from toscaparser.topology_template import TopologyTemplate
from toscaparser.tosca_template import ToscaTemplate
from toscaparser.utils.gettextutils import _
import toscaparser.utils.yamlparser

YAML_LOADER = toscaparser.utils.yamlparser.load_yaml


class TopologyTemplateTest(TestCase):

    def setUp(self):
        TestCase.setUp(self)
        '''TOSCA template.'''
        self.tosca_tpl_path = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "data/topology_template/transactionsubsystem.yaml")
        self.tpl = YAML_LOADER(self.tosca_tpl_path)
        self.topo_tpl = self.tpl.get('topology_template')
        self.imports = self.tpl.get('imports')
        self.topo = TopologyTemplate(self.topo_tpl,
                                     self._get_all_custom_def())

    def _get_custom_def(self, type_definition):
        custom_defs = {}
        for definition in self.imports:
            if os.path.isabs(definition):
                def_file = definition
            else:
                tpl_dir = os.path.dirname(os.path.abspath(self.tosca_tpl_path))
                def_file = os.path.join(tpl_dir, definition)
            custom_type = YAML_LOADER(def_file)
            custom_defs.update(custom_type.get(type_definition))
        return custom_defs

    def _get_all_custom_def(self):
        custom_defs = {}
        custom_defs.update(self._get_custom_def('node_types'))
        custom_defs.update(self._get_custom_def('capability_types'))
        return custom_defs

    def _get_custom_types(self):
        custom_types = {}
        def_file = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "data/topology_template/definitions.yaml")
        custom_type = YAML_LOADER(def_file)
        node_types = custom_type['node_types']
        for name in node_types:
            defintion = node_types[name]
            custom_types[name] = defintion
        return custom_types

    def test_description(self):
        expected_desc = 'Template of a database including its hosting stack.'
        self.assertEqual(expected_desc, self.topo.description)

    def test_inputs(self):
        self.assertEqual(
            ['mq_server_ip', 'my_cpus', 'receiver_port'],
            sorted([input.name for input in self.topo.inputs]))

        input_name = "receiver_port"
        expected_description = "Port to be used for receiving messages."
        for input in self.topo.inputs:
            if input.name == input_name:
                self.assertEqual(expected_description, input.description)

    def test_node_tpls(self):
        '''Test nodetemplate names.'''
        self.assertEqual(
            ['app', 'server', 'websrv'],
            sorted([tpl.name for tpl in self.topo.nodetemplates]))

        tpl_name = "app"
        expected_type = "example.SomeApp"
        expected_properties = ['admin_user', 'pool_size']
        expected_capabilities = ['app_endpoint', 'feature', 'message_receiver']
        expected_requirements = [{'host': {'node': 'websrv'}}]
        expected_relationshp = ['tosca.relationships.HostedOn']
        expected_host = ['websrv']
        for tpl in self.topo.nodetemplates:
            if tpl_name == tpl.name:
                '''Test node type.'''
                self.assertEqual(tpl.type, expected_type)

                '''Test properties.'''
                self.assertEqual(
                    expected_properties,
                    sorted(tpl.get_properties().keys()))

                '''Test capabilities.'''
                self.assertEqual(
                    expected_capabilities,
                    sorted(tpl.get_capabilities().keys()))

                '''Test requirements.'''
                self.assertEqual(
                    expected_requirements, tpl.requirements)

                '''Test relationship.'''
                ''' TODO : skip tempororily. need to fix it
                '''
                self.assertEqual(
                    expected_relationshp,
                    [x.type for x in tpl.relationships.keys()])
                self.assertEqual(
                    expected_host,
                    [y.name for y in tpl.relationships.values()])
                '''Test interfaces.'''
                # TODO(hurf) add interface test when new template is available

            if tpl.name == 'server':
                '''Test property value'''
                props = tpl.get_properties()
                if props and 'mem_size' in props.keys():
                    self.assertEqual(props['mem_size'].value, '4096 MB')
                '''Test capability'''
                caps = tpl.get_capabilities()
                self.assertIn('os', caps.keys())
                os_props_objs = None
                os_props = None
                os_type_prop = None
                if caps and 'os' in caps.keys():
                    capability = caps['os']
                    os_props_objs = capability.get_properties_objects()
                    os_props = capability.get_properties()
                    os_type_prop = capability.get_property_value('type')
                    break
                self.assertEqual(
                    ['Linux'],
                    [p.value for p in os_props_objs if p.name == 'type'])
                self.assertEqual(
                    'Linux',
                    os_props['type'].value if 'type' in os_props else '')
                self.assertEqual('Linux', os_props['type'].value)
                self.assertEqual('Linux', os_type_prop)

    def test_outputs(self):
        self.assertEqual(
            sorted(['receiver_ip', 'receiver_port']),
            sorted([output.name for output in self.topo.outputs]))

    def test_groups(self):
        group = self.topo.groups[0]
        self.assertEqual('webserver_group', group.name)
        self.assertEqual(['websrv', 'server'], group.members)
        for node in group.get_member_nodes():
            if node.name == 'server':
                '''Test property value'''
                props = node.get_properties()
                if props and 'mem_size' in props.keys():
                    self.assertEqual(props['mem_size'].value, '4096 MB')

    def test_system_template(self):
        tpl_path = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "data/topology_template/system.yaml")
        system_tosca_template = ToscaTemplate(tpl_path)
        self.assertIsNotNone(system_tosca_template)
        self.assertEqual(
            len(system_tosca_template.
                nested_tosca_templates_with_topology), 4)
        self.assertTrue(system_tosca_template.has_nested_templates())

    def test_invalid_keyname(self):
        tpl_snippet = '''
        substitution_mappings:
          node_type: example.DatabaseSubsystem
          capabilities:
            database_endpoint: [ db_app, database_endpoint ]
          requirements:
            receiver1: [ tran_app, receiver1 ]
          invalid_key: 123
        '''
        sub_mappings = (toscaparser.utils.yamlparser.
                        simple_parse(tpl_snippet))['substitution_mappings']
        expected_message = _(
            'SubstitutionMappings contains unknown field '
            '"invalid_key". Refer to the definition '
            'to verify valid values.')
        err = self.assertRaises(
            exception.UnknownFieldError,
            lambda: SubstitutionMappings(sub_mappings, None, None,
                                         None, None, None))
        self.assertEqual(expected_message, err.__str__())

    def test_missing_required_keyname(self):
        tpl_snippet = '''
        substitution_mappings:
          capabilities:
            database_endpoint: [ db_app, database_endpoint ]
          requirements:
            receiver1: [ tran_app, receiver1 ]
        '''
        sub_mappings = (toscaparser.utils.yamlparser.
                        simple_parse(tpl_snippet))['substitution_mappings']
        expected_message = _('SubstitutionMappings used in topology_template '
                             'is missing required field "node_type".')
        err = self.assertRaises(
            exception.MissingRequiredFieldError,
            lambda: SubstitutionMappings(sub_mappings, None, None,
                                         None, None, None))
        self.assertEqual(expected_message, err.__str__())

    def test_invalid_nodetype(self):
        tpl_snippet = '''
        substitution_mappings:
          node_type: example.DatabaseSubsystem1
          capabilities:
            database_endpoint: [ db_app, database_endpoint ]
          requirements:
            receiver1: [ tran_app, receiver1 ]
        '''
        sub_mappings = (toscaparser.utils.yamlparser.
                        simple_parse(tpl_snippet))['substitution_mappings']
        custom_defs = self._get_custom_types()
        expected_message = _('Node type "example.DatabaseSubsystem1" '
                             'is not a valid type.')
        err = self.assertRaises(
            exception.InvalidNodeTypeError,
            lambda: SubstitutionMappings(sub_mappings, None, None,
                                         None, None, custom_defs))
        self.assertEqual(expected_message, err.__str__())

    def test_system_with_input_validation(self):
        tpl_path0 = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "data/topology_template/validate/system_invalid_input.yaml")
        tpl_path1 = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "data/topology_template/validate/"
            "queuingsubsystem_invalid_input.yaml")
        errormsg = _('SubstitutionMappings with node_type '
                     'example.QueuingSubsystem is missing '
                     'required input definition of input "server_port".')

        # It's invalid in nested template.
        self.assertRaises(exception.ValidationError,
                          lambda: ToscaTemplate(tpl_path0))
        exception.ExceptionCollector.assertExceptionMessage(
            exception.MissingRequiredInputError, errormsg)

        # Subtemplate deploy standaolone is also invalid.
        self.assertRaises(exception.ValidationError,
                          lambda: ToscaTemplate(tpl_path1))
        exception.ExceptionCollector.assertExceptionMessage(
            exception.MissingRequiredInputError, errormsg)

    def test_system_with_unknown_output_validation(self):
        tpl_path0 = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "data/topology_template/validate/"
            "system_invalid_unknown_output.yaml")
        tpl_path1 = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "data/topology_template/validate/"
            "transactionsubsystem_invalid_unknown_output.yaml")
        errormsg = _('Unknown output "my_cpu_output" in SubstitutionMappings '
                     'with node_type example.TransactionSubsystem.')

        # It's invalid in nested template.
        self.assertRaises(exception.ValidationError,
                          lambda: ToscaTemplate(tpl_path0))
        exception.ExceptionCollector.assertExceptionMessage(
            exception.UnknownOutputError, errormsg)

        # Subtemplate deploy standaolone is invalid.
        self.assertRaises(exception.ValidationError,
                          lambda: ToscaTemplate(tpl_path1))
        exception.ExceptionCollector.assertExceptionMessage(
            exception.UnknownOutputError, errormsg)

    def test_system_with_missing_output_validation(self):
        tpl_path0 = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "data/topology_template/validate/"
            "system_invalid_missing_output.yaml")
        tpl_path1 = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "data/topology_template/validate/"
            "transactionsubsystem_invalid_missing_output.yaml")
        errormsg = _('SubstitutionMappings with node_type '
                     'example.TransactionSubsystem is missing '
                     'required output definition of output "receiver_port".')

        # It's invalid in nested template.
        self.assertRaises(exception.ValidationError,
                          lambda: ToscaTemplate(tpl_path0))
        exception.ExceptionCollector.assertExceptionMessage(
            exception.MissingRequiredOutputError, errormsg)

        # Subtemplate deploy standaolone is invalid.
        self.assertRaises(exception.ValidationError,
                          lambda: ToscaTemplate(tpl_path1))
        exception.ExceptionCollector.assertExceptionMessage(
            exception.MissingRequiredOutputError, errormsg)