Configuration Values¶
Config value key names must match the regex:
^[<>\-~]?[a-zA-Z0-9][a-zA-Z0-9_\-]*(:[a-zA-Z0-9]+)?$
If the first character is: (processed in this order)
-: remove from the value so far <nothing>: overlay/replace value so far with new value <: prepend to the value so far (same affect as append on dict/maps) >: append to the value so far ~: mask out/hide value so far, (NOTE: value is ignored)
If :[a-zA-Z0-9]+ is present, the value key/value is only applied if the class (the part that comes after the ‘:’) matches the classes indicated by the foundation. This is the _foundation_class_list.
Global and Config Attributes¶
To help indicate Attributes and to keep them from getting overwritten by config values ( config values are not allowed to start with _ ), Global attributes begin with __ and other attributes begin with _. Attributes also do not follow the value combining rules, as they are set internally. They are also not affected by config classes.
Value Merging¶
Config values are merged using Jinja2. They are merged together as a final step before outputting and before merging with a PXE or Boot template.
For documentation on Jina2 see http://jinja.pocoo.org/
For example:
root_zone: 'myservice.com'
dns_search: [ 'site1.{{ root_zone }}', '{{ root_zone }}' ]
dns_zone: 'site1.{{ root_zone }}'
Becomes:
root_zone: 'myservice.com'
dns_search: [ 'site1.myservice.com', 'myservice.com' ]
dns_zone: 'site1.myservice.com'
Jinja filters can be used:
dns_search: [ 'site1.{{ root_zone|default(\'.test\') }}', '{{ root_zone|default(\'.test\') }}' ]
dns_zone: 'site1.{{ root_zone|default(\'.test\') }}'
Becomes:
dns_search: [ 'site1..test', '.test' ]
dns_zone: 'site1..test'
NOTE: There is not sorting nor predictable order, be careful when embeding/referencing, you may get random results. A second (or more) evaluation round can be forced by escaping the ‘{{‘ ie:
{ 'a': 'c', 'b': 'a', 'd': '{{ "{{" }}{{b}}}}' }
the result will be:
{ 'a': 'c', 'b': 'a', 'd': 'c' }
Value Overlay Rules¶
For Site and BluePrint, the values of the parents are overlaid by the children.
Sources of Configuration Values¶
In general the order is blueprint, attributes, config values, and global attributes
- For a Site
- Parents in order from parent to child Target Site config values Global attribute values
- For a Foundation
- Foundation’s BluePrint (with its parents applied) Foundation’s attribute values (including values from a complex, if Foundation belongs to a complex) Site (with its parents applied) Global attribute values
- For a Structure
Structures’s BluePrint (with its parents applied) Foundation’s attribute values Site (with its parents applied) Structure’s attribute values Structure’s config_values Global attribute values
NOTE: the Foundation’s BluePrint values are NOT used, these are only for the physical provisioning of the Foundation, ie: BIOS settings, the Structure can specify values for the Foundation by which FoundationBluePrints the Structure BluePrint supports
NOTE2: also includes the complex values, if the foundation belongs to a complex
- NOTE:
- Site configs are applied from the top most parent down with the child overlaying the parent. BluePrint configs are applied Top down, and across each layer, the order of siblings is not predictable. BluePrint scripts are searched BFS (Breadth First Search), the order of siblings is not predictable.
Attribute Values¶
These values start with _ and are not overlayable/modifyable by config_Values. These values are attributes of the structure/foundation/complex, such as the structure/foundation/complex id, _structure_config_uuid, _structure_hostname, structure/foundation/complex state.
Global attribute values¶
These values start with __ and are not overlayable/modifyable by config_values. These values are things that are global to this install of Contractor, such as the base url to use to contact it. __last_modified is also added, which is the timestamp of the most recent modification date to any of the sources of configuration information.
Example¶
NOTE: for the following examples the ip address attributes and global attributes are ommited.
Let’s start with a Site with the following values:
+-------------------------------------------+
| |
| dns_servers: [ '10.0.0.20', '10.0.0.21' ] |
| dns_search: [ 'myservice.com' ] |
| dns_zone: 'myservice.com' |
| |
+-------------------------------------------+
Nice and simple. This Example is mostly going to deal with dns, but the config vaules can be used for just about anything.
Let’s add a Foundation and Structure (NOTE: the Foundation and Structure provide more attribute values than what is shown):
+-------------------------------------------+
| |
| dns_servers: [ '10.0.0.20', '10.0.0.21' ] |
| dns_search: [ 'myservice.com' ] |
| dns_zone: 'myservice.com' |
| |
| +----------------------+ |
| | | |
| | Structure: | |
| | Hostname: web1 | |
| | | |
| +----------+-----------+ |
| | |
| +----------+-----------+ |
| | | |
| | Foundation: | |
| | Locator: d2r050u20 | |
| | | |
| +----------------------+ |
| |
+-------------------------------------------+
Now if we get the config values for the structure, its resulting config values would be.
dns_servers: [ ‘10.0.0.20’, ‘10.0.0.21’ ] dns_search: [ ‘myservice.com’ ] dns_zone: ‘myservice.com’ _foundation_locator: ‘d2r050u20’ _structure_hostname: ‘web1’
One last thing we forgot, the blueprints:
+-------------------------------------------+
| |
| dns_servers: [ '10.0.0.20', '10.0.0.21' ] |
| dns_search: [ 'myservice.com' ] |
| dns_zone: 'myservice.com' | +----------------------------------------------------------------------+
| | | |
| +----------------------+ | | Web Server Structure BluePrint: |
| | +-----------------------+ distro: 'xenial' |
| | Structure: | | | extra_packages: [ 'apache2', 'python-django', 'postgres-server' ] |
| | Hostname: 'web1' | | | |
| | | | +----------------------------------------------------------------------+
| +----------+-----------+ |
| | | +----------------------------------------------------------------------+
| +----------+-------------+ | | |
| | +---------------------+ Small VM Foundation BluePrint: |
| | Foundation: | | | cpu_count: 2 |
| | Locator: 'd2r050u20' | | | memory: 1024 |
| | | | | |
| +------------------------+ | +----------------------------------------------------------------------+
| |
+-------------------------------------------+
There we go, now the Structures Config Values are:
dns_servers: [ '10.0.0.20', '10.0.0.21' ]
dns_search: [ 'myservice.com' ]
dns_zone: 'myservice.com'
distro: 'xenial'
extra_packages: [ 'apache2', 'python-django', 'postgres-server' ]
_foundation_locator: 'd2r050u20'
_structure_hostname: 'web1'
And the Foundation’s Config Values are:
dns_servers: [ '10.0.0.20', '10.0.0.21' ]
dns_search: [ 'myservice.com' ]
dns_zone: 'myservice.com'
cou_count: 2
memory: 1024
_foundation_locator: 'd2r050u20'
Everything was fine until our web site got busy, time to expand. First let’s move our server to a sub-site and create another sub-site with its own web server:
+----------------------------------------------------------------------------------------------+
| |
| dns_servers: [ '10.0.0.20', '10.0.0.21' ] |
| dns_search: [ 'myservice.com' ] |
| dns_zone: 'myservice.com' |
| |
| +-------------------------------------------+ +-------------------------------------------+ |
| | | | | |
| | {dns_search: [ 'site1.myservice.com' ] | | {dns_search: [ 'site2.myservice.com' ] | |
| | dns_zone: 'site1.myservice.com | | dns_zone: 'site2.myservice.com | | +----------------------------------------------------------------------+
| | | | | | | |
| | +----------------------+ | | +----------------------+ | | | Web Server Structure BluePrint: |
| | | +-----------------------+ +------------------------+ distro: 'xenial' |
| | | Structure: | | | | Structure: | | | | extra_packages: [ 'apache2', 'python-django', 'postgres-server' ] |
| | | Hostname: 'web1' | | | | Hostname: 'web1' | | | | |
| | | | | | | | | | +----------------------------------------------------------------------+
| | +----------+-----------+ | | +----------+-----------+ | |
| | | | | | | | +----------------------------------------------------------------------+
| | +----------+-------------+ | | +----------+-------------+ | | | |
| | | +---------------------+ +----------------------+ Small VM Foundation BluePrint: |
| | | Foundation: | | | | Foundation: | | | | cpu_count: 2 |
| | | Locator: 'd2r050u20' | | | | Locator: 'd2r020u20' | | | | memory: 1024 |
| | | | | | | | | | | |
| | +------------------------+ | | +------------------------+ | | +----------------------------------------------------------------------+
| | | | | |
| +-------------------------------------------+ +-------------------------------------------+ |
| |
+----------------------------------------------------------------------------------------------+
Nice, now we can handle the load. Site 1’s Structure is now:
dns_servers: [ '10.0.0.20', '10.0.0.21' ]
dns_search: [ 'site1.myservice.com', 'myservice.com' ]
dns_zone: 'site1.myservice.com'
distro: 'xenial'
extra_packages: [ 'apache2', 'python-django', 'postgres-server' ]
_foundation_locator: 'd2r050u20'
_structure_hostname: 'web1'
And Site 2’s Structure is:
dns_servers: [ '10.0.0.20', '10.0.0.21' ]
dns_search: [ 'site2.myservice.com', 'myservice.com' ]
dns_zone: 'site2.myservice.com'
distro: 'xenial'
extra_packages: [ 'apache2', 'python-django', 'postgres-server' ]
_foundation_locator: 'd2r020u20'
_structure_hostname: 'web1'
At some point in the future we add another DNS server, we can add it to the top level and it will propagate to everything automatically. Actually a better DNS design would be to add dns servers to Site 1 and Site 2 and prepend those to the dns server list. Also if we want another global dns search zone to come after ‘myservice.com’, we can add it to the list at the top, and once again it will propagate for us. If there is a site that you do not want to inherit the top level dns_search, you would omit the < from the name, and the value will overwrite instead of pre-pend.