Browse Source

Initial commit.

master
Alexander Thaller 1 year ago
commit
66b458c1e3
61 changed files with 9785 additions and 0 deletions
  1. +5
    -0
      LICENSE
  2. +3
    -0
      README.md
  3. +80
    -0
      _book/Docs/RFCs/SALT1-role_metadata.md
  4. +184
    -0
      _book/Docs/RFCs/SALT2-realm_naming.md
  5. +80
    -0
      _book/Docs/RFCs/salt1-role_metadata.md
  6. +184
    -0
      _book/Docs/RFCs/salt2-realm_naming.md
  7. +745
    -0
      _book/Docs/STRUCTURE.adoc
  8. +1495
    -0
      _book/Docs/Structure.html
  9. +376
    -0
      _book/Docs/Tools.html
  10. +376
    -0
      _book/Docs/index.html
  11. +80
    -0
      _book/Docs/rfcs/salt1-role_metadata.md
  12. +184
    -0
      _book/Docs/rfcs/salt2-realm_naming.md
  13. +8
    -0
      _book/Docs/tools.md
  14. +8
    -0
      _book/Docs/tools/README.md
  15. +80
    -0
      _book/Docs/tools/serinus.md
  16. BIN
      _book/gitbook/fonts/fontawesome/FontAwesome.otf
  17. BIN
      _book/gitbook/fonts/fontawesome/fontawesome-webfont.eot
  18. +685
    -0
      _book/gitbook/fonts/fontawesome/fontawesome-webfont.svg
  19. BIN
      _book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf
  20. BIN
      _book/gitbook/fonts/fontawesome/fontawesome-webfont.woff
  21. BIN
      _book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2
  22. +240
    -0
      _book/gitbook/gitbook-plugin-fontsettings/fontsettings.js
  23. +291
    -0
      _book/gitbook/gitbook-plugin-fontsettings/website.css
  24. +135
    -0
      _book/gitbook/gitbook-plugin-highlight/ebook.css
  25. +434
    -0
      _book/gitbook/gitbook-plugin-highlight/website.css
  26. +7
    -0
      _book/gitbook/gitbook-plugin-lunr/lunr.min.js
  27. +59
    -0
      _book/gitbook/gitbook-plugin-lunr/search-lunr.js
  28. +6
    -0
      _book/gitbook/gitbook-plugin-page-toc/anchor-3.1.1.min.js
  29. +25
    -0
      _book/gitbook/gitbook-plugin-page-toc/page-toc.css
  30. +81
    -0
      _book/gitbook/gitbook-plugin-page-toc/page-toc.js
  31. +7
    -0
      _book/gitbook/gitbook-plugin-search/lunr.min.js
  32. +50
    -0
      _book/gitbook/gitbook-plugin-search/search-engine.js
  33. +35
    -0
      _book/gitbook/gitbook-plugin-search/search.css
  34. +213
    -0
      _book/gitbook/gitbook-plugin-search/search.js
  35. +90
    -0
      _book/gitbook/gitbook-plugin-sharing/buttons.js
  36. +4
    -0
      _book/gitbook/gitbook.js
  37. BIN
      _book/gitbook/images/apple-touch-icon-precomposed-152.png
  38. BIN
      _book/gitbook/images/favicon.ico
  39. +9
    -0
      _book/gitbook/style.css
  40. +4
    -0
      _book/gitbook/theme.js
  41. +376
    -0
      _book/index.html
  42. +870
    -0
      _book/lints.html
  43. +382
    -0
      _book/realms.html
  44. +403
    -0
      _book/roles/ssl_terminator/index.html
  45. +1
    -0
      _book/search_index.json
  46. +8
    -0
      book.json
  47. +745
    -0
      docs/Docs/Structure.adoc
  48. +8
    -0
      docs/Docs/Tools.md
  49. +19
    -0
      docs/README.md
  50. +8
    -0
      docs/SUMMARY.adoc
  51. +342
    -0
      docs/lints.adoc
  52. +9
    -0
      docs/realms.adoc
  53. +27
    -0
      docs/roles/ssl_terminator/README.adoc
  54. +12
    -0
      node_modules/gitbook-plugin-page-toc/CHANGELOG.md
  55. +21
    -0
      node_modules/gitbook-plugin-page-toc/LICENSE
  56. +57
    -0
      node_modules/gitbook-plugin-page-toc/README.md
  57. +6
    -0
      node_modules/gitbook-plugin-page-toc/assets/anchor-3.1.1.min.js
  58. +25
    -0
      node_modules/gitbook-plugin-page-toc/assets/page-toc.css
  59. +81
    -0
      node_modules/gitbook-plugin-page-toc/assets/page-toc.js
  60. +7
    -0
      node_modules/gitbook-plugin-page-toc/index.js
  61. +115
    -0
      node_modules/gitbook-plugin-page-toc/package.json

+ 5
- 0
LICENSE View File

@@ -0,0 +1,5 @@
MIT License
Copyright (c) <2018> <Alexander Thaller (alexander@thaller.ws)>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 3
- 0
README.md View File

@@ -0,0 +1,3 @@
# saltstack-prototype_docs

Rendered documentation for https://git.thaller.ws/athaller/saltstack-prototype

+ 80
- 0
_book/Docs/RFCs/SALT1-role_metadata.md View File

@@ -0,0 +1,80 @@
{% raw %}
# SALT1: Role Metadata

This RFC describes how the storage of metadata for roles must be implemented.

