Initial commit
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
new file mode 100644
index 0000000..6317b51
--- /dev/null
+++ b/CHANGELOG.rst
@@ -0,0 +1,14 @@
+
+============
+salt-formula
+============
+
+0.0.2
+-----
+
+- Graphing of salt minion states
+
+0.0.1
+-----
+
+- Initial state for installing Salt master
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6f2b42f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2014-2015 tcp cloud a.s.
+
+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.
\ No newline at end of file
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..788cf53
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,323 @@
+
+====
+Salt
+====
+
+Salt is a new approach to infrastructure management. Easy enough to get running in minutes, scalable enough to manage tens of thousands of servers, and fast enough to communicate with them in seconds.
+
+Salt delivers a dynamic communication bus for infrastructures that can be used for orchestration, remote execution, configuration management and much more.
+
+Sample pillars
+==============
+
+Salt master
+-----------
+
+Salt master with base environment and pillar metadata source
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ enabled: true
+ command_timeout: 5
+ worker_threads: 2
+ pillar:
+ engine: salt
+ source:
+ engine: git
+ address: 'git@repo.domain.com:salt/pillar-demo.git'
+ branch: 'master'
+ base_environment: prd
+ environment:
+ prd:
+ enabled: true
+ formula:
+ linux:
+ source: git
+ address: 'git@repo.domain.com:salt/formula-linux.git'
+ branch: 'master'
+ salt:
+ source: git
+ address: 'git@repo.domain.com:salt/formula-salt.git'
+ branch: 'master'
+ openssh:
+ source: git
+ address: 'git@repo.domain.com:salt/formula-openssh.git'
+ branch: 'master'
+
+Simple Salt master with base environment and custom states
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ ...
+ environment:
+ base:
+ states:
+ - name: gitlab
+ source: git
+ address: 'git@repo.domain.cz:salt/state-gitlab.git'
+ branch: 'master'
+ formulas:
+ ...
+
+Salt master with reclass ENC
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ enabled: true
+ ...
+ pillar:
+ engine: reclass
+ data_dir: /srv/salt/reclass
+
+Salt master with windows repository
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ enabled: true
+ ...
+ windows_repo:
+ type: git
+ address: 'git@repo.domain.com:salt/win-packages.git'
+
+Salt master with API
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ ...
+ api:
+ enabled: true
+ port: 8000
+
+Salt master with preset minions
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ enabled: true
+ ...
+ minions:
+ - name: 'node1.system.location.domain.com'
+
+Salt master syndicate master of masters
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ enabled: true
+ ...
+ syndic:
+ mode: master
+
+Salt master syndicate (client) master
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ enabled: true
+ ...
+ syndicate:
+ mode: client
+ host: master-master
+
+Salt master with custom handlers
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ enabled: true
+ command_timeout: 5
+ worker_threads: 2
+ environments:
+ - name: base
+ states:
+ - source: git
+ address: 'git@repo.domain.com:salt/state-ubuntu.git'
+ branch: 'master'
+ pillar:
+ source: git
+ address: 'git@repo.domain.com:salt/pillar-demo.git'
+ branch: 'master'
+ handlers:
+ name: logstash
+ type: udp
+ bind:
+ host: 127.0.0.1
+ port: 9999
+ minion:
+ handlers:
+ - engine: udp
+ bind:
+ host: 127.0.0.1
+ port: 9999
+ - engine: zmq
+ bind:
+ host: 127.0.0.1
+ port: 9999
+
+Salt minion
+-----------
+
+Simplest Salt minion
+
+.. code-block:: yaml
+
+ salt:
+ minion:
+ enabled: true
+ master:
+ host: master.domain.com
+
+Multi-master Salt minion
+
+.. code-block:: yaml
+
+ salt:
+ minion:
+ enabled: true
+ masters:
+ - host: master1.domain.com
+ - host: master2.domain.com
+
+Salt minion with salt mine options
+
+ salt:
+ minion:
+ enabled: true
+ master:
+ host: master.domain.com
+ mine:
+ interval: 60
+ module:
+ grains.items: []
+ network.interfaces: []
+
+Salt minion with graphing dependencies
+
+.. code-block:: yaml
+
+ salt:
+ minion:
+ enabled: true
+ graph_states: true
+ master:
+ host: master.domain.com
+
+Salt control (cloud/virt)
+-------------------------
+
+Salt cloud with local OpenStack insecure (ignoring SSL cert errors) provider
+
+.. code-block:: yaml
+
+ salt:
+ control:
+ enabled: true
+ provider:
+ openstack_account:
+ engine: openstack
+ insecure: true
+ region: RegionOne
+ identity_url: 'https://10.0.0.2:35357'
+ tenant: devops
+ user: user
+ password: 'password'
+ fixed_networks:
+ - 123d3332-18be-4d1d-8d4d-5f5a54456554e
+ floating_networks:
+ - public
+ ignore_cidr: 192.168.0.0/16
+
+Salt cloud with Digital Ocean provider
+
+.. code-block:: yaml
+
+ salt:
+ control:
+ enabled: true
+ provider:
+ dony1:
+ engine: digital_ocean
+ region: New York 1
+ client_key: xxxxxxx
+ api_key: xxxxxxx
+
+Salt cloud with cluster definition
+
+.. code-block:: yaml
+
+ salt:
+ control:
+ enabled: true
+ cluster:
+ devops_ase:
+ config:
+ engine: salt
+ host: 147.32.120.1
+ node:
+ proxy1.ase.cepsos.cz:
+ provider: cepsos_devops
+ image: Ubuntu12.04 x86_64
+ size: m1.medium
+ node1.ase.cepsos.cz:
+ provider: cepsos_devops
+ image: Ubuntu12.04 x86_64
+ size: m1.medium
+ node2.ase.cepsos.cz:
+ provider: cepsos_devops
+ image: Ubuntu12.04 x86_64
+ size: m1.medium
+ node3.ase.cepsos.cz:
+ provider: cepsos_devops
+ image: Ubuntu12.04 x86_64
+ size: m1.medium
+
+Usage
+=====
+
+Working with salt-cloud
+
+.. code-block:: bash
+
+ salt-cloud -m /path/to/map --assume-yes
+
+Debug LIBCLOUD for salt-cloud connection
+
+.. code-block:: bash
+
+ export LIBCLOUD_DEBUG=/dev/stderr; salt-cloud --list-sizes provider_name --log-level all
+
+Read more
+=========
+
+* http://salt.readthedocs.org/en/latest/
+* https://github.com/DanielBryan/salt-state-graph
+* http://karlgrz.com/testing-salt-states-rapidly-with-docker/
+* https://mywushublog.com/2013/03/configuration-management-with-salt-stack/
+* http://russell.ballestrini.net/replace-the-nagios-scheduler-and-nrpe-with-salt-stack/
+* https://github.com/saltstack-formulas/salt-formula
+* http://docs.saltstack.com/en/latest/topics/tutorials/multimaster.html
+
+salt-cloud
+----------
+
+* http://www.blog.sandro-mathys.ch/2013/07/setting-user-password-when-launching.html
+* http://cloudinit.readthedocs.org/en/latest/topics/examples.html
+* http://salt-cloud.readthedocs.org/en/latest/topics/install/index.html
+* http://docs.saltstack.com/topics/cloud/digitalocean.html
+* http://salt-cloud.readthedocs.org/en/latest/topics/rackspace.html
+* http://salt-cloud.readthedocs.org/en/latest/topics/map.html
+* http://docs.saltstack.com/en/latest/topics/tutorials/multimaster.html
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..3b04cfb
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.2
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..02a9fbd
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,11 @@
+salt-formula-salt (0.2) trusty; urgency=medium
+
+ * First public release
+
+ -- Filip Pytloun <filip.pytloun@tcpcloud.eu> Tue, 06 Oct 2015 16:38:53 +0200
+
+salt-formula-salt (0.1) trusty; urgency=medium
+
+ * Initial release
+
+ -- Ales Komarek <ales.komarek@tcpcloud.eu> Thu, 13 Aug 2015 23:23:41 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..6073f20
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,15 @@
+Source: salt-formula-salt
+Maintainer: Ales Komarek <ales.komarek@tcpcloud.eu>
+Section: admin
+Priority: optional
+Build-Depends: debhelper (>= 9)
+Standards-Version: 3.9.6
+Homepage: http://www.tcpcloud.eu
+Vcs-Browser: https://github.com/tcpcloud/salt-formula-salt
+Vcs-Git: https://github.com/tcpcloud/salt-formula-salt.git
+
+Package: salt-formula-salt
+Architecture: all
+Depends: ${misc:Depends}, salt-master, reclass
+Description: Salt salt formula
+ Install and configure Salt masters and minions.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..79abd6c
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,15 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: salt-formula-salt
+Upstream-Contact: Ales Komarek <ales.komarek@tcpcloud.eu>
+Source: https://github.com/tcpcloud/salt-formula-salt
+
+Files: *
+Copyright: 2014-2015 tcp cloud a.s.
+License: Apache-2.0
+ Copyright (C) 2014-2015 tcp cloud a.s.
+ .
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ .
+ On a Debian system you can find a copy of this license in
+ /usr/share/common-licenses/Apache-2.0.
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..d585829
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,3 @@
+README.rst
+CHANGELOG.rst
+VERSION
diff --git a/debian/install b/debian/install
new file mode 100644
index 0000000..4eb02c4
--- /dev/null
+++ b/debian/install
@@ -0,0 +1,2 @@
+salt/* /usr/share/salt-formulas/env/salt/
+metadata/service/* /usr/share/salt-formulas/reclass/service/salt/
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..abde6ef
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,5 @@
+#!/usr/bin/make -f
+
+%:
+ dh $@
+
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/metadata/service/master/cluster.yml b/metadata/service/master/cluster.yml
new file mode 100644
index 0000000..404a8a9
--- /dev/null
+++ b/metadata/service/master/cluster.yml
@@ -0,0 +1,10 @@
+applications:
+- salt
+- git
+- openssh
+parameters:
+ salt:
+ master:
+ enabled: true
+ command_timeout: 5
+ worker_threads: 2
diff --git a/metadata/service/master/single.yml b/metadata/service/master/single.yml
new file mode 100644
index 0000000..58f437e
--- /dev/null
+++ b/metadata/service/master/single.yml
@@ -0,0 +1,13 @@
+applications:
+- salt
+- git
+- openssh
+parameters:
+ _param:
+ salt_master_base_environment: dev
+ salt:
+ master:
+ enabled: true
+ command_timeout: 5
+ worker_threads: 2
+ base_environment: ${_param:salt_master_base_environment}
\ No newline at end of file
diff --git a/metadata/service/minion/cluster.yml b/metadata/service/minion/cluster.yml
new file mode 100644
index 0000000..fbb64dc
--- /dev/null
+++ b/metadata/service/minion/cluster.yml
@@ -0,0 +1,13 @@
+applications:
+- salt
+parameters:
+ salt:
+ minion:
+ enabled: true
+ master:
+ host: ${_param:salt_master_host}
+ mine:
+ interval: 60
+ module:
+ grains.items: []
+ network.interfaces: []
diff --git a/metadata/service/minion/local.yml b/metadata/service/minion/local.yml
new file mode 100644
index 0000000..6739f17
--- /dev/null
+++ b/metadata/service/minion/local.yml
@@ -0,0 +1,10 @@
+applications:
+- salt
+parameters:
+ salt:
+ minion:
+ enabled: true
+ local: true
+ pillar:
+ engine: reclass
+ data_dir: /srv/salt/reclass
diff --git a/metadata/service/minion/master.yml b/metadata/service/minion/master.yml
new file mode 100644
index 0000000..fbb64dc
--- /dev/null
+++ b/metadata/service/minion/master.yml
@@ -0,0 +1,13 @@
+applications:
+- salt
+parameters:
+ salt:
+ minion:
+ enabled: true
+ master:
+ host: ${_param:salt_master_host}
+ mine:
+ interval: 60
+ module:
+ grains.items: []
+ network.interfaces: []
diff --git a/salt/api.sls b/salt/api.sls
new file mode 100644
index 0000000..5d53d9d
--- /dev/null
+++ b/salt/api.sls
@@ -0,0 +1,21 @@
+{%- from "salt/map.jinja" import api with context %}
+{%- if api.enabled %}
+
+include:
+- salt.master
+
+salt_api_packages:
+ pkg.installed
+ - names: {{ api.pkgs }}
+ - require:
+ - pkg: salt_master_packages
+
+salt_api_service:
+ service.running:
+ - name: salt-api
+ - require:
+ - pkg: salt_api_packages
+ - watch:
+ - file: /etc/salt/master
+
+{%- endif %}
\ No newline at end of file
diff --git a/salt/control/cluster.sls b/salt/control/cluster.sls
new file mode 100644
index 0000000..de9d2a2
--- /dev/null
+++ b/salt/control/cluster.sls
@@ -0,0 +1,47 @@
+{% from "salt/map.jinja" import control with context %}
+{%- if control.enabled %}
+
+/srv/salt/cloud/maps:
+ file.directory:
+ - makedirs: true
+
+/srv/salt/cloud/userdata:
+ file.directory:
+ - makedirs: true
+
+{%- for cluster_name, cluster in control.cluster.iteritems() %}
+
+/srv/salt/cloud/maps/{{ cluster_name }}:
+ file.managed:
+ - source: salt://salt/files/map
+ - user: root
+ - group: root
+ - template: jinja
+ - require:
+ - file: /srv/salt/cloud/maps
+ - defaults:
+ cluster_name: "{{ cluster_name }}"
+
+/srv/salt/cloud/userdata/{{ cluster_name }}:
+ file.directory:
+ - makedirs: true
+
+{%- for node_name, node in cluster.node.iteritems() %}
+
+/srv/salt/cloud/userdata/{{cluster_name }}/{{ node_name }}.conf:
+ file.managed:
+ - source: salt://salt/files/userdata
+ - user: root
+ - group: root
+ - template: jinja
+ - require:
+ - file: /srv/salt/cloud/userdata/{{ cluster_name }}
+ - defaults:
+ cluster_name: "{{ cluster_name }}"
+ node_name: "{{ node_name }}"
+
+{%- endfor %}
+
+{%- endfor %}
+
+{%- endif %}
\ No newline at end of file
diff --git a/salt/control/init.sls b/salt/control/init.sls
new file mode 100644
index 0000000..1feb678
--- /dev/null
+++ b/salt/control/init.sls
@@ -0,0 +1,4 @@
+include:
+- salt.control.service
+- salt.control.provider
+- salt.control.cluster
\ No newline at end of file
diff --git a/salt/control/provider.sls b/salt/control/provider.sls
new file mode 100644
index 0000000..09a5452
--- /dev/null
+++ b/salt/control/provider.sls
@@ -0,0 +1,18 @@
+{% from "salt/map.jinja" import control with context %}
+{%- if control.enabled %}
+
+/etc/salt/cloud.providers:
+ file.managed:
+ - source: salt://salt/files/providers.conf
+ - user: root
+ - group: root
+ - template: jinja
+
+/etc/salt/cloud.profiles:
+ file.managed:
+ - source: salt://salt/files/profiles.conf
+ - user: root
+ - group: root
+ - template: jinja
+
+{%- endif %}
\ No newline at end of file
diff --git a/salt/control/service.sls b/salt/control/service.sls
new file mode 100644
index 0000000..2acab7b
--- /dev/null
+++ b/salt/control/service.sls
@@ -0,0 +1,26 @@
+{% from "salt/map.jinja" import control with context %}
+{%- if control.enabled %}
+
+{%- if control.pkgs is defined and control.pkgs|length > 0 %}
+
+salt_control_packages:
+ pkg.installed:
+ - names: {{ control.pkgs }}
+
+{%- else %}
+{# No system packages defined, install with pip #}
+
+salt_control_packages:
+ pkg.installed:
+ - name: python-pip
+
+{%- for package in control.python_pkgs %}
+{{ package }}:
+ pip.installed:
+ - require:
+ - pkg: salt_control_packages
+{%- endfor %}
+
+{%- endif %}
+
+{%- endif %}
diff --git a/salt/files/map b/salt/files/map
new file mode 100644
index 0000000..90a0888
--- /dev/null
+++ b/salt/files/map
@@ -0,0 +1,8 @@
+{%- from "salt/map.jinja" import control with context %}
+
+{%- set cluster = salt['pillar.get']('salt:control:cluster:'+cluster_name) %}
+
+{%- for node_name, node in cluster.node.iteritems() %}
+{{ node_name }}.{{ cluster.domain }}:
+- {{ node_name }}.{{ cluster.domain }}
+{%- endfor %}
diff --git a/salt/files/master.conf b/salt/files/master.conf
new file mode 100644
index 0000000..48322e9
--- /dev/null
+++ b/salt/files/master.conf
@@ -0,0 +1,120 @@
+{%- from "salt/map.jinja" import master with context %}
+{%- from "linux/map.jinja" import system with context %}
+
+worker_threads: {{ master.worker_threads }}
+timeout: {{ master.command_timeout }}
+
+{%- if master.system is defined %}
+
+file_roots:
+ base:
+ - /srv/salt/env/{{ master.system.environment }}
+ {%- for formula_name, formula in master.system.get('formula', {}).iteritems() %}
+ - /srv/salt/env/{{ master.system.environment }}/{{ formula_name }}
+ {%- endfor %}
+ {{ master.system.environment }}:
+ - /srv/salt/env/{{ master.system.environment }}
+ {%- for formula_name, formula in master.system.get('formula', {}).iteritems() %}
+ - /srv/salt/env/{{ master.system.environment }}/{{ formula_name }}
+ {%- endfor %}
+
+{%- else %}
+
+file_roots:
+ {%- for environment_name, environment in master.get('environment', {}).iteritems() %}
+ {%- if master.base_environment == environment_name %}
+ base:
+ - /srv/salt/env/{{ environment_name }}
+ {%- endif %}
+ {{ environment_name }}:
+ - /srv/salt/env/{{ environment_name }}
+ {%- endfor %}
+
+{%- endif %}
+
+pillar_opts: False
+
+{%- if master.accept_policy == 'open_mode' %}
+open_mode: True
+{%- endif %}
+
+{%- if master.accept_policy == 'auto_accept' %}
+auto_accept: True
+{%- endif %}
+
+{%- if master.pillar.engine == 'salt' %}
+
+pillar_roots:
+ base:
+ - /srv/salt/pillar
+
+{%- endif %}
+
+{%- if master.pillar.engine == 'reclass' %}
+
+reclass: &reclass
+ storage_type: yaml_fs
+ inventory_base_uri: /srv/salt/reclass
+
+ext_pillar:
+ - reclass: *reclass
+
+master_tops:
+ reclass: *reclass
+
+{%- endif %}
+
+{%- if master.acl is defined %}
+
+client_acl:
+ {%- for acl in master.acl %}
+ {{ acl.name }}:
+ {%- for right in acl.rights %}
+ - {{ right }}
+ {%- endfor %}
+ {%- endfor %}
+
+{%- endif %}
+
+{%- if master.bind.api is defined %}
+
+rest_cherrypy:
+ port: {{ master.api.port }}
+ ssl_crt: /etc/ssl/certs/{{ system.name }}.{{ system.domain }}.crt
+ ssl_key: /etc/ssl/private/{{ system.name }}.{{ system.domain }}.key
+ {%- if pillar.halite is defined %}
+ static: /srv/halite/halite
+ app: /srv/halite/halite/index.html
+ {%- endif %}
+ debug: True
+
+{%- endif %}
+
+{%- for handler in pillar.salt.minion.get("handlers", []) %}
+
+{%- if handler.engine == "udp"%}
+logstash_udp_handler:
+ host: {{ handler.host }}
+ port: {{ handler.port }}
+ version: 1
+{%- endif %}
+
+{%- if handler.engine == "zmq"%}
+logstash_zmq_handler:
+ address: tcp://{{ handler.host }}:{{ handler.port }}
+ version: 1
+{%- endif %}
+
+{%- endfor %}
+
+{%- if master.syndic is defined %}
+
+{% if master.syndic.mode == 'master' %}
+order_masters: True
+{%- endif %}
+
+{% if master.syndic.mode == 'client' %}
+syndic_master: {{ master.syndic.host }}
+{%- endif %}
+
+{%- endif %}
diff --git a/salt/files/minion.conf b/salt/files/minion.conf
new file mode 100644
index 0000000..fdf9bd7
--- /dev/null
+++ b/salt/files/minion.conf
@@ -0,0 +1,143 @@
+{%- from "salt/map.jinja" import minion with context %}
+{%- from "linux/map.jinja" import system with context %}
+
+{%- if minion.masters is defined %}
+master:
+{%- for master in minion.masters %}
+- {{ master.host }}
+{%- endfor %}
+{%- else %}
+master: {{ minion.master.host }}
+{%- endif %}
+
+id: {{ system.name }}.{{ system.domain }}
+
+grains:
+ {%- if minion.get('manage_roles', True) %}
+ roles:
+ {%- for key, value in pillar.items() %}
+ {%- if key != 'master' and key != 'system' and key != 'public_keys' and key != 'private_keys' and key != 'known_hosts' and key != '__reclass__' and key != '_secret' %}
+ {%- for subkey, subvalue in value.iteritems() %}
+ {%- if subvalue.enabled is defined %}
+ {%- if subvalue.enabled %}
+ - {{key}}.{{ subkey }}
+ {%- endif %}
+ {%- endif %}
+ {%- endfor %}
+ {%- endif %}
+ {%- endfor %}
+ {%- endif %}
+ services:
+ {%- for key in pillar.__reclass__.applications %}
+ - {{key}}
+ {%- endfor %}
+
+grains_dirs:
+- /var/lib/salt/grains
+
+{%- if minion.mine is defined %}
+
+mine_functions:
+{%- for salt_module, salt_functions in minion.mine.module.iteritems() %}
+ {{ salt_module }}: {{ salt_functions }}
+{%- endfor %}
+mine_interval: {{ minion.mine.get('interval', 30) }}
+
+{%- endif %}
+
+
+{%- if minion.sentry is defined %}
+sentry_handler:
+{% for server in minion.sentry.servers %}
+ servers:
+ - {{ server }}
+{% endfor %}
+ project: {{ pillar.salt.minion.sentry.project }}
+ public_key: {{ pillar.salt.minion.sentry.public_key }}
+ secret_key: {{ pillar.salt.minion.sentry.secret_key }}
+ {% if pillar.salt.minion.sentry.log_level is defined %}
+ log_level: {{ pillar.salt.minion.sentry.log_level }}
+ {%- endif %}
+{%- endif %}
+
+{%- if pillar.get('mysql', {}).server is defined %}
+mysql.unix_socket: /var/run/mysqld/mysqld.sock
+{%- if pillar.mysql.server.admin is defined %}
+mysql.user: '{{ pillar.mysql.server.admin.user }}'
+mysql.pass: '{{ pillar.mysql.server.admin.password }}'
+{%- else %}
+mysql.user: 'root'
+mysql.pass: ''
+{%- endif %}
+mysql.db: 'mysql'
+mysql.charset: 'utf8'
+{%- endif %}
+
+{%- if pillar.get('galera', {}).master is defined %}
+mysql.unix_socket: /var/run/mysqld/mysqld.sock
+mysql.user: '{{ pillar.galera.master.admin.user }}'
+mysql.pass: '{{ pillar.galera.master.admin.password }}'
+mysql.db: 'mysql'
+mysql.charset: 'utf8'
+{%- endif %}
+
+{%- if pillar.get('mongodb', {}).server is defined %}
+mongodb.host: 'localhost'
+mongodb.port: {{ pillar.mongodb.server.bind.port }}
+mongodb.user: '{{ pillar.mongodb.server.admin.user }}'
+mongodb.password: '{{ pillar.mongodb.server.admin.password }}'
+{%- endif %}
+
+{%- if pillar.get('galera', {}).slave is defined %}
+mysql.unix_socket: /var/run/mysqld/mysqld.sock
+mysql.user: '{{ pillar.galera.slave.admin.user }}'
+mysql.pass: '{{ pillar.galera.slave.admin.password }}'
+mysql.db: 'mysql'
+mysql.charset: 'utf8'
+{%- endif %}
+
+{%- if pillar.get('postgresql', {}).server is defined %}
+postgres.user: 'postgres'
+postgres.pass: ''
+postgres.db: 'template1'
+{%- endif %}
+
+{%- if pillar.get('gitlab', {}).client is defined %}
+gitlab.url: 'https://{{ pillar.gitlab.client.server.host }}/'
+gitlab.token: '{{ pillar.gitlab.client.server.token }}'
+{%- elif pillar.get('gitlab', {}).server is defined %}
+gitlab.url: 'https://{{ pillar.gitlab.server.server_name }}/'
+gitlab.token: '{{ pillar.gitlab.server.token }}'
+{%- endif %}
+
+{%- if pillar.get('keystone', {}).get('server', {'enabled': False } ).enabled %}
+keystone.token: '{{ pillar.keystone.server.service_token }}'
+keystone.endpoint: 'http://{{ pillar.keystone.server.bind.private_address }}:{{ pillar.keystone.server.bind.private_port }}/v2.0'
+{%- elif pillar.get('keystone', {}).get('client', {'enabled': False } ).enabled %}
+{%- if pillar.keystone.client.server.service_token is defined %}
+keystone.token: '{{ pillar.keystone.client.server.service_token }}'
+keystone.endpoint: 'http://{{ pillar.keystone.client.server.host }}:{{ pillar.keystone.client.server.private_port }}/v2.0'
+{%- else %}
+keystone.user: '{{ pillar.keystone.client.server.user }}'
+keystone.password: '{{ pillar.keystone.client.server.password }}'
+keystone.tenant: '{{ pillar.keystone.client.server.tenant }}'
+keystone.auth_url: 'http://{{ pillar.keystone.client.server.host }}:{{ pillar.keystone.client.server.public_port }}/v2.0/'
+{%- endif %}
+{%- endif %}
+
+{%- for handler in pillar.salt.minion.get("handlers", []) %}
+
+{%- if handler.engine == "udp"%}
+logstash_udp_handler:
+ host: {{ handler.host }}
+ port: {{ handler.port }}
+ version: 1
+{%- endif %}
+
+{%- if handler.engine == "zmq"%}
+logstash_zmq_handler:
+ address: tcp://{{ handler.host }}:{{ handler.port }}
+ version: 1
+{%- endif %}
+
+{%- endfor %}
\ No newline at end of file
diff --git a/salt/files/profiles.conf b/salt/files/profiles.conf
new file mode 100644
index 0000000..6baa6ff
--- /dev/null
+++ b/salt/files/profiles.conf
@@ -0,0 +1,25 @@
+{% from "salt/map.jinja" import control with context %}
+
+{%- for cluster_name, cluster in control.cluster.iteritems() %}
+
+{%- for node_name, node in cluster.node.iteritems() %}
+
+{{ node_name }}.{{ cluster.domain }}:
+ provider: {{ node.provider }}
+ image: {{ node.image }}
+ size: {{ node.size }}
+ minion:
+ master: {{ cluster.config.host }}
+ id: {{ node_name }}.{{ cluster.domain }}
+ {%- if node.userdata is defined %}
+ userdata_file: /srv/salt/cloud/userdata/{{ cluster_name }}/{{ node_name }}.conf
+ {%- endif %}
+ {%- if 'ubuntu' in node.image|lower %}
+ ssh_username: ubuntu
+ {%- elif 'centos' in node.image|lower %}
+ ssh_username: cloud-user
+ {%- endif %}
+
+{%- endfor %}
+
+{%- endfor %}
diff --git a/salt/files/providers.conf b/salt/files/providers.conf
new file mode 100644
index 0000000..a764137
--- /dev/null
+++ b/salt/files/providers.conf
@@ -0,0 +1,43 @@
+{% from "salt/map.jinja" import control with context %}
+{%- for provider_name, provider in control.provider.iteritems() %}
+
+{{ provider_name }}:
+ provider: {{ provider.engine }}
+ {%- if provider.insecure is defined %}
+ insecure: true
+ {%- endif %}
+ {%- if provider.engine == 'openstack' %}
+ identity_url: '{{ provider.identity_url }}'
+ {%- if provider.compute_name is defined %}
+ compute_name: {{ provider.get('compute_name', 'nova') }}
+ {%- endif %}
+ protocol: ipv4
+ compute_region: {{ provider.region }}
+ tenant: {{ provider.tenant }}
+ user: {{ provider.user }}
+ {%- if provider.api_key is defined %}
+ apikey: {{ provider.api_key }}
+ {%- elif provider.password is defined %}
+ password: {{ provider.password }}
+ {%- endif %}
+ ssh_key_name: salt-cloud
+ ssh_key_file: /root/.ssh/id_rsa
+ ssh_interface: {{ provider.get('interface', 'private') }}_ips
+ networks:
+ - fixed:
+ {%- for net in provider.fixed_networks %}
+ - {{ net }}
+ {%- endfor %}
+ - floating:
+ {%- for net in provider.floating_networks %}
+ - {{ net }}
+ {%- endfor %}
+ {%- if provider.ignore_cidr is defined %}
+ ignore_cidr: {{ provider.ignore_cidr }}
+ {%- endif %}
+ {%- elif provider.engine == 'digital_ocean' %}
+ {#- location: {{ provider.region }} #}
+ personal_access_token: {{ provider.api_key }}
+ {%- endif %}
+
+{%- endfor %}
diff --git a/salt/files/salt-api.wsgi b/salt/files/salt-api.wsgi
new file mode 100644
index 0000000..07bb35f
--- /dev/null
+++ b/salt/files/salt-api.wsgi
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+import cherrypy
+
+import sys
+
+sys.path.append('/srv/salt-api')
+
+from saltapi.netapi.rest_cherrypy import app
+
+def bootstrap_app():
+ '''
+ Grab the opts dict of the master config by trying to import Salt
+ '''
+ import salt.client
+ opts = salt.client.LocalClient().opts
+ return app.get_app(opts)
+
+def get_application(*args):
+ '''
+ Returns a WSGI application function. If you supply the WSGI app and config
+ it will use that, otherwise it will try to obtain them from a local Salt
+ installation
+ '''
+ opts_tuple = args
+
+ def wsgi_app(environ, start_response):
+ root, _, conf = opts_tuple or bootstrap_app()
+
+ cherrypy.tree.mount(root, '/', conf)
+ return cherrypy.tree(environ, start_response)
+
+ return wsgi_app
+
+application = get_application()
diff --git a/salt/files/salt-state-graph.py b/salt/files/salt-state-graph.py
new file mode 100644
index 0000000..243d561
--- /dev/null
+++ b/salt/files/salt-state-graph.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+"""
+salt-state-graph
+
+A tool that ingests the YAML representing the Salt highstate (or sls state) for
+a single minion and produces a program written in DOT.
+
+The tool is useful for visualising the dependency graph of a Salt highstate.
+"""
+from pydot import Dot, Node, Edge
+import yaml
+import sys
+
+
+def find(obj, find_key):
+ """
+ Takes a list and a set. Returns a list of all matching objects.
+
+ Uses find_inner to recursively traverse the data structure, finding objects
+ with keyed by find_key.
+ """
+
+ all_matches = [find_inner(item, find_key) for item in obj]
+ final = [item for sublist in all_matches for item in sublist]
+
+ return final
+
+
+def find_inner(obj, find_key):
+ """
+ Recursively search through the data structure to find objects
+ keyed by find_key.
+ """
+ results = []
+
+ if not hasattr(obj, '__iter__'):
+ # not a sequence type - return nothing
+ # this excludes strings
+ return results
+
+ if isinstance(obj, dict):
+ # a dict - check each key
+ for key, prop in obj.iteritems():
+ if key == find_key:
+ results.extend(prop)
+ else:
+ results.extend(find_inner(prop, find_key))
+ else:
+ # a list / tuple - check each item
+ for i in obj:
+ results.extend(find_inner(i, find_key))
+
+ return results
+
+
+def make_node_name(state_type, state_label):
+ return "{0} - {1}".format(state_type.upper(), state_label)
+
+
+def find_edges(states, relname):
+ """
+ Use find() to recursively find objects at keys matching
+ relname, yielding a node name for every result.
+ """
+ try:
+ deps = find(states, relname)
+ for dep in deps:
+ for dep_type, dep_name in dep.iteritems():
+ yield make_node_name(dep_type, dep_name)
+ except AttributeError as e:
+ sys.stderr.write("Bad state: {0}\n".format(str(states)))
+ raise e
+
+
+def main(input):
+ state_obj = yaml.load(input)
+ graph = Dot("states", graph_type='digraph')
+
+ rules = {
+ 'require': {'color': 'blue'},
+ 'require_in': {'color': 'blue', 'reverse': True},
+ 'watch': {'color': 'red'},
+ 'watch_in': {'color': 'red', 'reverse': True},
+ }
+
+ for top_key, props in state_obj.iteritems():
+ # Add a node for each state type embedded in this state
+ # keys starting with underscores are not candidates
+
+ if top_key == '__extend__':
+ # TODO - merge these into the main states and remove them
+ sys.stderr.write(
+ "Removing __extend__ states:\n{0}\n".format(str(props)))
+ continue
+
+ for top_key_type, states in props.iteritems():
+ if top_key_type[:2] == '__':
+ continue
+
+ node_name = make_node_name(top_key_type, top_key)
+ graph.add_node(Node(node_name))
+
+ for edge_type, ruleset in rules.iteritems():
+ for relname in find_edges(states, edge_type):
+ if 'reverse' in ruleset and ruleset['reverse']:
+ graph.add_edge(Edge(
+ node_name, relname, color=ruleset['color']))
+ else:
+ graph.add_edge(Edge(
+ relname, node_name, color=ruleset['color']))
+
+ graph.write('/dev/stdout')
+
+if __name__ == '__main__':
+ main(sys.stdin)
diff --git a/salt/files/salt-state-graph.sh b/salt/files/salt-state-graph.sh
new file mode 100644
index 0000000..a7c0fdb
--- /dev/null
+++ b/salt/files/salt-state-graph.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+salt-call state.show_highstate --out yaml > ./highstate
+python salt-state-graph.py < ./highstate > ./highstate.dot
+dot -Tpng < ./highstate.dot -o ./highstate.png
+dot -Tsvg < ./highstate.dot -o ./highstate.svg
diff --git a/salt/files/salt.gpg b/salt/files/salt.gpg
new file mode 100644
index 0000000..11709fe
--- /dev/null
+++ b/salt/files/salt.gpg
@@ -0,0 +1,13 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: SKS 1.1.4
+Comment: Hostname: keyserver.ubuntu.com
+
+mI0ETs4aowEEALDRpPyebQ5JlJNmleRzZYzxO4Ia8hpCSHzLm6DaMvXcFesfP4OTN0J9JjAv
+xbRxw8ROBz4SZ4iPhzPOZlXHBaI/5BF8Cc8CFW/HDqhPNH3qdOC9Te2q0QZgzd7WS94GXgzK
+nKCi1bmZ5pCvoJEvu3XK24/jmfLijp/1iO46xuofABEBAAG0HExhdW5jaHBhZCBQUEEgZm9y
+IFNhbHQgU3RhY2uIuAQTAQIAIgUCTs4aowIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQR1n6lg4nwKYQMwP9FQpta7rMNj2kgIvv3pXOr4z+Rgp3Vd8NmoHlIt6ZyigiisGfuht9
+0PyvBLlJxpqGZt7bdz5QzV3HYSkk1K/L6CzpAgC/o/LPiir/Xi4ur/tgmRp30ONGPrLvSyRk
+dv1pIkMqEekOSdTgjyvRq7+rYpqh5obYFJPoxSqDYOND9lo=
+=woTM
+-----END PGP PUBLIC KEY BLOCK-----
\ No newline at end of file
diff --git a/salt/files/sensu.conf b/salt/files/sensu.conf
new file mode 100644
index 0000000..8b2ea59
--- /dev/null
+++ b/salt/files/sensu.conf
@@ -0,0 +1,12 @@
+local_salt_master_proc:
+ command: "PATH=$PATH:/usr/lib64/nagios/plugins:/usr/lib/nagios/plugins check_procs -C salt-master -u root -c 1:10"
+ interval: 60
+ occurrences: 1
+ subscribers:
+ - local-salt-master
+local_salt_minion_proc:
+ command: "PATH=$PATH:/usr/lib64/nagios/plugins:/usr/lib/nagios/plugins check_procs -C salt-minion -u root -c 1:10"
+ interval: 60
+ occurrences: 1
+ subscribers:
+ - local-salt-minion
diff --git a/salt/files/userdata b/salt/files/userdata
new file mode 100644
index 0000000..ac3a286
--- /dev/null
+++ b/salt/files/userdata
@@ -0,0 +1,9 @@
+{%- from "salt/map.jinja" import config with context %}
+{%- set cluster = salt['pillar.get']('salt:control:cluster:'+cluster_name) %}
+{%- set node = salt['pillar.get']('salt:control:cluster:'+cluster_name+':node:'+node_name) %}
+#!/bin/bash
+curl --insecure -L http://bootstrap.saltstack.org -o install_salt.sh
+sh install_salt.sh
+echo "id: {{ node_name }}.{{ cluster.domain }}" > /etc/salt/minion.d/minion.conf
+echo "master: salt/master: {{ cluster.config.host }}" >> /etc/salt/minion.d/minion.conf
+service salt-minion restart
\ No newline at end of file
diff --git a/salt/init.sls b/salt/init.sls
new file mode 100644
index 0000000..d7a67c4
--- /dev/null
+++ b/salt/init.sls
@@ -0,0 +1,15 @@
+{%- if pillar.salt is defined %}
+include:
+{%- if pillar.salt.master is defined %}
+- salt.master
+{%- endif %}
+{%- if pillar.salt.minion is defined %}
+- salt.minion
+{%- endif %}
+{%- if pillar.salt.syndic is defined %}
+- salt.syndic
+{%- endif %}
+{%- if pillar.salt.control is defined %}
+- salt.control
+{%- endif %}
+{%- endif %}
\ No newline at end of file
diff --git a/salt/map.jinja b/salt/map.jinja
new file mode 100644
index 0000000..886404a
--- /dev/null
+++ b/salt/map.jinja
@@ -0,0 +1,120 @@
+
+{% set master = salt['grains.filter_by']({
+ 'Arch': {
+ 'pkgs': ['salt-zmq'],
+ 'service': 'salt-master',
+ 'pillar': {
+ 'engine': 'salt',
+ },
+ 'accept_policy': 'preseed',
+ 'bind': {},
+ 'formula': {},
+ 'base_environment': 'dev',
+ },
+ 'Debian': {
+ 'pkgs': ['salt-master'],
+ 'service': 'salt-master',
+ 'pillar': {
+ 'engine': 'salt',
+ },
+ 'accept_policy': 'preseed',
+ 'bind': {},
+ 'formula': {},
+ 'base_environment': 'dev',
+ },
+ 'Gentoo': {
+ 'pkgs': ['app-admin/salt'],
+ 'service': 'salt-master',
+ 'pillar': {
+ 'engine': 'salt',
+ },
+ 'accept_policy': 'preseed',
+ 'bind': {},
+ 'formula': {},
+ 'base_environment': 'dev',
+ },
+ 'MacOS': {
+ 'pkgs': ['saltstack'],
+ 'service': 'salt-master',
+ 'pillar': {
+ 'engine': 'salt',
+ },
+ 'accept_policy': 'preseed',
+ 'bind': {},
+ 'formula': {},
+ 'base_environment': 'dev',
+ },
+ 'RedHat': {
+ 'pkgs': ['salt-master'],
+ 'service': 'salt-master',
+ 'pillar': {
+ 'engine': 'salt',
+ },
+ 'accept_policy': 'preseed',
+ 'bind': {},
+ 'formula': {},
+ 'base_environment': 'dev',
+ },
+}, merge=salt['pillar.get']('salt:master')) %}
+
+{% set minion = salt['grains.filter_by']({
+ 'Arch': {
+ 'pkgs': ['salt-zmq'],
+ 'graph_pkgs': ['graphviz'],
+ 'graph_states_pkgs': ['python-pydot', 'python-yaml'],
+ 'graph_states': False,
+ 'service': 'salt-minion',
+ },
+ 'Debian': {
+ 'pkgs': ['salt-minion'],
+ 'graph_pkgs': ['graphviz'],
+ 'graph_states_pkgs': ['python-pydot', 'python-yaml'],
+ 'graph_states': False,
+ 'service': 'salt-minion',
+ },
+ 'Gentoo': {
+ 'pkgs': ['app-admin/salt'],
+ 'graph_pkgs': ['graphviz'],
+ 'graph_states_pkgs': ['python-pydot', 'python-yaml'],
+ 'graph_states': False,
+ 'service': 'salt-minion',
+ },
+ 'MacOS': {
+ 'pkgs': ['saltstack'],
+ 'graph_pkgs': ['graphviz'],
+ 'graph_states_pkgs': ['python-pydot', 'python-yaml'],
+ 'graph_states': False,
+ 'service': 'salt-minion',
+ },
+ 'RedHat': {
+ 'pkgs': ['salt-minion'],
+ 'graph_pkgs': ['graphviz'],
+ 'graph_states_pkgs': ['python-pydot', 'python-yaml'],
+ 'graph_states': False,
+ 'service': 'salt-minion',
+ },
+}, merge=salt['pillar.get']('salt:minion')) %}
+
+{% set api = salt['grains.filter_by']({
+ 'Debian': {
+ 'pkgs': ['salt-api'],
+ 'service': 'salt-api',
+ },
+ 'RedHat': {
+ 'pkgs': ['salt-api'],
+ 'service': 'salt-api',
+ },
+}, merge=salt['pillar.get']('salt:api')) %}
+
+{% set control = salt['grains.filter_by']({
+ 'Debian': {
+ 'python_pkgs': ['apache-libcloud', 'netaddr'],
+ 'pkgs': ['python-netaddr', 'python-libcloud'],
+ 'cluster': {},
+ },
+ 'RedHat': {
+ 'python_pkgs': ['apache-libcloud', 'netaddr'],
+ 'pkgs': ['python-netaddr', 'python-libcloud'],
+ 'cluster': {},
+ },
+}, merge=salt['pillar.get']('salt:control')) %}
diff --git a/salt/master/api.sls b/salt/master/api.sls
new file mode 100644
index 0000000..4583b04
--- /dev/null
+++ b/salt/master/api.sls
@@ -0,0 +1,22 @@
+{%- from "salt/map.jinja" import master with context %}
+{%- if master.enabled %}
+
+include:
+- salt.master.service
+
+salt_api_packages:
+ pkg.latest
+ - names:
+ - salt-api
+ - require:
+ - pkg: salt_master_packages
+
+salt_api_service:
+ service.running:
+ - name: salt-api
+ - require:
+ - pkg: salt_api_packages
+ - watch:
+ - file: /etc/salt/master
+
+{%- endif %}
diff --git a/salt/master/ca.sls b/salt/master/ca.sls
new file mode 100644
index 0000000..83568b7
--- /dev/null
+++ b/salt/master/ca.sls
@@ -0,0 +1,23 @@
+{%- from "salt/map.jinja" import master with context %}
+{%- if master.enabled %}
+
+{%- if pillar.django_pki is defined %}
+{%- if pillar.django_pki.server.enabled %}
+
+include:
+- salt.master.service
+
+{#
+{%- for environment_name, environment in master.environment.iteritems() %}
+
+/srv/salt/env/{{ environment_name }}/pki:
+ file.symlink:
+ - target: /srv/django_pki/site/pki
+
+{%- endfor %}
+#}
+
+{%- endif %}
+{%- endif %}
+
+{%- endif %}
\ No newline at end of file
diff --git a/salt/master/env.sls b/salt/master/env.sls
new file mode 100644
index 0000000..2dbf935
--- /dev/null
+++ b/salt/master/env.sls
@@ -0,0 +1,248 @@
+{%- from "salt/map.jinja" import master with context %}
+{%- if master.enabled %}
+
+include:
+- git.client
+- salt.master.service
+
+{%- if master.system is defined %}
+
+salt_env_{{ master.system.environment }}_dirs:
+ file.directory:
+ - names:
+ - /srv/salt/env/{{ master.system.environment }}/_modules
+ - /srv/salt/env/{{ master.system.environment }}/_states
+ - /srv/salt/env/{{ master.system.environment }}/_grains
+ - /srv/salt/env/{{ master.system.environment }}
+ - makedirs: True
+
+{%- for grain_name, grain in master.system.get('grain', {}).iteritems() %}
+
+{%- if grain.source == 'git' %}
+
+salt_master_{{ master.system.environment }}_{{ grain_name }}_grain_source:
+ git.latest:
+ - name: {{ grain.address }}
+ - target: /srv/salt/env/{{ master.system.environment }}/_extra/grain_{{ grain_name }}
+ - rev: {{ grain.revision }}
+ - require:
+ - file: salt_env_{{ master.system.environment }}_dirs
+ - pkg: git_packages
+
+/srv/salt/env/{{ master.system.environment }}/_grains/{{ grain_name }}.py:
+ file.symlink:
+ - target: /srv/salt/env/{{ master.system.environment }}/_extra/grain_{{ grain_name }}/{{ grain_name }}.py
+ - require:
+ - git: salt_master_{{ master.system.environment }}_{{ grain_name }}_grain_source
+
+{%- endif %}
+
+{%- endfor %}
+
+{%- for state_name, state in master.system.get('state', {}).iteritems() %}
+
+{%- if state.source == 'git' %}
+
+salt_master_{{ master.system.environment }}_{{ state_name }}_state_source:
+ git.latest:
+ - name: {{ state.address }}
+ - target: /srv/salt/env/{{ master.system.environment }}/_extra/state_{{ state_name }}
+ - rev: {{ state.revision }}
+ - require:
+ - file: salt_env_{{ master.system.environment }}_dirs
+ - pkg: git_packages
+
+/srv/salt/env/{{ master.system.environment }}/_modules/{{ state_name }}.py:
+ file.symlink:
+ - target: /srv/salt/env/{{ master.system.environment }}/_extra/state_{{ state_name }}/modules/{{ state_name }}.py
+ - require:
+ - git: salt_master_{{ master.system.environment }}_{{ state_name }}_state_source
+
+/srv/salt/env/{{ master.system.environment }}/_states/{{ state_name }}.py:
+ file.symlink:
+ - target: /srv/salt/env/{{ master.system.environment }}/_extra/state_{{ state_name }}/states/{{ state_name }}.py
+ - require:
+ - git: salt_master_{{ master.system.environment }}_{{ state_name }}_state_source
+
+{%- endif %}
+
+{%- endfor %}
+
+{%- for formula_name, formula in master.system.get('formula', {}).iteritems() %}
+
+{%- if formula.source == 'git' %}
+
+salt_master_{{ master.system.environment }}_{{ formula_name }}_formula_source:
+ git.latest:
+ - name: {{ formula.address }}
+ - target: /srv/salt/env/{{ master.system.environment }}/{{ formula_name }}
+ - rev: {{ formula.revision }}
+ - require:
+ - file: salt_env_{{ master.system.environment }}_dirs
+ - pkg: git_packages
+
+{%- endif %}
+
+{%- endfor %}
+
+{%- if master.system.returners is defined %}
+
+salt_master_{{ master.system.environment }}_returners:
+ git.latest:
+ - name: {{ master.system.returners.address }}
+ - target: /srv/salt/env/{{ master.system.environment }}/_returners
+ - rev: {{ master.system.returners.revision }}
+ - require:
+ - file: salt_env_{{ master.system.environment }}_dirs
+ - pkg: git_packages
+
+{%- endif %}
+
+{%- endif %}
+
+{# Start new #}
+
+{%- for environment_name, environment in master.get('environment', {}).iteritems() %}
+
+{%- if master.base_environment == environment_name %}
+
+salt_env_{{ environment_name }}_pre_dirs:
+ file.directory:
+ - names:
+ - /usr/share/salt-formulas/env/_modules
+ - /usr/share/salt-formulas/env/_states
+ - /usr/share/salt-formulas/env/_grains
+ - /usr/share/salt-formulas/env/_formulas
+ - makedirs: True
+
+salt_env_{{ environment_name }}_dirs:
+ file.symlink:
+ - name: /srv/salt/env/{{ environment_name }}
+ - target: /usr/share/salt-formulas/env
+ - require:
+ - file: salt_env_{{ environment_name }}_pre_dirs
+
+{%- else %}
+
+salt_env_{{ environment_name }}_dirs:
+ file.directory:
+ - names:
+ - /srv/salt/env/{{ environment_name }}/_modules
+ - /srv/salt/env/{{ environment_name }}/_states
+ - /srv/salt/env/{{ environment_name }}/_grains
+ - /srv/salt/env/{{ environment_name }}/_formulas
+ - makedirs: True
+
+{%- endif %}
+
+{%- for formula_name, formula in environment.get('formula', {}).iteritems() %}
+
+{%- if formula.source == 'pkg' %}
+
+salt_master_{{ environment_name }}_{{ formula.name }}_formula:
+ pkg.latest:
+ - name: {{ formula.name }}
+
+{%- elif formula.source == 'git' %}
+
+{%- if master.base_environment == environment_name %}
+
+salt_master_{{ environment_name }}_{{ formula_name }}_formula:
+ git.latest:
+ - name: {{ formula.address }}
+ - target: /usr/share/salt-formulas/env/_formulas/{{ formula_name }}
+ - rev: {{ formula.revision }}
+ - require:
+ - file: salt_env_{{ environment_name }}_dirs
+ - pkg: git_packages
+
+salt_env_{{ environment_name }}_{{ formula_name }}_link:
+ file.symlink:
+ - name: /usr/share/salt-formulas/env/{{ formula_name }}
+ - target: /usr/share/salt-formulas/env/_formulas/{{ formula_name }}/{{ formula_name }}
+ - require:
+ - file: salt_env_{{ environment_name }}_dirs
+
+{%- for grain_name, grain in formula.get('grain', {}).iteritems() %}
+
+salt_master_{{ environment_name }}_{{ grain_name }}_grain:
+ file.symlink:
+ - name: /usr/share/salt-formulas/env/_grains/{{ grain_name }}
+ - target: /usr/share/salt-formulas/env/_formulas/{{ formula_name }}/_grains/{{ grain_name }}
+
+{%- endfor %}
+
+{%- for module_name, module in formula.get('module', {}).iteritems() %}
+
+salt_master_{{ environment_name }}_{{ module_name }}_module:
+ file.symlink:
+ - name: /usr/share/salt-formulas/env/_modules/{{ module_name }}
+ - target: /usr/share/salt-formulas/env/_formulas/{{ formula_name }}/_modules/{{ module_name }}
+
+{%- endfor %}
+
+{%- for state_name, state in formula.get('state', {}).iteritems() %}
+
+salt_master_{{ environment_name }}_{{ state_name }}_state:
+ file.symlink:
+ - name: /usr/share/salt-formulas/env/_states/{{ state_name }}
+ - target: /usr/share/salt-formulas/env/_formulas/{{ formula_name }}/_states/{{ state_name }}
+
+{%- endfor %}
+
+{%- else %}
+
+salt_master_{{ environment_name }}_{{ formula_name }}_formula:
+ git.latest:
+ - name: {{ formula.address }}
+ - target: /srv/salt/env/{{ environment_name }}/_formulas/{{ formula_name }}
+ - rev: {{ formula.revision }}
+ - require:
+ - file: salt_env_{{ environment_name }}_dirs
+ - pkg: git_packages
+
+salt_env_{{ environment_name }}_{{ formula_name }}_link:
+ file.symlink:
+ - name: /srv/salt/env/{{ environment_name }}/{{ formula_name }}
+ - target: /srv/salt/env/{{ environment_name }}/_formulas/{{ formula_name }}/{{ formula_name }}
+ - require:
+ - file: salt_env_{{ environment_name }}_dirs
+
+{%- for grain_name, grain in formula.get('grain', {}).iteritems() %}
+
+salt_master_{{ environment_name }}_{{ grain_name }}_grain:
+ file.symlink:
+ - name: /srv/salt/env/{{ environment_name }}/_grains/{{ grain_name }}
+ - target: /srv/salt/env/{{ environment_name }}/_formulas/{{ formula_name }}/_grains/{{ grain_name }}
+
+{%- endfor %}
+
+{%- for module_name, module in formula.get('module', {}).iteritems() %}
+
+salt_master_{{ environment_name }}_{{ module_name }}_module:
+ file.symlink:
+ - name: /srv/salt/env/{{ environment_name }}/_grains/{{ module_name }}
+ - target: /srv/salt/env/{{ environment_name }}/_formulas/{{ formula_name }}/_grains/{{ module_name }}
+
+{%- endfor %}
+
+{%- for state_name, state in formula.get('state', {}).iteritems() %}
+
+salt_master_{{ environment_name }}_{{ state_name }}_state:
+ file.symlink:
+ - name: /srv/salt/env/{{ environment_name }}/_grains/{{ state_name }}
+ - target: /srv/salt/env/{{ environment_name }}/_formulas/{{ formula_name }}/_grains/{{ state_name }}
+
+{%- endfor %}
+
+{%- endif %}
+
+{%- endif %}
+
+{%- endfor %}
+
+{%- endfor %}
+
+{# end new #}
+
+{%- endif %}
\ No newline at end of file
diff --git a/salt/master/init.sls b/salt/master/init.sls
new file mode 100644
index 0000000..b4e4142
--- /dev/null
+++ b/salt/master/init.sls
@@ -0,0 +1,7 @@
+include:
+- salt.master.service
+- salt.master.env
+- salt.master.pillar
+- salt.master.minion
+- salt.master.win_repo
+- salt.master.ca
\ No newline at end of file
diff --git a/salt/master/minion.sls b/salt/master/minion.sls
new file mode 100644
index 0000000..8ba4fea
--- /dev/null
+++ b/salt/master/minion.sls
@@ -0,0 +1,46 @@
+{%- from "salt/map.jinja" import master with context %}
+{%- if master.enabled %}
+
+include:
+- salt.master.service
+
+{%- if master.minion is defined %}
+
+/srv/salt/minion_keys:
+ file.directory:
+ - makedirs: true
+ - require:
+ - pkg: salt_master_packages
+
+{%- for name, environment in master.environment.iteritems() %}
+
+/srv/salt/env/{{ name }}/minion_keys:
+ file.symlink:
+ - target: /srv/salt/minion_keys
+ - require:
+ - file: /srv/salt/env/{{ name }}
+ - file: /srv/salt/minion_keys
+
+{%- endfor %}
+
+{%- for minion in master.minion %}
+
+generate_key_{{ minion.name }}:
+ cmd.run:
+ - name: salt-key --gen-keys={{ minion.name }} --gen-keys-dir=/srv/salt/minion_keys
+ - unless: "test -e /srv/salt/minion_keys/{{ minion.name}}.pem"
+ - require:
+ - file: /srv/salt/minion_keys
+
+copy_generated_key_{{ minion.name }}:
+ cmd.run:
+ - name: cp /srv/salt/minion_keys/{{ minion.name }}.pub /etc/salt/pki/master/minions/{{ minion.name }}
+ - unless: "test -e /etc/salt/pki/master/minions/{{ minion.name }}"
+ - require:
+ - cmd: generate_key_{{ minion.name }}
+
+{%- endfor %}
+
+{%- endif %}
+
+{%- endif %}
\ No newline at end of file
diff --git a/salt/master/pillar.sls b/salt/master/pillar.sls
new file mode 100644
index 0000000..c7be5d5
--- /dev/null
+++ b/salt/master/pillar.sls
@@ -0,0 +1,76 @@
+{%- from "salt/map.jinja" import master with context %}
+{%- if master.enabled %}
+
+{%- if master.pillar.engine == 'salt' %}
+
+include:
+- git.client
+- salt.master.service
+
+{{ master.pillar.source.address }}:
+ git.latest:
+ - target: /srv/salt/pillar
+ - rev: {{ master.pillar.source.branch }}
+ - require:
+ - file: /srv/salt/env
+ - pkg: git_packages
+
+/srv/salt/env/{{ master.system.environment }}/top.sls:
+ file.symlink:
+ - target: /srv/salt/pillar/files_top.sls
+ - require:
+ - file: /srv/salt/env/{{ master.system.environment }}
+
+{%- elif master.pillar.engine == 'reclass' %}
+
+include:
+- reclass.storage.data
+
+/srv/salt/reclass/classes/service:
+ file.directory
+
+
+{%- if master.system is defined %}
+
+{%- for formula_name, formula in master.system.get('formula', {}).iteritems() %}
+
+/srv/salt/reclass/classes/service/{{ formula_name }}:
+ file.symlink:
+ - target: /srv/salt/env/{{ master.system.environment }}/{{ formula_name }}/metadata/service
+ - require:
+ - git: reclass_data_source
+ - file: /srv/salt/reclass/classes/service
+
+{%- endfor %}
+
+{%- else %}
+
+{%- for environment_name, environment in master.environment.iteritems() %}
+
+{%- for formula_name, formula in environment.get('formula', {}).iteritems() %}
+
+{%- if environment_name == master.base_environment %}
+
+/srv/salt/reclass/classes/service/{{ formula_name }}:
+ file.symlink:
+ {%- if formula.source == 'pkg' %}
+ - target: /usr/share/salt-formulas/reclass/service/{{ formula_name }}
+ {%- else %}
+ - target: /usr/share/salt-formulas/env/_formulas/{{ formula_name }}/metadata/service
+ {%- endif %}
+ - require:
+ - git: reclass_data_source
+ - file: /srv/salt/reclass/classes/service
+
+{%- endif %}
+
+{%- endfor %}
+
+{%- endfor %}
+
+{%-endif %}
+
+
+{%- endif %}
+
+{%- endif %}
\ No newline at end of file
diff --git a/salt/master/service.sls b/salt/master/service.sls
new file mode 100644
index 0000000..4fd05aa
--- /dev/null
+++ b/salt/master/service.sls
@@ -0,0 +1,29 @@
+{%- from "salt/map.jinja" import master with context %}
+{%- if master.enabled %}
+
+salt_master_packages:
+ pkg.latest:
+ - names: {{ master.pkgs }}
+
+/etc/salt/master.d/master.conf:
+ file.managed:
+ - source: salt://salt/files/master.conf
+ - user: root
+ - template: jinja
+ - require:
+ - pkg: salt_master_packages
+ - watch_in:
+ - service: salt_master_service
+
+salt_master_service:
+ service.running:
+ - name: {{ master.service }}
+ - enable: true
+
+/srv/salt/env:
+ file.directory:
+ - user: root
+ - mode: 755
+ - makedirs: true
+
+{%- endif %}
diff --git a/salt/master/win_repo.sls b/salt/master/win_repo.sls
new file mode 100644
index 0000000..ef41129
--- /dev/null
+++ b/salt/master/win_repo.sls
@@ -0,0 +1,49 @@
+{%- from "salt/map.jinja" import master with context %}
+{%- if master.enabled %}
+
+include:
+- git.client
+- salt.master.service
+
+{%- if master.windows_repo is defined %}
+
+/srv/salt/win:
+ file.directory:
+ - user: root
+ - mode: 755
+ - makedirs: true
+ - require:
+ - file: /srv/salt/env
+
+{%- if master.windows_repo.source == 'git' %}
+
+{{ master.windows_repo.address }}:
+ git.latest:
+ - target: /srv/salt/win/repo
+ - rev: {{ master.windows_repo.branch }}
+ - require:
+ - file: /srv/salt/win
+ - pkg: git_packages
+
+salt_master_update_win_repo:
+ cmd.run:
+ - name: salt-run winrepo.genrepo
+ - require:
+ - git: {{ master.windows_repo.address }}
+
+{%- for environment in master.environments %}
+
+/srv/salt/env/{{ name }}/win:
+ file.symlink:
+ - target: /srv/salt/win
+ - require:
+ - file: /srv/salt/env/{{ name }}
+ - git: {{ master.windows_repo.address }}
+
+{%- endfor %}
+
+{%- endif %}
+
+{%- endif %}
+
+{%- endif %}
\ No newline at end of file
diff --git a/salt/minion.sls b/salt/minion.sls
new file mode 100644
index 0000000..4900389
--- /dev/null
+++ b/salt/minion.sls
@@ -0,0 +1,58 @@
+{%- from "salt/map.jinja" import minion with context %}
+{%- if minion.enabled %}
+
+salt_minion_packages:
+ pkg.latest:
+ - names: {{ minion.pkgs }}
+
+salt_minion_grains_dir:
+ file.directory:
+ - name: /var/lib/salt/grains
+ - mode: 700
+ - makedirs: true
+ - user: root
+
+/etc/salt/minion.d/minion.conf:
+ file.managed:
+ - source: salt://salt/files/minion.conf
+ - user: root
+ - group: root
+ - template: jinja
+ - require:
+ - pkg: salt_minion_packages
+ - file: salt_minion_grains_dir
+ - watch_in:
+ - service: salt_minion_service
+
+salt_minion_service:
+ service.running:
+ - name: {{ minion.service }}
+ - enable: true
+
+{%- if minion.graph_states %}
+
+salt_graph_packages:
+ pkg.latest:
+ - names: {{ minion.graph_pkgs }}
+ - require:
+ - pkg: salt_minion_packages
+
+salt_graph_states_packages:
+ pkg.latest:
+ - names: {{ minion.graph_states_pkgs }}
+
+/root/salt-state-graph.py:
+ file.managed:
+ - source: salt://salt/files/salt-state-graph.py
+ - require:
+ - pkg: salt_graph_packages
+
+/root/salt-state-graph.sh:
+ file.managed:
+ - source: salt://salt/files/salt-state-graph.sh
+ - require:
+ - pkg: salt_graph_packages
+
+{%- endif %}
+
+{%- endif %}
\ No newline at end of file
diff --git a/salt/virt/init.sls b/salt/virt/init.sls
new file mode 100644
index 0000000..5811e85
--- /dev/null
+++ b/salt/virt/init.sls
@@ -0,0 +1,44 @@
+
+wlan0:
+ network.managed:
+ - enabled: True
+ - type: eth
+ - bridge: br0
+
+br0:
+ network.managed:
+ - enabled: True
+ - type: bridge
+ - proto: dhcp
+ - require:
+ - network: wlan0
+
+libvirt:
+ pkg.installed: []
+ file.managed:
+ - name: /etc/sysconfig/libvirtd
+ - contents: 'LIBVIRTD_ARGS="--listen"'
+ - require:
+ - pkg: libvirt
+ libvirt.keys:
+ - require:
+ - pkg: libvirt
+ service.running:
+ - name: libvirtd
+ - require:
+ - pkg: libvirt
+ - network: br0
+ - libvirt: libvirt
+ - watch:
+ - file: libvirt
+
+libvirt-python:
+ pkg.installed: []
+
+libguestfs:
+ pkg.installed:
+ - pkgs:
+ - libguestfs
+ - libguestfs-tools
+
+