<html>
<head>
    <base href="https://wiki.asterisk.org/wiki">
            <link rel="stylesheet" href="/wiki/s/2042/1/7/_/styles/combined.css?spaceKey=TOP&amp;forWysiwyg=true" type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://wiki.asterisk.org/wiki/display/TOP/Configuration+Pattern">Configuration Pattern</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://wiki.asterisk.org/wiki/display/~jcolp">Joshua Colp</a>
    </h4>
        <br/>
                         <h4>Changes (9)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >h4. Groups <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >Groups contain different configuration items that apply to a single entity. This allow multiple instances of an item to be present with different values and for them to only apply to the specific entity they should. Some examples of groups would be a general group or a <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">group for</span> network <span class="diff-changed-words">configuration<span class="diff-added-chars"style="background-color: #dfd;"> group</span>.</span> <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">In the case of a network configuration group there may be multiple groups each relevant to a specific network configuration. One for IPv4, one for IPv6, etc. <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h4. Items <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Items are individual configurable items. An item class need not contain just one variable though, it can contain many. A configuration item MUST be added to a configuration group. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Items are individual configurable items. An item class need not contain just one variable though, it can contain many. Logically the variables should be associated with the item class though. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{note} <br>A configuration item MUST be added to a configuration group. It is not possible to have standalone configuration items. <br>{note} <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h3. Configuration Receiving <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >   class ExamplePresentItem extends ExampleConfigurationItem <br>   { <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">      bool enable; <br></td></tr>
            <tr><td class="diff-unchanged" >   }; <br>{code} <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >The needed group visitor code <span class="diff-added-words"style="background-color: #dfd;">for C++</span> would look like the following: <br></td></tr>
            <tr><td class="diff-unchanged" > <br>{code} <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >{code} <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >The needed item visitor code <span class="diff-added-words"style="background-color: #dfd;">for C++</span> would look like the following: <br></td></tr>
            <tr><td class="diff-unchanged" > <br>{code} <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>A simple python module is provided which provides the ability to configure a component from the command line. It requires minimal implementation to make it aware of how to configure the component. It is recommended that this be used for rapid development. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br>An example for the slice above is provided below: <br> <br>{code} <br>import Ice, Configurator, sys <br> <br>class ExampleSectionVisitors(Configurator.SectionVisitors): <br>        def visit_general(self, config, section): <br>                group = ExampleGeneralGroup() <br>                group.configurationItems = { } <br> <br>                mapper = Configurator.OptionMapper() <br>                mapper.map(&#39;enable&#39;, ExamplePresentItem(), &#39;enable&#39;, &#39;enable&#39;, config.getboolean, None) <br> <br>                for option in config.options(section): <br>                        mapper.execute(group, section, option) <br>                mapper.finish(group) <br> <br>                self.groups.append(group) <br> <br> <br>app = Configurator.ConfiguratorApp(&#39;Example.config&#39;, ExampleSectionVisitors()) <br>sys.exit(app.main(sys.argv)) <br>{code} <br> <br>Further information on the Configurator python module can be found [here|TOP:Configurator Python Module]. <br> <br>h4. Standalone <br> <br>Since the configuration interface is a defined interface there is no requirement to use the Configurator python module. Any supported Ice language can be used to construct configuration groups and items and send them to the component. <br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h3><a name="ConfigurationPattern-Overview"></a>Overview</h3>
<p>Component configuration in Asterisk SCF will follow a simple pattern. All major components will be designed to receive their configuration via an external interface defined by the component. The advantage of this approach is that it allows configuration implementations and services to evolve independently of each other, and allows developers tremendous flexibility in the tools and techniques used to perform configuration. A service need not concern itself with any details of the external process providing the configuration.  </p>

<h3><a name="ConfigurationPattern-ConfigurationPatternDesign"></a>Configuration Pattern Design</h3>
<p>The essence of the design, as stated in the Overview, is that configuration data is managed externally from the component. The component presents a component-specific occurrence of the Configuration Pattern in its Slice definitions. The external configuration process always pushes data to the component via the interfaces and types defined by the component being configured. </p>

<p>Calls to the setConfiguration() operation can be triggered by startup events, or whenever the configuration services detects (or is told) that the configuration data has changed. At startup, the configuration process could itself be configured to push configuration data to a given component via a name that can be found via the Service Locator. However, these are all suppositions outside the definition of this pattern. </p>

<p>As long as a configuration process can instantiate the Configuration Item types specific to a given component, and make calls to the component's Configuration interface, there are no other constraints placed on the configuration process itself. </p>

<h3><a name="ConfigurationPattern-ConfigurationInterface"></a>Configuration Interface</h3>

<p>A component using the configuration design is expected to implement and provide a proxy to the configuration interface. The interface provides the ability to push and pull the configuration. Since the ability to pull exists the component is also expected to store the current configuration as received. A current version of the interface can be viewed <a href="https://code.asterisk.org/code/browse/astscf-slice-release/AsteriskSCF/System/Component/ConfigurationIf.ice?hb=true" class="external-link" rel="nofollow">here</a>.</p>

<h3><a name="ConfigurationPattern-ConfigurationClasses"></a>Configuration Classes</h3>

<p>The configuration design provides two classes that can be extended and used: groups, and items.</p>

<h4><a name="ConfigurationPattern-Groups"></a>Groups</h4>

<p>Groups contain different configuration items that apply to a single entity. This allow multiple instances of an item to be present with different values and for them to only apply to the specific entity they should. Some examples of groups would be a general group or a network configuration group.</p>

<p>In the case of a network configuration group there may be multiple groups each relevant to a specific network configuration. One for IPv4, one for IPv6, etc.</p>

<h4><a name="ConfigurationPattern-Items"></a>Items</h4>

<p>Items are individual configurable items. An item class need not contain just one variable though, it can contain many. Logically the variables should be associated with the item class though.</p>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>A configuration item MUST be added to a configuration group. It is not possible to have standalone configuration items.</td></tr></table></div>

<h3><a name="ConfigurationPattern-ConfigurationReceiving"></a>Configuration Receiving</h3>

<p>The configuration design is implemented using the visitor plugin. This means that to handle incoming configuration groups and items a visitor needs to be implemented and each visited.</p>

<p>Given the following example slice:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
   local class ExampleConfigurationGroupVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationGroupVisitor
   {
   };
 
   ["visitor:ExampleConfigurationGroupVisitor"] class ExampleConfigurationGroup extends AsteriskSCF::System::Configuration::V1::ConfigurationGroup
   {
   };

   class ExampleGeneralGroup extends ExampleConfigurationGroup
   {
   };

   local class ExampleConfigurationItemVisitor extends AsteriskSCF::System::Configuration::V1::ConfigurationItemVisitor
   {
   };

   ["visitor:ExampleConfigurationItemVisitor"] class ExampleConfigurationItem extends AsteriskSCF::System::Configuration::V1::ConfigurationItem
   {
   };

   class ExamplePresentItem extends ExampleConfigurationItem
   {
      bool enable;
   };
]]></script>
</div></div>