## Conventions
The key words “**MUST**”, “**MUST NOT**”, “**REQUIRED**”, “**SHALL**”, “**SHALL
NOT**”, “**SHOULD**”, “**SHOULD NOT**”, “**RECOMMENDED**”, “**MAY**”, and
“**OPTIONAL**” in this document are to be interpreted as described in [RFC
2119](https://tools.ietf.org/html/rfc2119).

- [YAML Ain’t Markup Language (YAML™) Version
1.2](http://www.yaml.org/spec/1.2/spec.html)
- [2.1 Collections](http://www.yaml.org/spec/1.2/spec.html#id2759963): In this
document a "Sequence of Scalars" is a *list*.
- [2.3 Scalars](http://www.yaml.org/spec/1.2/spec.html#id2760844): In this
document a "Scalar" is a *string*.
- [Internet Message Format](https://tools.ietf.org/html/rfc5322): For definition
about a *valid email address*.

## Purpose

Metadata defines additional information about a role besides the included states.

Metadata can range from describing the overall function of the role to who is
maintaing the role, but also as an example have links to additional resources
that describe or inform about the role.

## Specification

1. Metadata **MUST** be stored in `states/role/{{ rolename }}/metadata.yaml`.

2. Metadata **MUST** be valid `YAML`.

3. Metadata **SHOULD** have a `name` key.
1. The `name` key's value, if provided, **MUST** be a *string*.
2. When the `name` key is not provided the folder name of the role **MUST**
be used.

4. Metadata **SHOULD** have a `description` key.
1. The `description` key's value, if provided, **MUST** be a *string*.
2. The `description` key's value **MUST** contain a short description of
the overall function of the role.

5. Metadata **SHOULD** have a `maintainers` key.
1. The `maintainers` key's value, if provided, **MUST** be a *list*.
2. A *list* item's value **MUST** be a *string* and a *valid email
address*.
3. The `maintainers` key's value **MUST** contain a *list* of people who
**MUST** be contacted when states change that are used by that role.

6. Metadata **MAY** have additional keys. They are not further specified in this
document.

## Example

`states/role/loadbalancer_datacenter/metadata.yaml`:

```yaml
name: loadbalancer_datacenter
description: Role for the loadbalancers in SFO, DCA and HKG.
maintainers:
- alexander.thaller@trivago.com
- marc.peters@trivago.com

# example for additional keys these are not standardized but can still be
# added if wanted.
version: 7
links:
- http://knowledge.trivago.com/some-page
- http://tasks.trivago.com/SALT-4711
- http://someupstreamprojectistoletheideafrom.com
known_issues:
- only applies to datacenters DCA, SFO, HKG
```

## References
- [Discussion](http://git.trivago.trv/projects/DCO/repos/saltstack/pull-requests/1817/overview)
- Tool to extract metadata from the `metadata.yaml`: [SaltStack Helper Tool](http://git.trivago.trv/projects/SALT/repos/saltstack_helper/browse)
{% endraw %}

+ 184
- 0
_book/Docs/RFCs/SALT2-realm_naming.md View File

@@ -0,0 +1,184 @@
{% raw %}
# SALT2: Realm naming

This RFC describes conventions how realms should be named.

## Conventions
The key words “**MUST**”, “**MUST NOT**”, “**REQUIRED**”, “**SHALL**”, “**SHALL
NOT**”, “**SHOULD**”, “**SHOULD NOT**”, “**RECOMMENDED**”, “**MAY**”, and
“**OPTIONAL**” in this document are to be interpreted as described in [RFC
2119](https://tools.ietf.org/html/rfc2119).

## Purpose

Realms should have clear names to make it easier to identify the purpose and
logical or geographical location of a minion. They are also hierarchical which
can make it more complicated to decide how to name realms.

This RFC should give guidelines on how to name realms and also predefine realms
that are already in use.

## Situation

Currently we have the following realms:

```
can
datacenter.can.frontend
datacenter.dca.frontend
datacenter.dus.backbone
datacenter.dus.frontend
datacenter.hkg.backbone
datacenter.hkg.frontend
datacenter.sfo.frontend
dca
dg
dus
hkg
sfo
sfo_cloud
testing.saltmaster_dev.jails.can
testing.saltmaster_dev.jails.dca
testing.saltmaster_dev.jails.dus
testing.saltmaster_dev.jails.dus
testing.saltmaster_dev.jails.dus
testing.saltmaster_dev.jails.dus
testing.saltmaster_dev.jails.dus.backbone
testing.saltmaster_dev.jails.hkg
testing.saltmaster_dev.jails.sfo
testing.saltmaster_dev.jails.sfo
testing.saltmaster_dev.master
testing.saltmaster_dev.opennebula
testing.saltmaster_dev.opennebula
trv
trv-dg
trv-dus-dg
```

They are constructed by logical and geographical identifiers:

* **logical**: `datacenter`, `frontend`, `backend`, `trv`, `testing`,
`saltmaster_dev`, `jails`
* **geographical**: `can`, `dca`, `dus`, `hkg`, `sfo`, `sfo_cloud`, `dg`, `dus-dg`

We also have the `trivago_utils` module with the `get_ip` function which also
uses existing conventions about our datacenter network.

There we have the following definitions:

```
'firewall': {
'base_pattern': (
'10.1.',
'10.11.',
'10.21.',
'10.31.',
'10.51.',
'192.168.',
'172.',
),
'frontend': (
'10.1.5.',
'10.1.2.',
'10.11.2.',
'10.21.2.',
'10.31.2.',
'10.51.2.',
'10.1.13.',
'10.1.12.',
'10.1.11.',
'10.1.10.',
'10.1.9.',
'10.1.8.',
),
'backend': (
'10.1.3.',
'10.11.3.',
'10.21.3.',
'10.31.3.',
'10.51.3.',
),
'admin': (
'10.1.6.',
'10.11.6.',
'10.21.6.',
'10.31.6.',
'10.51.6.',
),
},
'backbone': {
'base_pattern': (
'10.2.',
'10.12.',
'10.22.',
'10.32.',
'10.52.',
'192.168.',
'172.',
),
'frontend': (
'10.2.5.',
'10.2.2.',
'10.12.2.',
'10.22.2.',
'10.32.2.',
'10.52.2.',
),
'backend': (
'10.2.3.',
'10.12.3.',
'10.22.3.',
'10.32.3.',
'10.52.3.',
),
'admin': (
'10.2.6.',
'10.12.6.',
'10.22.6.',
'10.32.6.',
'10.52.6.',
)
}
```

These should also be used as a guide for naming realms as they are an already
existing convention.

An ideal solution would incorporate the existing realms and conventions but also
make it clear what the purpose of the realm is and if it is hierarchical below
another realm or not.

## Specification

1. Realm name **MUST** be unique.
2. Realms **MAY** have _SubRealms_ which inherit options from the parent realm.
3. SubRealms **MUST** be separated by an dot (`.`).
4. Existing realms **SHOULD** be reused.
5. If an option does not fit an existing realm a new realm **MUST** be created.
6. Realms **MUST** be documented in a **METADATA** file under
`docs/v2/metadata.yaml`. It **MUST** contain the description of the realm and
**MAY** contain subrealms of the realm.

## Example

* `datacenter.dus.backbone`: Part of the Düsseldorf datacenter which has access
to the backbone network segment.
* `datacenter.dus.firewall`: Part of the Düsseldorf datacenter which does not
have access to the backbone network segment.
* `eu.dus.b1`: European office in Düsseldorf called B1 (white building).
* `eu.dus.dc.backbone`: Part of the European datacenter in Düsseldorf which has
access to the backbone network segment.
* `eu.dus.dg`: European office in Düsseldorf called DeepGrey (grey IBM
building).
* `office.b1`: Office B1 (white building in Düsseldorf).
* `office.deep_grey`: Office DeepGrey (grey IBM building in Düsseldorf).
* `office.palma`: Office Palma.
* `testing.saltmaster_dev.jails.dus`: Machines that are inside a jail on a
`saltmaster_dev` to test machines that should be deployed to `dus`.
* `us.sfo.dc.frontend`: Part of the USA datacenter in San Francisco which does
not have access to the backbone network segment.

## References
- [Discussion](http://git.trivago.trv/projects/DCO/repos/saltstack/pull-requests/2045/overview)
- Tool to extract realms from the repository: [SaltStack Helper Tool](http://git.trivago.trv/projects/SALT/repos/saltstack_helper/browse)
{% endraw %}

+ 80
- 0
_book/Docs/RFCs/salt1-role_metadata.md View File

@@ -0,0 +1,80 @@
{% raw %}
# SALT1: Role Metadata

This RFC describes how the storage of metadata for roles must be implemented.

## Conventions
The key words “**MUST**”, “**MUST NOT**”, “**REQUIRED**”, “**SHALL**”, “**SHALL
NOT**”, “**SHOULD**”, “**SHOULD NOT**”, “**RECOMMENDED**”, “**MAY**”, and
“**OPTIONAL**” in this document are to be interpreted as described in [RFC
2119](https://tools.ietf.org/html/rfc2119).

- [YAML Ain’t Markup Language (YAML™) Version
1.2](http://www.yaml.org/spec/1.2/spec.html)
- [2.1 Collections](http://www.yaml.org/spec/1.2/spec.html#id2759963): In this
document a "Sequence of Scalars" is a *list*.
- [2.3 Scalars](http://www.yaml.org/spec/1.2/spec.html#id2760844): In this
document a "Scalar" is a *string*.
- [Internet Message Format](https://tools.ietf.org/html/rfc5322): For definition
about a *valid email address*.

## Purpose

Metadata defines additional information about a role besides the included states.

Metadata can range from describing the overall function of the role to who is
maintaing the role, but also as an example have links to additional resources
that describe or inform about the role.

## Specification

1. Metadata **MUST** be stored in `states/role/{{ rolename }}/metadata.yaml`.

2. Metadata **MUST** be valid `YAML`.

3. Metadata **SHOULD** have a `name` key.
1. The `name` key's value, if provided, **MUST** be a *string*.
2. When the `name` key is not provided the folder name of the role **MUST**
be used.

4. Metadata **SHOULD** have a `description` key.
1. The `description` key's value, if provided, **MUST** be a *string*.
2. The `description` key's value **MUST** contain a short description of
the overall function of the role.

5. Metadata **SHOULD** have a `maintainers` key.
1. The `maintainers` key's value, if provided, **MUST** be a *list*.
2. A *list* item's value **MUST** be a *string* and a *valid email
address*.
3. The `maintainers` key's value **MUST** contain a *list* of people who
**MUST** be contacted when states change that are used by that role.

6. Metadata **MAY** have additional keys. They are not further specified in this
document.

## Example

`states/role/loadbalancer_datacenter/metadata.yaml`:

```yaml
name: loadbalancer_datacenter
description: Role for the loadbalancers in SFO, DCA and HKG.
maintainers:
- alexander.thaller@trivago.com
- marc.peters@trivago.com

# example for additional keys these are not standardized but can still be
# added if wanted.
version: 7
links:
- http://knowledge.trivago.com/some-page
- http://tasks.trivago.com/SALT-4711
- http://someupstreamprojectistoletheideafrom.com
known_issues:
- only applies to datacenters DCA, SFO, HKG
```

## References
- [Discussion](http://git.trivago.trv/projects/DCO/repos/saltstack/pull-requests/1817/overview)
- Tool to extract metadata from the `metadata.yaml`: [SaltStack Helper Tool](http://git.trivago.trv/projects/SALT/repos/saltstack_helper/browse)
{% endraw %}

+ 184
- 0
_book/Docs/RFCs/salt2-realm_naming.md View File

@@ -0,0 +1,184 @@
{% raw %}
# SALT2: Realm naming

This RFC describes conventions how realms should be named.

## Conventions
The key words “**MUST**”, “**MUST NOT**”, “**REQUIRED**”, “**SHALL**”, “**SHALL
NOT**”, “**SHOULD**”, “**SHOULD NOT**”, “**RECOMMENDED**”, “**MAY**”, and
“**OPTIONAL**” in this document are to be interpreted as described in [RFC
2119](https://tools.ietf.org/html/rfc2119).

## Purpose

Realms should have clear names to make it easier to identify the purpose and
logical or geographical location of a minion. They are also hierarchical which
can make it more complicated to decide how to name realms.

This RFC should give guidelines on how to name realms and also predefine realms
that are already in use.

## Situation

Currently we have the following realms:

```
can
datacenter.can.frontend
datacenter.dca.frontend
datacenter.dus.backbone
datacenter.dus.frontend
datacenter.hkg.backbone
datacenter.hkg.frontend
datacenter.sfo.frontend
dca
dg
dus
hkg
sfo
sfo_cloud
testing.saltmaster_dev.jails.can
testing.saltmaster_dev.jails.dca
testing.saltmaster_dev.jails.dus
testing.saltmaster_dev.jails.dus
testing.saltmaster_dev.jails.dus
testing.saltmaster_dev.jails.dus
testing.saltmaster_dev.jails.dus.backbone
testing.saltmaster_dev.jails.hkg
testing.saltmaster_dev.jails.sfo
testing.saltmaster_dev.jails.sfo
testing.saltmaster_dev.master
testing.saltmaster_dev.opennebula
testing.saltmaster_dev.opennebula
trv
trv-dg
trv-dus-dg
```

They are constructed by logical and geographical identifiers:

* **logical**: `datacenter`, `frontend`, `backend`, `trv`, `testing`,
`saltmaster_dev`, `jails`
* **geographical**: `can`, `dca`, `dus`, `hkg`, `sfo`, `sfo_cloud`, `dg`, `dus-dg`

We also have the `trivago_utils` module with the `get_ip` function which also
uses existing conventions about our datacenter network.

There we have the following definitions:

```
'firewall': {
'base_pattern': (
'10.1.',
'10.11.',
'10.21.',
'10.31.',
'10.51.',
'192.168.',
'172.',
),
'frontend': (
'10.1.5.',
'10.1.2.',
'10.11.2.',
'10.21.2.',
'10.31.2.',
'10.51.2.',
'10.1.13.',
'10.1.12.',
'10.1.11.',
'10.1.10.',
'10.1.9.',
'10.1.8.',
),
'backend': (
'10.1.3.',
'10.11.3.',
'10.21.3.',
'10.31.3.',
'10.51.3.',
),
'admin': (
'10.1.6.',
'10.11.6.',
'10.21.6.',
'10.31.6.',
'10.51.6.',
),
},
'backbone': {
'base_pattern': (
'10.2.',
'10.12.',
'10.22.',
'10.32.',
'10.52.',
'192.168.',
'172.',
),
'frontend': (
'10.2.5.',
'10.2.2.',
'10.12.2.',
'10.22.2.',
'10.32.2.',
'10.52.2.',
),
'backend': (
'10.2.3.',
'10.12.3.',
'10.22.3.',
'10.32.3.',
'10.52.3.',
),
'admin': (
'10.2.6.',
'10.12.6.',
'10.22.6.',
'10.32.6.',
'10.52.6.',
)
}
```

These should also be used as a guide for naming realms as they are an already
existing convention.

An ideal solution would incorporate the existing realms and conventions but also
make it clear what the purpose of the realm is and if it is hierarchical below
another realm or not.

## Specification

1. Realm name **MUST** be unique.
2. Realms **MAY** have _SubRealms_ which inherit options from the parent realm.
3. SubRealms **MUST** be separated by an dot (`.`).
4. Existing realms **SHOULD** be reused.
5. If an option does not fit an existing realm a new realm **MUST** be created.
6. Realms **MUST** be documented in a **METADATA** file under
`docs/v2/metadata.yaml`. It **MUST** contain the description of the realm and
**MAY** contain subrealms of the realm.

## Example

* `datacenter.dus.backbone`: Part of the Düsseldorf datacenter which has access
to the backbone network segment.
* `datacenter.dus.firewall`: Part of the Düsseldorf datacenter which does not
have access to the backbone network segment.
* `eu.dus.b1`: European office in Düsseldorf called B1 (white building).
* `eu.dus.dc.backbone`: Part of the European datacenter in Düsseldorf which has
access to the backbone network segment.
* `eu.dus.dg`: European office in Düsseldorf called DeepGrey (grey IBM
building).
* `office.b1`: Office B1 (white building in Düsseldorf).
* `office.deep_grey`: Office DeepGrey (grey IBM building in Düsseldorf).
* `office.palma`: Office Palma.
* `testing.saltmaster_dev.jails.dus`: Machines that are inside a jail on a
`saltmaster_dev` to test machines that should be deployed to `dus`.
* `us.sfo.dc.frontend`: Part of the USA datacenter in San Francisco which does
not have access to the backbone network segment.

## References
- [Discussion](http://git.trivago.trv/projects/DCO/repos/saltstack/pull-requests/2045/overview)
- Tool to extract realms from the repository: [SaltStack Helper Tool](http://git.trivago.trv/projects/SALT/repos/saltstack_helper/browse)
{% endraw %}

+ 745
- 0
_book/Docs/STRUCTURE.adoc View File

@@ -0,0 +1,745 @@
{% raw %}
// vim: set filetype=asciidoc:

= Terms and Structure of the SaltStack Repository

This document describes different terms used in this repository and gives an
overview of the structure of the repository.

Version:: 1.1

== Overview

The goals of this structure are the following:

* Make it easy to reuse existing code (states and pillars)
* Make it easy to add new and extend existing code
* Make it easy to reason and understand what gets executed on the minion

These goals are achieved by doing the following:

* Defining an structure through code (topfile)
* Using folder based matching instead of complicated topfile matching
* Introducing the <<profile,profile>> abstraction layer
** Describe dependencies between <<formulas,formula>>
** Reuse and extend existing <<formulas,formula>>
* Moving pillars from the <<global,global>> space to the <<role,role>> space

This structure is inspired by the puppet structure "Roles and
Profiles"footnote:[https://docs.puppet.com/pe/2017.1/r_n_p_intro.html].

== Terms
=== State
Examples:: `formula.nginx.pkgs`, `profile.pkgng_cacher.cachedir`

The smallest part of SaltStack where we define what should be executed on the
minion. These can contain installing packages, rolling out configuration files
or starting and enabling services.

See also the saltstack documenation about this: link:https://docs.saltstack.com/en/latest/ref/states/writing.html[Saltstack - State Modules]

==== Examples

A typical state would look like this:

.Template state for rolling out a configuration file
[source,yaml]
----
formula.template.config:
file.managed:
- name: '{{ lookup.config.name }}'
- source: 'salt://{{ salt['file.join'](tpldir, "files", "config_template") }}'
- mode: 0644
- template: 'jinja'
- require:
- pkg: 'formula.template.pkg'
# template variables
- context:
options: {{ options }}
----

=== Formula
Examples:: `nginx`, `apache`, `haproxy`, `php`

Formulas are a collection of <<state,states>>. They describe how to install and
manage a single application or service.

For example a formula can take care of the following:

* Install the right package depending on the operating system
* Decide where to put the configuration file if needed
* Provide reasonable defaults for the configuration if possible
* Provide a configuration file template that can easily be extended through
<<pillars>>
* Start and enable services that are associated with the software
* Restart or reload services if certain conditions are met (change in
configuration file)

WARNING: If you need to have a dependency between two formulas you should write
a <<profile>>!

==== File and folder structure
A formula normally contains of these files and folders:

`init.sls`:: Entry point for the formula that is used by salt. Here you can
write your <<states,states>>.

`map.jinja`:: Provides operating system specific defaults and general defaults
that can be overwritten via <<pillars,pillars>>.

`pillar.example`:: Contains example pillar options for the formula.

`files`:: Contains all files that are used by the template. For example the
configuration template.

`README.md`:: Short description about what the formula is doing.

==== Examples

Contents of the `template` formula.

.`init.sls`
[source,yaml]
----
{#
import the lookup and options map from the map.jinja file.
tpldir is a jinja variable that gives the current folder so make it easier to
move states around.
#}
{%- from salt['file.normpath'](tpldir+"/map.jinja") import lookup -%}
{%- from salt['file.normpath'](tpldir+"/map.jinja") import options -%}

# Install packages that are defined in the lookup map in the `map.jinja` file
formula.template.pkg:
pkg.installed:
- pkgs: {{ lookup.pkgs }}

# Deploy the configuration template from `files/config_template` which renders
# the content of the contens map from `map.jinja` as YAML.
formula.template.config:
file.managed:
- name: '{{ lookup.config.name }}'
- source: 'salt://{{ salt['file.join'](tpldir, "files", "config_template") }}'
- mode: 0644
- template: 'jinja'
- require:
- pkg: 'formula.template.pkg'
# template variables
- context:
options: {{ options }}

# Make sure that the service specified in the lookup map from `map.jinja` is
# running and enabled. Also make sure to restart the service if the
# configuration has changed and restart is enabled.
formula.template.service:
service.running:
- name: '{{ lookup.service.name }}'
{% if lookup.service.restart %}
- restart: True
{% endif %}
- enable: True
- require:
- pkg: 'formula.template.pkg'
- file: 'formula.template.config'
- watch:
- file: 'formula.template.config'
----

.`map.jinja`
[source,jinja]
----
{# lookup holds operating system specific options the lookup values can be
overwritten by pillars in the lookup key #}
{% set lookup = salt['grains.filter_by'](
{
'FreeBSD': {
'pkgs': [
'no_package_like_this',
'another_package',
],
'config': {
'name': '/usr/local/etc/template.conf',
},
'service': {
'name': 'template_service',
'restart': True
},
},
'Debian': {
'pkgs': [
'no_package_like_this',
'another_package',
],
'config': {
'name': '/etc/template.conf',
},
'service': {
'name': 'template_service',
'restart': True
},
},
'RedHat': {
'pkgs': [
'no_package_like_this',
'another_package',
],
'config': {
'name': '/etc/template.conf',
},
'service': {
'name': 'template_service',
'restart': True
},
},
},
grain='os_family',
merge=salt['pillar.get']('formula.template:lookup'),
) %}

{# defaults hold default values for the options that can be overwritten by the options/pillars #}
{% set defaults = {
} %}

{# options hold the pillar information for the formula and are defined through a pillar #}
{% set options = salt['pillar.get']('formula.template',
default=defaults,
merge=True) %}
----

.`pillar.example`
[source,yaml]
----
formula.template:
key: 'value'
map:
key: 'value'
second_key: 'second_value'
lists:
- 'this is the first element'
- 'this is the second element'
----

.`README.md`
[source,md]
----
This is a template for a salt formula that can be used as a base for developing
a new formula.
----

.`files/config_template`
[source,jinja]
----
{{ options | yaml(False) }}
----

=== Profile
Examples:: `trivago_default`, `appserver_php_apache`, `nginx_ssl_terminator`

Profiles are an abstraction over formulas. They serve multiple purposes:

* Make bundles of formulas and profiles that are often used by multiple roles
(see <<profile-code-trivago_default-code,profile trivago_default>>)

* Gluing formulas together (see <<profile-code-appserver_php_apache-code,profile
appserver_php_apache>>)

* Making it easier to reuse and extend existing formulas (see
<<profile-code-nginx_ssl_terminator-code,profile nginx_ssl_terminator>>

To use profiles in these cases solves these problems:

* Inter formula dependencies which make it hard to reuse formulas in different
ways. For example if we would combine `php` and `apache` directly we would not
have the ability to use `php` combined with `nginx` without also using `apache`.
* Standardized way to extend or reuse formulas which is clearly communicated.

==== Examples
===== Profile `trivago_default`
Profile `trivago_default` bundles multiple formulas and profiles together that
are used by almost all roles used at trivago.

.`default` `init.sls`
[source,yaml]
----
include:
- 'formula.hosts'
- 'profile.pkgrepo'
- 'formula.default_packages'
- 'formula.salt_minion'
- 'formula.sudoers'
- 'formula.nrpe'
----

===== Profile `appserver_php_apache`

Profile `appserver_php_apache` reuses the formula `php` and `apache` and will
automatically restart apache when the PHP configuration changes.

.`appserver_php` `init.sls`
[source,yaml]
----
include:
- 'formula.php'
- 'formula.apache'

extend:
formula.apache.service:
# autorestart apache when php config changes
- watch:
- file: 'formula.php.config'
----

===== Profile `nginx_ssl_terminator`

.`nginx_ssl_terminator` `init.sls`
[source,yaml]
----
include:
- 'formula.nginx'

extend:
formula.nginx.config:
file.managed:
- source: 'profile.ssl_terminator.files.config_template'
----

=== Role
Examples:: `pricesearch_server`, `ssl_terminator`, `saltmaster_dev`

Roles include <<profiles,profile>> and <<formulas,formula>> to describe the
business function of a minion.

A minion can only have one role at the same time and are used for the _matching_
inside the <<states,states>> and <<pillars,pillars>> topfile.

==== Examples
===== Role `saltmaster_dev`

`saltmaster_dev` deploys a saltmaster and multiple jails on a minion to make it
easy to develope saltstack states and pillars.

.Statefile for `saltmaster_dev`
[source,yaml]
----
include:
- 'profile.default'
- 'profile.pkgng_cacher'
- 'formula.salt_master'
- 'formula.salt_api'
- 'profile.jailmaster'
- 'formula.salt-compressor'
----

.Pillarfile for `saltmaster_dev`
[source,yaml]
----
include:
- 'preset.datacenter_defaults'
- 'role.saltmaster_dev.base'
----

=== Environment
Examples:: `dev`, `stage`, `prod`

Environments define in what kind of _stage_ the minion is in. Is it a
development machine or a production machine.

This makes it easy to make small behavior changes that are desirable in a
_development environment_ but not in a _production environment_.

==== Examples
===== Configcheck on rollout

For example if you develop a new state. You have a configuration check which
checks the validity of a configuration file before rolling it out. You also have
a template that gets rendered depending on <<pillar,pillar>> options.

You now want to see the output of the template after applying the pillar
options. If you make an error the configuration check will catch that and not
deploy the rendered configuration file to the machine. This makes it hard to
debug and fix the problem.

In a production environment this is a desirable thing as it prevents errors that
could lead to downtime. In a development environment this is annoying as it
prevents you to see the actual output of your configuration file.

You can now define in your pillars that the configuration check should only be
run in production environments but not in development environments.

This makes it easier to develop new states but still have good error checks in
production.

In code it could look like this:

.Haproxy formula config state
[source,yaml]
----
formula.haproxy.config:
file.managed:
- name: '{{ lookup.config.name }}'
- source: 'salt://{{ salt['file.join'](tpldir, "files", "config_template") }}'
{% if lookup.config.check %}
- check_cmd: '{{ lookup.service.name }} -c -f'
{% endif %}
----

.Global dev environment pillar
[source,yaml]
----
formula.haproxy:
lookup:
config:
check: False
----

.Global prod environment pillar
[source,yaml]
----
formula.haproxy:
lookup:
config:
check: True
----

=== Realm
Examples:: `dus`, `dus.frontend`, `dus.backbone`, `sfo`, `hkg`,
`eu.dus.office.deepgrey.thaller.saltmaster_dev`

Realms describe the geographical or logical location of the minion. They are
used to change settings of the minion depending on their surrounding. If a
minion is in the _hkg datatacenter_ it needs different IPs for its DNS and NTP
server then a minion in the _sfo datacenter_.

Realms should be treated as a _logical_ environment but are usually encoded in a
_geographical_ location. This is mostly to make it easier to understand where a
server is and follows our usual naming structure.

Realms are hierarchically structured and should be separated by a `.` (dot). So
for example the realm `eu.dus` is a subrealm of the realm `eu`. For more
information on how realms are used see the <<folders>> section under
<<pillars>>.

[CAUTION]
====
Realms should *not* be used to to differentiate between _dev_ and
_prod_ environments.

If you have behavior changes use a different <<role,role>> or an
<<environment,environment>>.

They can be used to setup a development realm which brings for example
different IPs or endpoints with it.
====

[IMPORTANT]
====
If you want to have different settings than an existing realm its a new realm!
====

==== Examples
`dus`:: Used by the Düsseldorf datacenter
`sfo`:: User by the San Francisco datacenter
`trv-dus-dg`:: Used by the Deep Grey office in Düsseldorf

== Structure

----
saltstack
├── pillars
│   ├── global
│   │   ├── environment
│   │   ├── id
│   │   └── realm
│   ├── preset
│   └── role
│   └── <role>
│   ├── environment
│   ├── id
│   └── realm
└── states
├── formula
├── profile
└── role
----

=== States

.States dependencies generated by `graph_states_dependencies`
image::states_dependencies.svg[States dependencies]

Folders:: `formula`, `profile`, `role`

States have a relatively simple structure. They just match the <<role,role>>
grain of the minion to the files and folders in the `role` folder.

----
states
├── formula
│   ├── default_packages
│   ├── haproxy
│   ├── hosts
│   └── nginx
├── profile
│   ├── loadbalancer_datacenter
│   └── trivago_default
└── role
├── loadbalancer_datacenter
└── ssl_terminator
----

For example if the role of the minion is `ssl_terminator` then
`role.ssl_terminator` will be used.

The role file then includes <<formula,formulas>> and <<profile,profiles>>:

.Role file `role.ssl_terminator`
[source,yaml]
----
include:
- 'profile.default'
- 'profile.ssl_terminator'
----

=== Pillars

Folders:: `global`, `preset`, `role`

Pillars have a more complicated structure than <<states,states>>. They provide
a structured configuration for the states. As they are structured it's easy to
extend and overwrite them.

[CAUTION]
====
The behavior of the pillars can heavily depend on the configuration of the
saltmaster. See
link:https://docs.saltstack.com/en/latest/ref/configuration/master.html#pillar-merging-options[Pillar
Merging Options] for more information.

On our saltmaster's we usually set the following options:

.Usual pillar settings for saltmaster
[source,yaml]
----
# Recursively merge pillar data
pillar_source_merging_strategy: 'recurse'

# Recursively merge lists by aggregating them instead of replacing them.
pillar_merge_lists: True
----
====

==== Folders
===== Global

IMPORTANT: Global pillar should be avoided as much as possible and should only
be used when absolutely necessary. Not all minions need all pillars all the time
and globals make it harder to determine where pillars come from If you can put
the pillars you want to add under the same folder in your <<role,role>>.

Examples:: `global.realm.dus.frontend`, `global.environment.dev`,
`global.id.ssl-ter0-dus`

Stores pillars that are used between multiple roles.

Global provides three folders to match pillars to a minion:

`environment`:: Will match against the <<environment,environment>> grain of the
minion. Should only contain small behavior changes like not auto-restarting
_apache_ in `prod` when the configuration file changes.
`realm`:: Will match against the <<realm,realm>> grain of the minion. Contains
information about the "surrounding" of the minion like _dns server_ or _kafka
server_.
+
The realms are hierarchically structured with subfolders:
+
----
realm
├── eu
│   ├── ams
│   │   └── office
│   └── dus
│   ├── datacenter
│   │   ├── backend
│   │   └── frontend
│   └── office
│   └── deepgrey
└── north_america
├── dca
│   └── datacenter
└── sfo
└── datacenter
----
+
Pillars defined in the realm `eu` would be inherited by the realms `eu.ams` and
`eu.dus`. Pillars defined in a lower level for example `eu.ams` will overwrite
pillars inherited by `eu`.
+
For example if you have the following pillars defined:
+
.`eu`
[source,yaml]
----
formula.example:
key1: 'value1'
key2: 'value2'
----
+
.`eu.dus`
[source,yaml]
----
formula.example:
key1: 'value3'
----
+
The resulting pillar for a minion in the `eu.dus` realm would be the following:
+
[source,yaml]
----
formula.example
key1: 'value3'
key2: 'value2'
----

`id`:: Will match against a specific minion ID.

===== Preset

Examples:: `preset.datacenter_defaults`, `preset.dev_ssl_cert`

Contains preset pillar files that are reusable between multiple roles.

They make it easier to opt-in to pillars instead of having a default matching,
but still having a way to share pillars between roles.

They contain defaults we want to have on all minions. Good example are
`nrpe` pillars which enable checks we want to have enabled on all minions.

They also contain pillars that are useful to different minions but are not
needed on all minions. For example the `dev_ssl_cert` contains a valid
certificate that can be used for when applications get tested against HTTPs.

They can be `include` files or their own pillar entry files.

==== Examples
===== Preset `datacenter_defaults`

[source,yaml]
----
# default trivago options

include:
- 'preset.pkgng_repos'
- 'preset.nrpe_sudo'
----

===== Preset `pkgng_repos`

[source,yaml]
----
formula.pkgng:
repos:
FreeBSD:
enabled: 'no'
trivago:
url: 'http://pkgmirror.trivago.trv/103x64/default'
mirror_type: 'http'
signature_type: 'pubkey'
pubkey: '/etc/ssl/pkg.cert'
enabled: 'yes'
trivago-php:
url: 'http://pkgmirror.trivago.trv/103x64/php5/'
mirror_type: 'http'
signature_type: 'pubkey'
pubkey: '/etc/ssl/pkg.cert'
trivago-php7:
url: 'http://pkgmirror.trivago.trv/103x64/php7/'
mirror_type: 'http'
signature_type: 'pubkey'
pubkey: '/etc/ssl/pkg.cert'
ssl_terminator:
url: 'http://pkgmirror.trivago.trv/103x64/libressl/'
mirror_type: 'http'
signature_type: 'pubkey'
pubkey: '/etc/ssl/pkg.cert'
----

===== Role
Examples:: `role.loadbalancer_datacenter`, `role.saltmaster_dev`,
`role.ssl_terminator`

Contains the role pillars that are matched to the <<role,role>> of the minion.

They mirror the structure from the <<global,global pillars>>:

----
role
└── loadbalancer_datacenter
├── environment
│   ├── dev
│   └── prod
├── id
│   ├── lb0-dus
│   └── lb1-dus
└── realm
├── asia
│   └── hkg
├── eu
│   ├── ams
│   └── dus
└── north_america
├── dca
└── sfo
----

This has the purpose to contain pillars to their role. This makes it easier to
find the pillar files for the specific role. It also avoids unnecessary clutter
in the pillars as only role that needs the pillars gets the pillars.

When pillars need to be used by multiple roles there are two ways:

* Define a <<global,global>> pillar applicable to the scope that is needed. This
should be avoided if possible.
* Define a <<preset,preset>> pillar that is then included into the role pillar.
This is done like this:
+
.Role `ssl_terminator` pillar `init.sls`
[source,yaml]
----
include:
- 'preset.datacenter_defaults'
- 'role.ssl_terminator.base'
----

==== Matching
The following grains are used for matching:

`role`:: The <<role>> of the server.
`environment`:: The <<environment>> of the server.
`realm`:: The <<realm>> of the server.

They will be matched in this order:

. `role.<role>`
. `global.realm.<realm>`
. `role.<role>.realm.<realm>`
. `global.environment.<environment>`
. `role.<role>.environment.<environment>`
. `global.id.<id>`
. `role.<role>.id.<id>`

The matching will also happen in the same order for `_secret` as a prefix where
our pillars reside that are not included in the normal repository.

// TODO: Add example with specific grains that shows where stuff will be put and
// why they where put there.
//== Examples
//=== Role `saltmaster_dev` in realm `dus` with environment `prod`

== Links

* link:https://www.youtube.com/watch?v=yWhvgLqgYR0[Best Practices for Enterprise-Scale SaltStack - Trivago - SaltConf17]

== Authors

* Alexander Thaller <alexander.thaller@trivago.com>
{% endraw %}

+ 1495
- 0
_book/Docs/Structure.html
File diff suppressed because it is too large
View File


+ 376
- 0
_book/Docs/Tools.html View File

@@ -0,0 +1,376 @@

<!DOCTYPE HTML>
<html lang="" >
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Tools · GitBook</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="description" content="">
<meta name="generator" content="GitBook 3.2.3">
<link rel="stylesheet" href="../gitbook/style.css">

<link rel="stylesheet" href="../gitbook/gitbook-plugin-page-toc/page-toc.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-highlight/website.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-search/search.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-fontsettings/website.css">



<meta name="HandheldFriendly" content="true"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="../gitbook/images/apple-touch-icon-precomposed-152.png">
<link rel="shortcut icon" href="../gitbook/images/favicon.ico" type="image/x-icon">

<link rel="next" href="../lints.html" />
<link rel="prev" href="Structure.html" />

</head>
<body>
<div class="book">
<div class="book-summary">
<div id="book-search-input" role="search">
<input type="text" placeholder="Type to search" />
</div>

<nav role="navigation">


<ul class="summary">


<li class="chapter " data-level="1.1" data-path="../">
<a href="../">
Introduction
</a>

</li>
<li class="chapter " data-level="1.2" data-path="../realms.html">
<a href="../realms.html">
Realms
</a>

</li>
<li class="chapter " data-level="1.3" data-path="./">
<a href="./">
Docs
</a>

<ul class="articles">
<li class="chapter " data-level="1.3.1" data-path="Structure.html">
<a href="Structure.html">
Structure
</a>

</li>
<li class="chapter active" data-level="1.3.2" data-path="Tools.html">
<a href="Tools.html">
Tools
</a>

</li>

</ul>
</li>
<li class="chapter " data-level="1.4" data-path="../lints.html">
<a href="../lints.html">
Lints
</a>

</li>
<li class="chapter " data-level="1.5" data-path="../states/formula/README.md">
<span>
Formulas
</a>

</li>
<li class="chapter " data-level="1.6" data-path="../states/profile/README.md">
<span>
Profiles
</a>

</li>
<li class="chapter " data-level="1.7" data-path="../roles/README.md">
<span>
Roles
</a>

<ul class="articles">
<li class="chapter " data-level="1.7.1" data-path="../roles/ssl_terminator/">
<a href="../roles/ssl_terminator/">
ssl_terminator
</a>

</li>

</ul>
</li>


<li class="divider"></li>

<li>
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
Published with GitBook
</a>
</li>
</ul>


</nav>
</div>

<div class="book-body">
<div class="body-inner">

<div class="book-header" role="navigation">

<!-- Title -->
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i>
<a href=".." >Tools</a>
</h1>
</div>




<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<div id="book-search-results">
<div class="search-noresults">
<section class="normal markdown-section">
<h1 id="tools">Tools</h1>
<p>Different tools that can help with managing a saltstack repository:</p>
<ul>
<li><strong>serinus</strong>: Used to be called the saltstack helper and does a bunch of
different things. For more information see the repository: <a href="https://git.thaller.ws/athaller/serinus" target="_blank">https://git.thaller.ws/athaller/serinus</a>.</li>
</ul>

</section>
</div>
<div class="search-results">
<div class="has-results">
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
<ul class="search-results-list"></ul>
</div>
<div class="no-results">
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
</div>
</div>
</div>

</div>
</div>
</div>

<a href="Structure.html" class="navigation navigation-prev " aria-label="Previous page: Structure">
<i class="fa fa-angle-left"></i>
</a>
<a href="../lints.html" class="navigation navigation-next " aria-label="Next page: Lints">
<i class="fa fa-angle-right"></i>
</a>
</div>

<script>
var gitbook = gitbook || [];
gitbook.push(function() {
gitbook.page.hasChanged({"page":{"title":"Tools","level":"1.3.2","depth":2,"next":{"title":"Lints","level":"1.4","depth":1,"path":"lints.adoc","ref":"lints.adoc","articles":[]},"previous":{"title":"Structure","level":"1.3.1","depth":2,"path":"Docs/Structure.adoc","ref":"Docs/Structure.adoc","articles":[]},"dir":"ltr"},"config":{"plugins":["page-toc"],"root":"./docs","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"position":"before-first","page-toc":{"position":"before-first","selector":".markdown-section h1, .markdown-section h2, .markdown-section h3, .markdown-section h4","showByDefault":true},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"3.2.3"},"file":{"path":"Docs/Tools.md","mtime":"2018-09-20T15:54:29.058Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2018-09-20T15:54:51.284Z"},"basePath":"..","book":{"language":""}});
});
</script>
</div>

<script src="../gitbook/gitbook.js"></script>
<script src="../gitbook/theme.js"></script>
<script src="../gitbook/gitbook-plugin-page-toc/anchor-3.1.1.min.js"></script>
<script src="../gitbook/gitbook-plugin-page-toc/page-toc.js"></script>
<script src="../gitbook/gitbook-plugin-search/search-engine.js"></script>
<script src="../gitbook/gitbook-plugin-search/search.js"></script>
<script src="../gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
<script src="../gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
<script src="../gitbook/gitbook-plugin-sharing/buttons.js"></script>
<script src="../gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>

</body>
</html>


+ 376
- 0
_book/Docs/index.html View File

@@ -0,0 +1,376 @@

<!DOCTYPE HTML>
<html lang="" >
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Docs · GitBook</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="description" content="">
<meta name="generator" content="GitBook 3.2.3">
<link rel="stylesheet" href="../gitbook/style.css">

<link rel="stylesheet" href="../gitbook/gitbook-plugin-page-toc/page-toc.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-highlight/website.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-search/search.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-fontsettings/website.css">



<meta name="HandheldFriendly" content="true"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="../gitbook/images/apple-touch-icon-precomposed-152.png">
<link rel="shortcut icon" href="../gitbook/images/favicon.ico" type="image/x-icon">

<link rel="next" href="Structure.html" />
<link rel="prev" href="../realms.html" />

</head>
<body>
<div class="book">
<div class="book-summary">
<div id="book-search-input" role="search">
<input type="text" placeholder="Type to search" />
</div>

<nav role="navigation">


<ul class="summary">


<li class="chapter " data-level="1.1" data-path="../">
<a href="../">
Introduction
</a>

</li>
<li class="chapter " data-level="1.2" data-path="../realms.html">
<a href="../realms.html">
Realms
</a>

</li>
<li class="chapter active" data-level="1.3" data-path="./">
<a href="./">
Docs
</a>

<ul class="articles">
<li class="chapter " data-level="1.3.1" data-path="Structure.html">
<a href="Structure.html">
Structure
</a>

</li>
<li class="chapter " data-level="1.3.2" data-path="Tools.html">
<a href="Tools.html">
Tools
</a>

</li>

</ul>
</li>
<li class="chapter " data-level="1.4" data-path="../lints.html">
<a href="../lints.html">
Lints
</a>

</li>
<li class="chapter " data-level="1.5" data-path="../states/formula/README.md">
<span>
Formulas
</a>

</li>
<li class="chapter " data-level="1.6" data-path="../states/profile/README.md">
<span>
Profiles
</a>

</li>
<li class="chapter " data-level="1.7" data-path="../roles/README.md">
<span>
Roles
</a>

<ul class="articles">
<li class="chapter " data-level="1.7.1" data-path="../roles/ssl_terminator/">
<a href="../roles/ssl_terminator/">
ssl_terminator
</a>

</li>

</ul>
</li>


<li class="divider"></li>

<li>
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
Published with GitBook
</a>
</li>
</ul>


</nav>
</div>

<div class="book-body">
<div class="body-inner">

<div class="book-header" role="navigation">

<!-- Title -->
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i>
<a href=".." >Docs</a>
</h1>
</div>




<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<div id="book-search-results">
<div class="search-noresults">
<section class="normal markdown-section">
<h1 id="tools">Tools</h1>
<p>Different tools that can help with managing a saltstack repository:</p>
<ul>
<li><strong>serinus</strong>: Used to be called the saltstack helper and does a bunch of
different things. For more information see the repository: <a href="https://git.thaller.ws/athaller/serinus" target="_blank">https://git.thaller.ws/athaller/serinus</a>.</li>
</ul>

</section>
</div>
<div class="search-results">
<div class="has-results">
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
<ul class="search-results-list"></ul>
</div>
<div class="no-results">
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
</div>
</div>
</div>

</div>
</div>
</div>

<a href="../realms.html" class="navigation navigation-prev " aria-label="Previous page: Realms">
<i class="fa fa-angle-left"></i>
</a>
<a href="Structure.html" class="navigation navigation-next " aria-label="Next page: Structure">
<i class="fa fa-angle-right"></i>
</a>
</div>

<script>
var gitbook = gitbook || [];
gitbook.push(function() {
gitbook.page.hasChanged({"page":{"title":"Docs","level":"1.3","depth":1,"next":{"title":"Structure","level":"1.3.1","depth":2,"path":"Docs/Structure.adoc","ref":"Docs/Structure.adoc","articles":[]},"previous":{"title":"Realms","level":"1.2","depth":1,"path":"realms.adoc","ref":"realms.adoc","articles":[]},"dir":"ltr"},"config":{"plugins":["page-toc"],"root":"./docs","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"position":"before-first","page-toc":{"position":"before-first","selector":".markdown-section h1, .markdown-section h2, .markdown-section h3, .markdown-section h4","showByDefault":true},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"3.2.3"},"file":{"path":"Docs/README.md","mtime":"2018-09-20T14:57:36.222Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2018-09-20T15:54:51.284Z"},"basePath":"..","book":{"language":""}});
});
</script>
</div>

<script src="../gitbook/gitbook.js"></script>
<script src="../gitbook/theme.js"></script>
<script src="../gitbook/gitbook-plugin-page-toc/anchor-3.1.1.min.js"></script>
<script src="../gitbook/gitbook-plugin-page-toc/page-toc.js"></script>
<script src="../gitbook/gitbook-plugin-search/search-engine.js"></script>
<script src="../gitbook/gitbook-plugin-search/search.js"></script>
<script src="../gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
<script src="../gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
<script src="../gitbook/gitbook-plugin-sharing/buttons.js"></script>
<script src="../gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>

</body>
</html>


+ 80
- 0
_book/Docs/rfcs/salt1-role_metadata.md View File

@@ -0,0 +1,80 @@
{% raw %}
# SALT1: Role Metadata

This RFC describes how the storage of metadata for roles must be implemented.

## Conventions
The key words “**MUST**”, “**MUST NOT**”, “**REQUIRED**”, “**SHALL**”, “**SHALL
NOT**”, “**SHOULD**”, “**SHOULD NOT**”, “**RECOMMENDED**”, “**MAY**”, and
“**OPTIONAL**” in this document are to be interpreted as described in [RFC
2119](https://tools.ietf.org/html/rfc2119).

- [YAML Ain’t Markup Language (YAML™) Version
1.2](http://www.yaml.org/spec/1.2/spec.html)
- [2.1 Collections](http://www.yaml.org/spec/1.2/spec.html#id2759963): In this
document a "Sequence of Scalars" is a *list*.
- [2.3 Scalars](http://www.yaml.org/spec/1.2/spec.html#id2760844): In this
document a "Scalar" is a *string*.
- [Internet Message Format](https://tools.ietf.org/html/rfc5322): For definition
about a *valid email address*.

## Purpose

Metadata defines additional information about a role besides the included states.

Metadata can range from describing the overall function of the role to who is
maintaing the role, but also as an example have links to additional resources
that describe or inform about the role.

## Specification

1. Metadata **MUST** be stored in `states/role/{{ rolename }}/metadata.yaml`.

2. Metadata **MUST** be valid `YAML`.

3. Metadata **SHOULD** have a `name` key.
1. The `name` key's value, if provided, **MUST** be a *string*.
2. When the `name` key is not provided the folder name of the role **MUST**
be used.

4. Metadata **SHOULD** have a `description` key.
1. The `description` key's value, if provided, **MUST** be a *string*.
2. The `description` key's value **MUST** contain a short description of
the overall function of the role.

5. Metadata **SHOULD** have a `maintainers` key.
1. The `maintainers` key's value, if provided, **MUST** be a *list*.
2. A *list* item's value **MUST** be a *string* and a *valid email
address*.
3. The `maintainers` key's value **MUST** contain a *list* of people who
**MUST** be contacted when states change that are used by that role.

6. Metadata **MAY** have additional keys. They are not further specified in this
document.

## Example

`states/role/loadbalancer_datacenter/metadata.yaml`:
<