diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1e89a0b --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ + Copyright (c) 2014 Salt Stack Formulas + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/README.md b/README.md deleted file mode 100644 index 8bed6f5..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -reverse-grains-formula -====================== diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..b187735 --- /dev/null +++ b/README.rst @@ -0,0 +1,23 @@ +====================== +reverse-grains-formula +====================== + +Formula to configure grains via pillar in a grain/hosts rather than host/grains manner. + + +.. note:: + + See the full `Salt Formulas installation and usage instructions + `_. + +Available states +================ + +.. contents:: + :local: + +``grains`` +--------- + +Configure grains in /etc/salt/grains. Written with the py renderer. Utilizes +compound matches in the pillar to apply the grains and their values. diff --git a/grains/init.sls b/grains/init.sls new file mode 100644 index 0000000..ebb3c1f --- /dev/null +++ b/grains/init.sls @@ -0,0 +1,72 @@ +#!py +import yaml + +class GrainMaker: + """Generates the /etc/salt/grains file based on pillar data. + Example pillar: + grains: + grain1: + grainvalue1: + - G@id:host1 + - G@id:host2 + grainvalue2: + - G@id:host3 + grain2: + grainvalue1: + - G@id:host1 + - G@id:host2 + + Grains are assigned to each minion via compound matchers. + """ + def __init__(self): + self._grains = {} + + def _createGrainsYaml(self): + # Outputs the final yaml for /etc/salt/grains + return yaml.dump(self._grains, default_flow_style=False) + + def _matchValueToMinion(self, matchList): + # Checks that the matches for each grain value apply to this minion + matchList = matchList or [] + return any(__salt__["match.compound"](match) for match in matchList) + + def _addToGrains(self, grain, grainKey, value): + # Collects the grains into a dictionary + if self._matchValueToMinion(grain[grainKey][value]): + valueList = self._grains.get(grainKey, []) + valueList.append(value) + + self._grains[grainKey] = valueList + + def _parseGrainValues(self, grain): + # Parses individual grains and their values passed from the pillar + grainKey = grain.keys()[0] + if grain[grainKey]: + for value in grain[grainKey]: + self._addToGrains(grain, grainKey, value) + + # If there is only one value for a grain, make sure it is a string + # and not a single item list. This is import for the yaml to be + # properly formatted. + if len(self._grains.get(grainKey, [])) == 1: + self._grains[grainKey] = self._grains[grainKey][0] + + def buildGrains(self, grains): + """Starts the grain building process.""" + for grain in grains: + self._parseGrainValues({grain: grains[grain]}) + + return self._createGrainsYaml() + +def run(): + maker=GrainMaker() + grainsYaml = maker.buildGrains(__pillar__["grains"]) + + return {'/etc/salt/grains': + {'file.managed': [ + {'contents': grainsYaml}, + {'user': 'root'}, + {'group': 'root'}, + {'mode': '644'}] + } + } diff --git a/pillar.example b/pillar.example new file mode 100644 index 0000000..100b9b8 --- /dev/null +++ b/pillar.example @@ -0,0 +1,44 @@ +#################################################################### +# Grains pillar: # +# Only compound matches are uses # +# # +# Matches with single value will appear in /etc/salt/grains as: # +# grain: value # +# # +# Matches with multiple values will appear in /etc/salt/grains as: # +# grain: # +# - value1 # +# - value2 # +#################################################################### +grains: + # Grain + environment: + # Grain value + prod: + # Compound match to apply the grain and value to + - G@environment:prod + qa: + - G@environment:qa + dev: + - G@environment:dev + testing: + - G@environment:testing + datacenter: + phx: + - G@id:*phx* + ewr: + - G@id:*ewr* + roles: + database: + - G@id:db* + memcache: + - G@id:memcache* + docker: + - G@id:docker* + logserver: + - G@id:log* + web: + - G@id:web* + subrole: + primary: + - E@web[0-9]+-(phx|ewr).example.com or E@db[0-9]+-(phx|ewr).example.com