<p>The needed group visitor code for C++ would look like the following:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
    class ExampleGroupVisitor : public ExampleConfigurationGroupVisitor
    {
    private:
        void visitExampleGeneralGroup(const ExampleGeneralGroupPtr&amp; group)
        {
        };
     };

    ExampleConfigurationGroupVisitorPtr v = new ExampleGroupVisitor();

    for (ConfigurationGroupSeq::const_iterator group = groups.begin(); group != groups.end(); ++group)
    {
        (*group)-&gt;visit(v);
    }
]]></script>
</div></div>

<p>The needed item visitor code for C++ would look like the following:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
    class ExampleItemVisitor : public ExampleConfigurationItemVisitor
    {
    private:
        void visitExamplePresentItem(const ExamplePresentItemPtr&amp; item)
        {
        };
     };

    ExampleConfigurationItemVisitorPtr v = new ExampleItemVisitor();

    for (ConfigurationItemDict::const_iterator item = group-&gt;configurationItems.begin();
         item != group-&gt;configurationItems.end();
         ++item)
    {
         (*item).second-&gt;visit(v);
    }
]]></script>
</div></div>

<h3><a name="ConfigurationPattern-ConfigurationSending"></a>Configuration Sending</h3>

<p>In order for configuration to be sent to a component the slice used to define the configuration groups and items must be made available to the configuring component. The configuring component must then create relevant groups and items and populate them with values. The groups should then be pushed to the component which will configure itself based on the contents.</p>

<h4><a name="ConfigurationPattern-Configurator"></a>Configurator</h4>

<p>A simple python module is provided which provides the ability to configure a component from the command line. It requires minimal implementation to make it aware of how to configure the component. It is recommended that this be used for rapid development.</p>

<p>An example for the slice above is provided below:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
import Ice, Configurator, sys

class ExampleSectionVisitors(Configurator.SectionVisitors):
        def visit_general(self, config, section):
                group = ExampleGeneralGroup()
                group.configurationItems = { }

                mapper = Configurator.OptionMapper()
                mapper.map('enable', ExamplePresentItem(), 'enable', 'enable', config.getboolean, None)

                for option in config.options(section):
                        mapper.execute(group, section, option)
                mapper.finish(group)

                self.groups.append(group)


app = Configurator.ConfiguratorApp('Example.config', ExampleSectionVisitors())
sys.exit(app.main(sys.argv))
]]></script>
</div></div>

<p>Further information on the Configurator python module can be found <a href="/wiki/display/TOP/Configurator+Python+Module" title="Configurator Python Module">here</a>.</p>

<h4><a name="ConfigurationPattern-Standalone"></a>Standalone</h4>

<p>Since the configuration interface is a defined interface there is no requirement to use the Configurator python module. Any supported Ice language can be used to construct configuration groups and items and send them to the component.</p>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://wiki.asterisk.org/wiki/users/viewnotifications.action" class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://wiki.asterisk.org/wiki/display/TOP/Configuration+Pattern">View Online</a>
        |
        <a href="https://wiki.asterisk.org/wiki/pages/diffpagesbyversion.action?pageId=4817009&revisedVersion=14&originalVersion=13">View Changes</a>
                |
        <a href="https://wiki.asterisk.org/wiki/display/TOP/Configuration+Pattern?showComments=true&amp;showCommentArea=true#addcomment">Add Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>