clusterinfo
- Module Description
-
Setup
- Requirements
- Config File Layout
- Required Top Level Variables
-
Usage
- Keys in
clusterinfo
hiera and their sources
- Keys in
- Limitations
- Development
Module Description
clusterinfo
supplies a central source of information for several modules developed at ZIT-RLP. Configuration files are grouped by customer,
application, operation mode and cluster. The module supplies a custom hiera backend supplying nodes with their respective config, e.g. a database
server with all database parameters of all clusters in the DB server's operation mode.
A cluster in this context is a collection of nodes which provide different internal services in order to provide one user visible service, e.g. a web server, a database server and several application servers providing one web accessible application.
The module was originally developed to support HIS QIS and HISinOne.
Setup
Requirements
clusterinfo
needs those modules:
- puppetlabs-stdlib
- zitrlp-netinfo (similar module concerning network config)
The module accesses hiera data of other modules. The modules don't have to be installed, but the keys named in the
corresponding
clusterinfo
key must be filled in order to get data fromclusterinfo
.
Config File Layout
Config files are stored in ${CODEDIR}/environments/${ENVIRONMENT}/data/
, e.g. /etc/puppetlabs/code/environments/productions/data
. Inside this
directory, the following structure is expected:
+-- nodes
| +-- node1.yaml
| +-- node2.yaml
+-- cluster
+-- CUST
| +-- CUST_hs.yaml
| +-- some_app
| | +-- some_app_application.yaml
| | +-- NONPROD
| | | +-- CUST_opmode.yaml
| | | +-- CUSTTEST01.yaml
| | | +-- CUSTDEVL01.yaml
| | +-- PROD
| | +-- CUST_opmode.yaml
| | +-- CUSTPROD01.ymal
| +-- some_other_app
| +-- [...]
+-- OCST
+-- [...]
In this structure, these naming restrictions apply:
- Customers names are four upper case characters, e.g.
CUST
. - In the customer's directory,
${customer}_hs.yaml
, e.g.CUST_hs.yaml
, customer specific config is stored. - Application directories are stored within the customer directories. There is no restriction for the application name.
- Within the application directory,
${customer}_application.yaml
, e.g.CUST_application.yaml
contains application specific config. - Operation mode (opmode) config is stored in the respective application directory. Valid opmodes are
PROD
andNONPROD
. - In the opmode directory,
${customer}_opmode.yalm
, e.g.CUST_opmode.yaml
, contains opmode specific config. - Cluster configs are stored in their respective opmode directory. Their name starts with the customer name, followed by four upper
case characters ('stage') and two numbers ('nodenum'), e.g.
CUSTTEST01.yaml
. Node names must follow this scheme for some keys: - Application Servers:
#{customer}-#{application}-#{stage}-app-#{nodenum}.yaml
, all lower case - Required for
clusterinfo::web::node_clusternames
-
clusterinfo::web::worker_node_by_cluster
If these keys are not to be used, node naming is not restricted.
Required Top Level Variables
In order to select the cluster for a node, some variables must be supplied, e.g. by an external node classifier (ENC):
-
hs
(customer) application
opmode
nodenum
Usage
clusterinfo
works by collecting keys in all layers up to the cluster itself and constructing keys in the clusterinfo
namespace from them.
Keys
clusterinfo::bi_sql_tasks
@todo mha
Data Structure: Hash
{
$cluster => {
pre_sql_cron_term,
pre_sql_steps,
post_sql_cron_term,
post_sql_steps,
hiodb=>{
database,
user
},
eduetldb=>{
database,
user
}
}
}
Input Keys:
- hisinone::bi_update
- qisserver::dbconnections
Transformation:
clusterinfo::cluster_list
List of clusters in the current customer/application/opmode hierarchy.
Input Keys: none
Transformation: On iterating over the config directory, add each processed cluster to this list.
clusterinfo::database_list
List of databases.
Data Structure: Array of database names
Input Keys:
- zit_interface::dbconnections
- qisserver::dbconnections
Transformation: Merge of input keys, iteration over the result with $input for each DB connection: Put $input['database'] in Array, i.e. same as keys of clusterinfo::databases.
clusterinfo::databases
Databases with their corresponding owner.
Data Structure: Hash {database_name => owner, ...}
Input Keys:
- zit_interface::dbconnections
- qisserver::dbconnections
Transformation: Merge of input keys, iteration over the result with $input for each DB connection: $input['database'] is used as key, $input['user'] as value.
clusterinfo::database_with_schemas
Mapping of databases to their default schema, owner and connection name.
Data Structure: Hash { database_name => {schema, owner, connection_name}}
Input Keys:
- zit_interface::dbconnections
- qisserver::dbconnections
Transformation: Merge of input keys, iteration over the result with $input for each DB connection and $name for DB connection's name: Use $input['database'] as key, $input['user'] as owner and $name as connection_name. Map connection_name to schema:
database name | schema |
---|---|
hisinone | hisinone |
hisinone_audit | hisinone |
interface | interface |
clusterinfo::db_owner_roles
Users which own at least one database.
Data Structure: User resource: Hash { $username => { ensure => present, update_password => true, password_hash => $password, username => $username }}
Input Keys:
- zit_interface::dbconnections
- qisserver::dbconnections
Transformation: Merge of input keys, iteration over the result with $input for each DB connection: $input['user'] is used as $username, $input['password'] as $password. password_hash is generated as 'md5'+MD5_hex_digest(password+$user).
Assertions:
- Fail if a user occurs more than once with non-matching passwords.
clusterinfo::postgresql_admins
List of PostgreSQL admin users.
Data Structure: Hash, merge of customer, opmode, application and each cluster's zit_postgresql::admins
.
Input Keys:
- zit_postgresql::admins
Transformation:
Iterate over applying customer, application, opmode and contained clusters and merge each occurrence of zit_postgreqsl::admins
to result.
clusterinfo::postgresql_users
Data Structure: Hash, merge of customer, opmode, application and each cluster's zit_postgresql::users
with sanitized permissions
.
Input Keys:
- zit_postgresql::users
Transformation:
Iterate over applying customer, application, opmode and contained clusters and merge each occurrence of
zit_postgreqsl::users
to result. Additionally check if there is a permissions
key for each user. If so, apply
the according permission and remove key permissions
from the user:
permission |
key filled with all databases |
---|---|
connect | connect_dbs |
read | read_dbs |
write | write_dbs |
assertions:
- if
permissions
is set to an invalid value, fail with error.
clusterinfo::web::access_rules_services2
data structure: hash:
{
$cluster => "content of qisserver::access_rules_services2"
$cluster+$nodetype => "content of qisserver::access_rules_services2::$nodetype"
}
input keys:
- qisserver::access_rules_services2
transformation: merge qisserver::access_rules_services2 from customer/application/opmode and all applying clusters. If entries for additional node types exist, they are merged into the corresponding node type entry. Otherwise, the node type entry is a copy of the cluster entry.
clusterinfo::web::allow_ldap_groups
data structure: hash:
{
$cluster => "content of qisserver::access_rules_services2"
$cluster+$nodetype => "content of qisserver::access_rules_services2::$nodetype"
}
input keys:
- qisserver::access_rules_services2
transformation: merge qisserver::access_rules_services2 from customer/application/opmode and all applying clusters. If entries for additional node types exist, they are merged into the corresponding node type entry. Otherwise, the node type entry is a copy of the cluster entry.
clusterinfo::web::allow_nets
data structure: hash:
{
$cluster => "content of qisserver::allow_nets"
$cluster+$nodetype => "content of qisserver::allow_nets::$nodetype"
}
input keys:
- qisserver::allow_nets
transformation: merge qisserver::allow_nets from customer/application/opmode and all applying clusters. If entries for additional node types exist, they are merged into the corresponding node type entry. Otherwise, the node type entry is a copy of the cluster entry.
clusterinfo::web::allow_nets_regex
data structure: hash:
{
$cluster => "content of qisserver::allow_nets_regex"
$cluster+$nodetype => "content of qisserver::allow_nets_regex::$nodetype"
}
input keys:
- qisserver::allow_nets_regex
transformation: merge qisserver::allow_nets_regex from customer/application/opmode and all applying clusters. If entries for additional node types exist, they are merged into the corresponding node type entry. Otherwise, the node type entry is a copy of the cluster entry.
clusterinfo::web::cluster_url_host_overrides
data structure: hash:
{
$cluster => "content of qisserver::url_hostparts"
}
input keys:
- qisserver::url_hostparts
transformation: merge qisserver::url_hostparts from customer/application/opmode and all applying clusters.
clusterinfo::web::domains_by_cluster
data structure: hash:
{
$cluster => "content of qisserver::domains"
}
input keys:
- qisserver::domains
transformation: merge qisserver::domains from customer/application/opmode and all applying clusters.
clusterinfo::web::ignore_maintenance_nets
data structure: hash:
{
$cluster => "content of qisserver::ignore_maintenance_nets"
$cluster+$nodetype => "content of qisserver::ignore_maintenance_nets::$nodetype"
}
input keys:
- qisserver::ignore_maintenance_nets
transformation: merge qisserver::ignore_maintenance_nets from customer/application/opmode and all applying clusters. If entries for additional node types exist, they are merged into the corresponding node type entry. Otherwise, the node type entry is a copy of the cluster entry.
clusterinfo::web::ignore_maintenance_nets_regex
data structure: hash:
{
$cluster => "content of qisserver::ignore_maintenance_nets_regex"
$cluster+$nodetype => "content of qisserver::ignore_maintenance_nets_regex::$nodetype"
}
input keys:
- qisserver::ignore_maintenance_nets_regex
transformation: merge qisserver::ignore_maintenance_nets_regex from customer/application/opmode and all applying clusters. If entries for additional node types exist, they are merged into the corresponding node type entry. Otherwise, the node type entry is a copy of the cluster entry.
clusterinfo::web::node_clusternames
Data Structure: Hash:
{
nodename => cluster
}
Input Keys:
- qisserver::hsclustermap
Transformation: Iterate over all known clusters for this customer/application/opmode and build expected host name. Iterate over all node configs and add existing nodes to list.
clusterinfo::web::repos
Data Structure: Hash,
{
$cluster => $copy_of_zit_repo::branches,
$cluster+$nodetype => $copy_of_zit_repo::branches_of_cluster,
}
Input Keys:
- zit_repos::branches
Transformation: zit_repo::branches is copied to this key for each cluster. If a non NODE
-type node is
found, its cluster's zit_repo::branches is duplicated to the key $nodetype.
clusterinfo::web::shibboleth
Data Structure: Hash
{
default => config_hash,
cluster => {
$cluster1 => config_hash,
$cluster2 => config_hash,
...
},
odbc_used => (true|false),
defaultcluster => $cluster_name_of_default,
metadata_provider_config_files => [file1, file2,...],
metadata_provider_cert_files => [file1, file2,...]
}
`config_hash` contains these keys:
* entity_id
* application_id
* name
* key
* cert
and may contain:
* `entity_id_sso`
* `metadata_provider_uri`
* `metadata_provider_file_path`
* `metadata_provider_valid_until`
* `metadata_provider_cert_file`
* `default_application_id`
Input Keys:
- shibboleth
- clusterinfo::web::urls
Transformation:
- The
default
config is set to the merge of customer/application/opmode-lookups of keyshibboleth
. If there are any options which are also set by all clusters, they are removed from thedefault
config. - To fill the
clusters
key, all clusters for this customer/application/opmode are iterated:-
$fqdn
is either set toshibboleth/primary_fqdn
of present or to the firstsystem
entry of the current cluster's URL list (clusterinfo::web::urls
). - if
is_default
is true,application_id
is set to 'default', otherwiseapplication_id
is set to$fqdn
-
cert
is set to${fqdn}.cert.pem
-
entity_id
is set tohttps://${fqdn}/shibbo
-
key
is set to${fqdn}.key.pem
-
name
is set to$fqdn
- For each optional key listed above, the key is added to the cluster if it deviates from the default config,
otherwise it is omitted. If
metadata_provider_file_path
ormetadata_provider_cert_file
are encountered, the values are also added tometadata_provider_config_files
ormetadata_provider_cert_files
, respectively.
-
- If there is a cluster with
is_default
set, its name is stored indefaultcluster
. - If there is any cluster with
shibboleth/odbc_store
set,odbc_used
is set to true and the cluster'sshibbolet/odbc_store
is copied to the cluster's config in the result of this lookup. - If
shibbolet/additional_nodetypes
is set, the cluster's base config is copied tocluster/${cluster}${nodetype}. In this copy,
$fqdn` as used above is replaced by the additional node type's value. Assertions - If there are two clusters with
is_default==true
, the module fails with an according error.
clusterinfo::web::untrusted_domains_by_cluster
data structure: hash:
{
$cluster => "content of qisserver::untrusted_domains"
}
input keys:
- qisserver::untrusted_domains
transformation: merge qisserver::untrusted_domains from customer/application/opmode and all applying clusters.
clusterinfo::web::urls
Data Structure: Hash
{
$cluster => {
'system' => [url1, url2,...],
'untrusted'=> [url1, url2,...]
}
}
Input Keys:
- clusterinfo::web::worker_node_by_cluster
- qisserver::domains
- qisserver::nodetype_host_map
- qisserver::sysnameurlmap
- qisserver::untrusted_domains
- qisserver::url_hostparts
Transformation:
- If
qisserver::url_hostparts
contains values, use it as list of host-parts. Otherwise, use
information fromqisserver::sysnameurlmap
to build host parts. - Iterate over all domains in
qisserver::domains
and prepend host parts. Ifqisserver::sysnameurlmap
hasbasedomain_url==true
orqisserver::url_hostparts
containsGENERATE_BASEDOMAIN
, also generate a URL for the domain without a host part. Ifclusterinfo::web::worker_node_by_cluster
contains additional workers, i.e. application servers of Type ~= 'node', also generate URLs based onqisserver::nodetype_host_map
. URLs generated in this step are put into the 'system' part of the cluster's URL hash. - To generate the 'untrusted' part, use the same host parts generated above and create an entry for each domain
in
qisserver::untrusted_domains
. The list of untrusted domain for non-default node types is empty.
clusterinfo::web::worker_node_by_cluster
Map of load balance worker to worker and hostname for apache's mod_ajp.
Data Structure: Hash
{
lb_workername => {
worker => hostname
}
}
Input Keys:
- clusterinfo::web::node_clusternames
Transformation:
Iterade over clusterinfo::web::node_clusternames,
if node type is node
, the cluster name is used as lb_workername otherwise, lb_workername is set to
${clustername}${nodetype}
. Workers are added as ${clustername}${nodetype}${nodenum}
.
Limitations
- The module is only tested agains ZIT-RLP's ENC, available at https://software.service.zit-rlp.de.
- Parts of the module may work even without strictly following the naming scheme, for full functuallity, the naming scheme must be applied.