diff --git a/FORMULA b/FORMULA new file mode 100644 index 0000000..40d1c79 --- /dev/null +++ b/FORMULA @@ -0,0 +1,8 @@ +name: salt +os: Debian, Redhat, Suse, Arch, Gentoo, FreeBSD, Windows +os_family: Debian, Redhat, Suse, Arch, Gentoo, FreeBSD, Windows +version: 201603 +release: 1 +minimum_version: 2015.8 +summary: Formula for install Saltstack +description: Formula for installing Saltstack diff --git a/README.rst b/README.rst index d11530a..a034960 100644 --- a/README.rst +++ b/README.rst @@ -63,19 +63,22 @@ Install gitfs backend dulwich dependencies. Set ``salt:master:gitfs_provider: du Install gitfs backend GitPython dependenciess. Set ``salt:master:gitfs_provider: gitpython`` in your pillar. +``salt.gitfs.keys`` +---------------------- + +Install ssh keys to be used by gitfs + ``salt.gitfs.pygit2`` ---------------------- Install gitfs backend libgit2/pygit2 dependenciess. Set ``salt:master:gitfs_provider: pygit2`` in your pillar. +For EL distributions, pygit is installed from packages from `EPEL `_. ``salt.pkgrepo`` ---------------- Enable the official saltstack package repository in order to always -benefit from the latest version. This state currently only works on Debian -and Ubuntu, and aims to implement the `installation recommendations of the -official documentation -`_. +benefit from the latest version. This state currently only works on Debian, Ubuntu, RHEL 6/7 and aims to implement the `installation recommendations of the official documentation `_. ``salt.pkgrepo.absent`` ----------------------- @@ -117,7 +120,7 @@ you control, then you can safely enable the ``Configuration`` ================= -Every option available in the templates can be set in pillar. Settings under 'salt' will be overridden by more specific settings under ``salt['master']``, ``salt['minion']`` or ``salt['cloud']`` +Every option available in the templates can be set in pillar. Settings under 'salt' will be overridden by more specific settings under ``salt['master']``, ``salt['minion']`` or ``salt['cloud']``. Options specified in ``salt['minion']`` which are not present in the default configuration file will be added to the end of the configuration file. :: diff --git a/dev/setup-salt.sh b/dev/setup-salt.sh index dc0a734..5f2d2e2 100644 --- a/dev/setup-salt.sh +++ b/dev/setup-salt.sh @@ -1,5 +1,9 @@ #!/bin/sh -sudo add-apt-repository ppa:saltstack/salt -y + +# use the latest stable Salt from repo.saltstack.com +wget -O - https://repo.saltstack.com/apt/ubuntu/14.04/amd64/latest/SALTSTACK-GPG-KEY.pub | sudo apt-key add - +sudo echo 'deb http://repo.saltstack.com/apt/ubuntu/14.04/amd64/latest trusty main' > /etc/apt/sources.list.d/saltstack.list + sudo apt-get update -y sudo apt-get install salt-master -y sudo apt-get install salt-minion -y diff --git a/pillar.example b/pillar.example index ca41f63..721bd3b 100644 --- a/pillar.example +++ b/pillar.example @@ -4,6 +4,12 @@ salt: # and up as it'll wipe out important files that Salt relies on. clean_config_d_dir: False + # This state will remove "/etc/salt/minion" when you set this to true. + minion_remove_config: True + + # This state will remove "/etc/salt/master" when you set this to true. + master_remove_config: True + # Set this to False to not have the formula install packages (in the case you # install Salt via git/pip/etc.) install_packages: True @@ -20,14 +26,24 @@ salt: master: fileserver_backend: - git + - s3fs - roots gitfs_remotes: - git://github.com/saltstack-formulas/salt-formula.git: - base: develop + s3.keyid: GKTADJGHEIQSXMKKRBJ08H + s3.key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs + s3.buckets: + - bucket1 + - bucket2 + - bucket3 + - bucket4 file_roots: base: - /srv/salt - + pillar_roots: + base: + - /srv/pillar # for salt-api with tornado rest interface rest_tornado: port: 8000 @@ -35,6 +51,49 @@ salt: ssl_key: /etc/pki/api/certs/server.key debug: False disable_ssl: False + # for profile configuration as https://docs.saltstack.com/en/latest/topics/tutorials/lxc.html#tutorial-lxc-profiles + lxc.container_profile: + debian: + template: download + options: + dist: debian + release: jessie + arch: amd64 + backing: lvm + vgname: kimsufi + size: 10G + lxc.network_profile: + basic: + eth0: + link: lxcbr0 + type: veth + flags: up + ## for external auth - LDAP + # filter to use for Active Directory LDAP + auth.ldap.filter: {% raw %}'sAMAccountName={{username}}'{% endraw %} + # filter to use for Most other LDAP servers + auth.ldap.filter: {% raw %}'uid={{ username }}'{% endraw %} + + # Define winrepo provider, by default support order is pygit2, gitpython + # Set to gitpython for Debian & Ubuntu to get around saltstack/salt#35993 + # where pygit2 is not compiled with pygit2.GIT_FEATURE_HTTPS support + winrepo_provider: gitpython + + # optional engine configuration + engines: + slack: + token: xoxp-XXXXX-XXXXXXX + control: True + valid_users: + - someuser + - otheruser + valid_commands: + - test.ping + - list_jobs + aliases: + list_jobs: + type: runner + cmd: jobs.list_jobs # salt minion config: minion: @@ -43,9 +102,9 @@ salt: master: salt # multi master setup - master: - - salt_master_1 - - salt_master_2 + #master: + #- salt_master_1 + #- salt_master_2 fileserver_backend: - git @@ -56,6 +115,9 @@ salt: file_roots: base: - /srv/salt + pillar_roots: + base: + - /srv/pillar module_config: test: True test.foo: foo @@ -75,16 +137,85 @@ salt: mine_functions: network.interface_ip: [eth0] + # other 'non-default' config + auth_keytab: /root/auth.keytab + auth_principal: kadmin/admin + + # optional engine configuration + engines: + slack: + token: xoxp-XXXXX-XXXXXXX + control: True + valid_users: + - someuser + - otheruser + valid_commands: + - test.ping + - list_jobs + aliases: + list_jobs: + type: runner + cmd: jobs.list_jobs + + # optional beacons configuration + beacons: + load: + 1m: + - 0.0 + - 2.0 + 5m: + - 0.0 + - 1.5 + 15m: + - 0.1 + - 1.0 + interval: 10 + + # salt cloud config cloud: master: salt - folders: - - cloud.providers.d/key - - cloud.profiles.d - - cloud.maps.d + + # For non-templated custom cloud provider/profile/map files providers: - - ec2 - - gce + provider-filename1.conf: + vmware-prod: + driver: vmware + user: myusernameprod + password: mypassword + vmware-nonprod: + driver: vmware + user: myusernamenonprod + password: mypassword + profiles: + profile-filename1.conf: + server-non-prod: + clonefrom: rhel6xtemplatenp + grains: + platform: + name: salt + realm: lab + subscription_level: standard + memory: 8GB + num_cpus: 4 + password: sUpErsecretey + provider: vmware-nonprod + maps: + map-filename1.map: + server-non-prod: + - host.mycompany.com: + grains: + environment: dev1 + + # You can take profile and map templates from an alternate location + # if you want to write your own. + template_sources: + providers: salt://salt/files/cloud.providers.d + profiles: salt://salt/files/cloud.profiles.d + maps: salt://salt/files/cloud.maps.d + + # These settings are used by the default provider templates and + # only need to be set for the ones you're using. aws_key: AWSKEYIJSHJAIJS6JSH aws_secret: AWSSECRETYkkDY1iQf9zRtl9+pW+Nm+aZY95 gce_project: test @@ -107,6 +238,16 @@ salt: user: ubuntu sudo: True priv: /etc/salt/ssh_keys/sshkey.pem + gitfs: + keys: + global: + # key and pub end up being the extension used on the key file. values other than key and pub are possible + key: | + -----BEGIN RSA PRIVATE KEY----- + ........... + -----END RSA PRIVATE KEY----- + pub: | + ........... salt_cloud_certs: aws: diff --git a/salt/api.sls b/salt/api.sls index 812f243..278511f 100644 --- a/salt/api.sls +++ b/salt/api.sls @@ -9,8 +9,12 @@ salt-api: - name: {{ salt_settings.salt_api }} {% endif %} service.running: + - enable: True - name: {{ salt_settings.api_service }} - require: - service: {{ salt_settings.master_service }} - watch: - - pkg: salt-master +{% if salt_settings.install_packages %} + - pkg: salt-api +{% endif %} + - file: salt-master diff --git a/salt/cloud.sls b/salt/cloud.sls index 9d467e7..63d4776 100644 --- a/salt/cloud.sls +++ b/salt/cloud.sls @@ -1,5 +1,10 @@ {% from "salt/map.jinja" import salt_settings with context %} +{% set cloudmaps = salt['pillar.get']('salt:cloud:maps', {}) -%} +{% set cloudprofiles = salt['pillar.get']('salt:cloud:profiles', {}) -%} +{% set cloudproviders = salt['pillar.get']('salt:cloud:providers', {}) -%} + +{%- if salt_settings.use_pip %} python-pip: pkg.installed @@ -19,62 +24,77 @@ apache-libcloud: pip.installed: - require: - pkg: python-pip +{%- endif %} {% if salt_settings.install_packages %} salt-cloud: pkg.installed: - name: {{ salt_settings.salt_cloud }} + {%- if salt_settings.use_pip %} - require: - pip: apache-libcloud - pip: pycrypto {% if grains['os_family'] not in ['Debian', 'RedHat'] %} - pip: crypto {% endif %} + {%- endif %} {% endif %} -{% for folder in salt_settings.cloud.folders %} -{{ folder }}: - file.directory: - - name: /etc/salt/{{ folder }} - - user: root - - group: root - - file_mode: 744 - - dir_mode: 755 - - makedirs: True -{% endfor %} - {% for cert in pillar.get('salt_cloud_certs', {}) %} {% for type in ['pem'] %} cloud-cert-{{ cert }}-pem: file.managed: - - name: /etc/salt/cloud.providers.d/key/{{ cert }}.pem - - source: salt://salt/files/key + - name: {{ salt_settings.config_path }}/pki/cloud/{{ cert }}.pem + - source: salt://{{ slspath }}/files/key - template: jinja - user: root - group: root - mode: 600 + - makedirs: True - defaults: key: {{ cert }} type: {{ type }} {% endfor %} {% endfor %} -{% for providers in salt_settings.cloud.providers %} -salt-cloud-profiles-{{ providers }}: - file.managed: - - name: /etc/salt/cloud.profiles.d/{{ providers }}.conf +{%- for dir, templ_path in salt_settings.cloud.template_sources.items() %} +salt-cloud-{{ dir }}: + file.recurse: + - name: {{ salt_settings.config_path }}/cloud.{{ dir }}.d + - source: {{ templ_path }} - template: jinja - - source: salt://salt/files/cloud.profiles.d/{{ providers }}.conf + - makedirs: True +{%- endfor %} -salt-cloud-providers-{{ providers }}: +{% for key, value in cloudmaps.items() %} +/etc/salt/cloud.maps.d/{{ key }}: file.managed: - - name: /etc/salt/cloud.providers.d/{{ providers }}.conf - - template: jinja - - source: salt://salt/files/cloud.providers.d/{{ providers }}.conf - -salt-cloud-maps-{{ providers }}: - file.managed: - - name: /etc/salt/cloud.maps.d/{{ providers }}.conf - - template: jinja - - source: salt://salt/files/cloud.maps.d/{{ providers }}.conf + - contents: | + {{ value|yaml(False) | indent(8) }} {% endfor %} + +{% for key, value in cloudprofiles.items() %} +/etc/salt/cloud.profiles.d/{{ key }}: + file.managed: + - contents: | + {{ value|yaml(False) | indent(8) }} +{% endfor %} + +{% for key, value in cloudproviders.items() %} +/etc/salt/cloud.providers.d/{{ key }}: + file.managed: + - contents: | + {{ value|yaml(False) | indent(8) }} +{% endfor %} + +salt-cloud-providers-permissions: + file.directory: + - name: {{ salt_settings.config_path }}/cloud.providers.d + - user: root + - group: root + - file_mode: 600 + - dir_mode: 700 + - recurse: + - user + - group + - mode diff --git a/salt/defaults.yaml b/salt/defaults.yaml index 3457a72..8a82d80 100644 --- a/salt/defaults.yaml +++ b/salt/defaults.yaml @@ -1,17 +1,29 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml salt: install_packages: True + use_pip: False + clean_config_d_dir: True + config_path: /etc/salt + + minion_remove_config: False + master_remove_config: False + minion_service: salt-minion master_service: salt-master api_service: salt-api syndic_service: salt-syndic + salt_master: salt-master salt_minion: salt-minion salt_syndic: salt-syndic salt_cloud: salt-cloud salt_api: salt-api salt_ssh: salt-ssh - clean_config_d_dir: True + + python_git: python-git + python_dulwich: python-dulwich master: gitfs_provider: gitpython @@ -21,5 +33,22 @@ salt: install_from_source: True pygit2: install_from_source: True + version: 0.23.0 + git: + # if not false, should be state name + require_state: False + install_from_package: git + libgit2: + version: 0.23.0 + install_from_source: True + build_parent_dir: /usr/src/ + # hash necessary until github issue #9272 is addressed + download_hash: 683d1164e361e2a0a8d52652840e2340 gitpython: install_from_source: False + + cloud: + template_sources: + providers: salt://salt/files/cloud.providers.d + profiles: salt://salt/files/cloud.profiles.d + maps: salt://salt/files/cloud.maps.d diff --git a/salt/files/cloud.profiles.d/ec2.conf b/salt/files/cloud.profiles.d/ec2.conf index 3032f1a..2141ef7 100644 --- a/salt/files/cloud.profiles.d/ec2.conf +++ b/salt/files/cloud.profiles.d/ec2.conf @@ -1,4 +1,6 @@ # This file managed by Salt, do not edit by hand!! +{% set cloud = salt['pillar.get']('salt:cloud', {}) -%} +{% if 'aws_key' in cloud %} base_ubuntu_ec2: provider: ec2_ubuntu_public image: ami-cb4986bc @@ -13,4 +15,5 @@ base_ubuntu_ec2: SecurityGroupId: - sg-6ec11d3b tag: {'Environment': 'production', 'Role': 'ubuntu'} - sync_after_install: grains \ No newline at end of file + sync_after_install: grains +{% endif %} diff --git a/salt/files/cloud.profiles.d/gce.conf b/salt/files/cloud.profiles.d/gce.conf index 8120489..0311d03 100644 --- a/salt/files/cloud.profiles.d/gce.conf +++ b/salt/files/cloud.profiles.d/gce.conf @@ -1,4 +1,6 @@ # This file managed by Salt, do not edit by hand!! +{%- set cloud = salt['pillar.get']('salt:cloud', {}) -%} +{%- if 'gce_project' in cloud %} base_debian_gce: image: debian-7-wheezy size: g1-small @@ -10,4 +12,5 @@ base_debian_gce: delete_boot_pd: True deploy: True make_master: False - provider: gce \ No newline at end of file + provider: gce +{%- endif %} diff --git a/salt/files/cloud.providers.d/ec2.conf b/salt/files/cloud.providers.d/ec2.conf index fddf6b7..1413166 100644 --- a/salt/files/cloud.providers.d/ec2.conf +++ b/salt/files/cloud.providers.d/ec2.conf @@ -1,16 +1,23 @@ # This file managed by Salt, do not edit by hand!! -{% set cloud = salt['pillar.get']('salt:cloud', {}) -%} +{%- from "salt/map.jinja" import salt_settings with context -%} +{%- set cloud = salt['pillar.get']('salt:cloud', {}) -%} +{%- if 'aws_key' in cloud %} ec2_ubuntu_public: minion: - master: {{ cloud['master'] }} + master: {{ cloud.get('master', 'salt') }} grains: test: True ssh_interface: public_ips - id: {{ cloud['aws_key'] }} - key: '{{ cloud['aws_secret'] }}' - private_key: /etc/salt/cloud.providers.d/key/key.pem + id: {{ cloud.get('aws_key', 'DEFAULT') }} + key: '{{ cloud.get('aws_secret', 'DEFAULT') }}' + private_key: {{ salt_settings.config_path }}/pki/cloud/ec2.pem keyname: keyname location: eu-west-1 availability_zone: eu-west-1a ssh_username: ubuntu + {%- if grains.saltversioninfo[0] >= 2016 or (grains.saltversioninfo[0] >= 2015 and grains.saltversioninfo[1] >= 8) %} + driver: ec2 + {%- else %} provider: ec2 + {%- endif %} +{%- endif %} diff --git a/salt/files/cloud.providers.d/gce.conf b/salt/files/cloud.providers.d/gce.conf index 5313dfb..57278ee 100644 --- a/salt/files/cloud.providers.d/gce.conf +++ b/salt/files/cloud.providers.d/gce.conf @@ -1,11 +1,18 @@ # This file managed by Salt, do not edit by hand!! -{% set cloud = salt['pillar.get']('salt:cloud', {}) -%} +{%- from "salt/map.jinja" import salt_settings with context -%} +{%- set cloud = salt['pillar.get']('salt:cloud', {}) -%} +{%- if 'gce_project' in cloud %} gce: - project: "{{ cloud['gce_project'] }}" - service_account_email_address: "{{ cloud['gce_service_account_email_address'] }}" - service_account_private_key: "/etc/salt/cloud.providers.d/key.pem" + project: "{{ cloud.get('gce_project', 'DEFAULT') }}" + service_account_email_address: "{{ cloud.get('gce_service_account_email_address', 'DEFAULT') }}" + service_account_private_key: "{{ salt_settings.config_path }}/pki/cloud/gce.pem" minion: - master: {{ cloud['master'] }} + master: {{ cloud.get('master', 'salt') }} grains: test: True + {%- if grains.saltversioninfo[0] >= 2016 or (grains.saltversioninfo[0] >= 2015 and grains.saltversioninfo[1] >= 8) %} + driver: gce + {%- else %} provider: gce + {%- endif %} +{%- endif %} diff --git a/salt/files/cloud.providers.d/rsos.conf b/salt/files/cloud.providers.d/rsos.conf index d3d6aa7..3734e36 100644 --- a/salt/files/cloud.providers.d/rsos.conf +++ b/salt/files/cloud.providers.d/rsos.conf @@ -6,7 +6,7 @@ rsos_{{ region|lower }}: minion: - master: {{ cloud['master'] }} + master: {{ cloud.get('master', 'salt') }} grains: region: {{ region|lower }} @@ -14,8 +14,12 @@ rsos_{{ region|lower }}: compute_name: cloudServersOpenStack protocol: ipv4 compute_region: {{ region }} + {%- if grains.saltversioninfo[0] >= 2016 or (grains.saltversioninfo[0] >= 2015 and grains.saltversioninfo[1] >= 8) %} + driver: openstack + {%- else %} provider: openstack - user: {{ cloud['rsos_user'] }} - tenant: {{ cloud['rsos_tenant'] }} - apikey: {{ cloud['rsos_apikey'] }} + {%- endif %} + user: {{ cloud.get('rsos_user', 'DEFAULT') }} + tenant: {{ cloud.get('rsos_tenant', 'DEFAULT') }} + apikey: {{ cloud.get('rsos_apikey', 'DEFAULT') }} {% endfor %} diff --git a/salt/files/cloud.providers.d/saltify.conf b/salt/files/cloud.providers.d/saltify.conf index 4fcff65..4ff5b1b 100644 --- a/salt/files/cloud.providers.d/saltify.conf +++ b/salt/files/cloud.providers.d/saltify.conf @@ -1,5 +1,12 @@ # This file is managed by Salt via {{ source }} + +{% set cloud = salt['pillar.get']('salt:cloud', {}) -%} + saltify: + {%- if grains.saltversioninfo[0] >= 2016 or (grains.saltversioninfo[0] >= 2015 and grains.saltversioninfo[1] >= 8) %} + driver: saltify + {%- else %} provider: saltify + {%- endif %} minion: - master: {{ cloud['master'] }} + master: {{ cloud.get('master', 'salt') }} diff --git a/salt/files/gitfs_key.jinja b/salt/files/gitfs_key.jinja new file mode 100644 index 0000000..7c33128 --- /dev/null +++ b/salt/files/gitfs_key.jinja @@ -0,0 +1 @@ +{{ pillar['salt']['gitfs']['keys'][key][type] }} diff --git a/salt/files/master.d/engine.conf b/salt/files/master.d/engine.conf new file mode 100644 index 0000000..47e6a6d --- /dev/null +++ b/salt/files/master.d/engine.conf @@ -0,0 +1,9 @@ +# +# This file is managed by Salt! Do not edit by hand! +# +{%- set engines = salt['pillar.get']('salt:engines', {}) -%} +{%- set engines = salt['pillar.get']('salt:master:engines', default=engines, merge=True) -%} +{%- if engines %} +engines: + {{ engines | yaml(False) | indent(2) }} +{%- endif -%} diff --git a/salt/files/master.d/f_defaults.conf b/salt/files/master.d/f_defaults.conf index 53cbd41..b97bf57 100644 --- a/salt/files/master.d/f_defaults.conf +++ b/salt/files/master.d/f_defaults.conf @@ -1,24 +1,33 @@ # This file managed by Salt, do not edit by hand!! -# Based on salt version 0.17.4 default config -{% set reserved_keys = ['master', 'minion', 'cloud', 'salt_cloud_certs'] -%} +# Based on salt version 2015.8.7 default config +{% set reserved_keys = ['master', 'minion', 'cloud', 'salt_cloud_certs', 'engines'] -%} {% set cfg_salt = pillar.get('salt', {}) -%} {% set cfg_master = cfg_salt.get('master', {}) -%} +{% set default_keys = [] -%} {%- macro get_config(configname, default_value) -%} +{%- do default_keys.append(configname) %} {%- if configname in cfg_master -%} -{{ configname }}: {{ cfg_master[configname] }} +{{ configname }}: {{ cfg_master[configname]|json }} {%- elif configname in cfg_salt and configname not in reserved_keys -%} -{{ configname }}: {{ cfg_salt[configname] }} +{{ configname }}: {{ cfg_salt[configname]|json }} {%- else -%} -#{{ configname }}: {{ default_value }} +#{{ configname }}: {{ default_value|json }} {%- endif -%} {%- endmacro -%} {%- from 'salt/formulas.jinja' import file_roots, formulas with context -%} ##### Primary configuration settings ##### ########################################## -# This configuration file is used to manage the behavior of the Salt Master -# Values that are commented out but have no space after the comment are -# defaults that need not be set in the config. If there is a space after the -# comment that the value is presented as an example and is not the default. +# This configuration file is used to manage the behavior of the Salt Master. +# Values that are commented out but have an empty line after the comment are +# defaults that do not need to be set in the config. If there is no blank line +# after the comment then the value is presented as an example and is not the +# default. + +# The id to be passed in the publish job to minions. +# This is used for MultiSyndics to return the job to the requesting master. +# This must be the same string as the syndic is configured with. +# master_id: None +{{ get_config('master_id', 'None') }} # Per default, the master will automatically include all config files # from master.d/*.conf (master.d is a directory in the same directory @@ -41,30 +50,6 @@ # modified files cause conflicts, set verify_env to False. {{ get_config('user', 'root') }} -# Max open files -# -# Each minion connecting to the master uses AT LEAST one file descriptor, the -# master subscription connection. If enough minions connect you might start -# seeing on the console (and then salt-master crashes): -# Too many open files (tcp_listener.cpp:335) -# Aborted (core dumped) -# -# By default this value will be the one of `ulimit -Hn`, ie, the hard limit for -# max open files. -# -# If you wish to set a different value than the default one, uncomment and -# configure this setting. Remember that this value CANNOT be higher than the -# hard limit. Raising the hard limit depends on your OS and/or distribution, -# a good way to find the limit is to search the internet. For example: -# raise max open files hard limit debian -# -{{ get_config('max_open_files', '100000') }} - -# The number of worker threads to start. These threads are used to manage -# return calls made from minions to the master. If the master seems to be -# running slowly, increase the number of threads. -{{ get_config('worker_threads', '5') }} - # The port used by the communication interface. The ret (return) port is the # interface used for the file server, authentication, job returns, etc. {{ get_config('ret_port', '4506') }} @@ -81,6 +66,8 @@ {{ get_config('pki_dir', '/etc/salt/pki/master') }} # Directory to store job and cache data: +# This directory may contain sensitive data and should be protected accordingly. +# {{ get_config('cachedir', '/var/cache/salt/master') }} # Directory for custom modules. This directory can contain subdirectories for @@ -88,6 +75,26 @@ # "states", "returners", etc. {{ get_config('extension_modules', '') }} +# Directory for custom modules. This directory can contain subdirectories for +# each of Salt's module types such as "runners", "output", "wheel", "modules", +# "states", "returners", etc. +# Like 'extension_modules' but can take an array of paths +{% if 'module_dirs' in cfg_master -%} +{%- do default_keys.append('module_dirs') %} +module_dirs: + {%- for dir in cfg_master['module_dirs'] %} + - {{ dir}} + {%- endfor -%} +{% elif 'module_dirs' in cfg_salt -%} +module_dirs: + {%- for dir in cfg_salt['module_dirs'] %} + - {{ dir}} + {%- endfor -%} +{% else -%} +#module_dirs: +# - /var/cache/salt/minion/extmods +{% endif %} + # Verify and set permissions on configuration directories at startup: {{ get_config('verify_env', 'True') }} @@ -135,10 +142,9 @@ {{ get_config('minion_data_cache', 'True') }} # Store all returns in the given returner. -# Setting this option requires that any returner-specific configuration also +# Setting this option requires that any returner-specific configuration also # be set. See various returners in salt/returners for details on required # configuration values. (See also, event_return_queue below.) -# {{ get_config('event_return', 'mysql') }} # On busy systems, enabling event_returns can cause a considerable load on @@ -149,6 +155,7 @@ # Only events returns matching tags in a whitelist {% if 'event_return_whitelist' in cfg_master -%} +{%- do default_keys.append('event_return_whitelist') %} event_return_whitelist: {%- for event_return in cfg_master['event_return_whitelist'] %} - {{ event_return }} @@ -166,6 +173,7 @@ event_return_whitelist: # Store all event returns _except_ the tags in a blacklist {% if 'event_return_blacklist' in cfg_master -%} +{%- do default_keys.append('event_return_blacklist') %} event_return_blacklist: {%- for event_return in cfg_master['event_return_blacklist'] %} - {{ event_return }} @@ -179,7 +187,6 @@ event_return_blacklist: # event_return_blacklist: # - salt/master/not_this_tag # - salt/master/or_this_one - {% endif %} # Passing very large events can cause the minion to consume large amounts of @@ -199,12 +206,12 @@ event_return_blacklist: # the key rotation event as minions reconnect. Consider this carefully if this # salt master is managing a large number of minions. # -# If disabled, it is recommended to handle this event by listening for the +# If disabled, it is recommended to handle this event by listening for the # 'aes_key_rotate' event with the 'key' tag and acting appropriately. {{ get_config('ping_on_rotate', 'False') }} # By default, the master deletes its cache of minion data when the key for that -# minion is removed. To preserve the cache after key deletion, set +# minion is removed. To preserve the cache after key deletion, set # 'preserve_minion_cache' to True. # # WARNING: This may have security implications if compromised minions auth with @@ -233,6 +240,58 @@ event_return_blacklist: # - /etc/salt/extra_config {{ get_config('include', '[]') }} +##### Large-scale tuning settings ##### +########################################## +# Max open files +# +# Each minion connecting to the master uses AT LEAST one file descriptor, the +# master subscription connection. If enough minions connect you might start +# seeing on the console (and then salt-master crashes): +# Too many open files (tcp_listener.cpp:335) +# Aborted (core dumped) +# +# By default this value will be the one of `ulimit -Hn`, ie, the hard limit for +# max open files. +# +# If you wish to set a different value than the default one, uncomment and +# configure this setting. Remember that this value CANNOT be higher than the +# hard limit. Raising the hard limit depends on your OS and/or distribution, +# a good way to find the limit is to search the internet. For example: +# raise max open files hard limit debian +# +{{ get_config('max_open_files', '100000') }} + +# The number of worker threads to start. These threads are used to manage +# return calls made from minions to the master. If the master seems to be +# running slowly, increase the number of threads. This setting can not be +# set lower than 3. +{{ get_config('worker_threads', '5') }} + +# Set the ZeroMQ high water marks +# http://api.zeromq.org/3-2:zmq-setsockopt + +# The publisher interface ZeroMQPubServerChannel +{{ get_config('pub_hwm', '1000') }} + +# These two ZMQ HWM settings, salt_event_pub_hwm and event_publisher_pub_hwm +# are significant for masters with thousands of minions. When these are +# insufficiently high it will manifest in random responses missing in the CLI +# and even missing from the job cache. Masters that have fast CPUs and many +# cores with appropriate worker_threads will not need these set as high. + +# On deployment with 8,000 minions, 2.4GHz CPUs, 24 cores, 32GiB memory has +# these settings: +# +# salt_event_pub_hwm: 128000 +# event_publisher_pub_hwm: 64000 + +# ZMQ high-water-mark for SaltEvent pub socket +{{ get_config('salt_event_pub_hwm', '20000') }} + +# ZMQ high-water-mark for EventPublisher pub socket +{{ get_config('event_publisher_pub_hwm', '10000') }} + + ##### Security settings ##### ########################################## # Enable "open mode", this mode still maintains encryption, but turns off @@ -273,11 +332,8 @@ event_return_blacklist: # This setting should be treated with care since it opens up execution # capabilities to non root users. By default this capability is completely # disabled. -#client_acl: -# larry: -# - test.ping -# - network.* {% if 'client_acl' in cfg_master -%} +{%- do default_keys.append('client_acl') %} client_acl: {%- for name, user in cfg_master['client_acl']|dictsort %} {{ name}}: @@ -305,8 +361,8 @@ client_acl: # This example would blacklist all non sudo users, including root from # running any commands. It would also blacklist any use of the "cmd" # module. This is completely disabled by default. -# {% if 'client_acl_blacklist' in cfg_master %} +{%- do default_keys.append('client_acl_blacklist') %} client_acl_blacklist: users: {% for user in cfg_master['client_acl_blacklist'].get('users', []) %} @@ -336,8 +392,7 @@ client_acl_blacklist: {% endif %} # Enforce client_acl & client_acl_blacklist when users have sudo -# access to the salt command. -# +# access to the salt command. {{ get_config('sudo_acl', 'False') }} # The external auth system uses the Salt auth modules to authenticate and @@ -374,6 +429,103 @@ client_acl_blacklist: # will cause minion to throw an exception and drop the message. {{ get_config('sign_pub_message', 'False') }} +# Sign the master auth-replies with a cryptographic signature of the masters public key. +# Please see the tutorial how to use these settings in the Multimaster-PKI with Failover Tutorial +{{ get_config('master_sign_pubkey', 'False') }} + +# The customizable name of the signing-key-pair without suffix. +# master_sign_key_name: +{{ get_config('master_sign', '{}') }} + +# The name of the file in the masters pki-directory that holds the pre-calculated +# signature of the masters public-key. +# master_pubkey_signature: +{{ get_config('master_pubkey_signature', '{}') }} + +# Instead of computing the signature for each auth-reply, use a pre-calculated signature. +# The master_pubkey_signature must also be set for this. +{{ get_config('master_use_pubkey_signature', 'False') }} + +# Rotate the salt-masters AES-key when a minion-public is deleted with salt-key. +# This is a very important security-setting. Disabling it will enable deleted minions to still +# listen in on the messages published by the salt-master. +# Do not disable this unless it is absolutely clear what this does. +{{ get_config('rotate_aes_key', 'True') }} + +# Unique ID attribute name for the user. For Active Directory should be set +# to 'sAMAccountName'. Default value is 'memberUid'. +{{ get_config('auth.ldap.accountattributename', 'memberUid') }} + +# Set this to True if LDAP is Active Directory. Default is False +{{ get_config('auth.ldap.activedirectory', False) }} + +# Bind to LDAP anonymously to determine group membership +# Active Directory does not allow anonymous binds without special configuration +{{ get_config('auth.ldap.anonymous', False) }} + +# The base DN under which users can be found in LDAP +{{ get_config('auth.ldap.basedn', '') }} + +# The user Salt authenticates to search for a users' Distinguished Name and +# group membership. +{{ get_config('auth.ldap.binddn', '') }} + +# The bind password to go along with the bind dn (binddn). +{{ get_config('auth.ldap.bindpw', '') }} + +# The filter used to find the DN associated with a user. For most LDAPs use +# the value {% raw %}'uid={{ username }}'{% endraw %}. For Active Directory use the value +# {% raw %}'sAMAccountName={{username}}'{% endraw %}. +{{ get_config('auth.ldap.filter', '') }} + +# The attribute used for user group membership. Defaults to 'memberOf' +{{ get_config('auth.ldap.groupattribute', 'memberOf') }} + +# LDAP group class. Use 'group' for Active Directory. Defaults to 'posixGroup' +{{ get_config('auth.ldap.groupclass', 'posixGroup') }} + +# To specify an OU that contains group data. Not used for Active Directory +# Default value: 'Groups' +{{ get_config('auth.ldap.groupou', 'Groups') }} + +# Allows the administrator to strip off a certain set of domain names +# so the hostnames looked up in the directory service can match the minion IDs. +{{ get_config('auth.ldap.minion_stripdomains', []) }} + +# Verify server's TLS certificate. Default value: False +{{ get_config('auth.ldap.no_verify', False) }} + +# Only for Active Directory. Default value: 'person' +{{ get_config('auth.ldap.persontype', 'person') }} + +# Port to connect via. Default value: '389' +{{ get_config('auth.ldap.port', '389') }} + +# LDAP scope level, almost always 2. Default value: 2 +{{ get_config('auth.ldap.scope', 2) }} + +# Server to auth against. Default value: 'localhost' +{{ get_config('auth.ldap.server', 'localhost') }} + +# Use TLS when connecting. Default value: False +{{ get_config('auth.ldap.tls', False) }} + +# Server specified in URI format. Overrides .ldap.server, .ldap.port, +# .ldap.tls. Default value: '' +{{ get_config('auth.ldap.uri', '') }} + +##### Salt-SSH Configuration ##### +########################################## + +# Pass in an alternative location for the salt-ssh roster file +{{ get_config('roster_file', '/etc/salt/roster') }} + +# Pass in minion option overrides that will be inserted into the SHIM for +# salt-ssh calls. The local minion config is not used for salt-ssh. Can be +# overridden on a per-minion basis in the roster (`minion_opts`) +#ssh_minion_opts: +# gpg_keydir: /root/gpg +{{ get_config('ssh_minion_opts', '{}') }} ##### Master Module Management ##### ########################################## @@ -402,7 +554,21 @@ client_acl_blacklist: # master_tops: # ext_nodes: # -{{ get_config('master_tops', '{}') }} +#master_tops: {} +{% if 'master_tops' in cfg_master %} +{%- do default_keys.append('master_tops') %} +master_tops: +{%- for master in cfg_master['master_tops'] -%} + {%- if cfg_master['master_tops'][master] is string %} + {{ master }}: {{ cfg_master['master_tops'][master] }} + {%- else %} + {{ master}}: + {%- for parameter in cfg_master['master_tops'][master] %} + {{ parameter }}: {{ cfg_master['master_tops'][master][parameter] }} + {%- endfor -%} + {%- endif -%} +{%- endfor %} +{% endif %} # The external_nodes option allows Salt to gather data that would normally be # placed in a top file. The external_nodes option is the executable that will @@ -420,7 +586,7 @@ client_acl_blacklist: # (block, not variable tag!). Defaults to False, corresponds to the Jinja # environment init variable "trim_blocks". {{ get_config('jinja_trim_blocks', 'False') }} -# + # If this is set to True leading spaces and tabs are stripped from the start # of a line to a block. Defaults to False, corresponds to the Jinja # environment init variable "lstrip_blocks". @@ -444,13 +610,22 @@ client_acl_blacklist: {{ get_config('state_output', 'full') }} # Automatically aggregate all states that have support for mod_aggregate by -# setting to True. Or pass a list of state module names to automatically +# setting to 'True'. Or pass a list of state module names to automatically # aggregate just those types. # # state_aggregate: # - pkg # #state_aggregate: False +{{ get_config('state_aggregate', '{}') }} + +# Send progress events as each function in a state run completes execution +# by setting to 'True'. Progress events are in the format +# 'salt/job//prog//'. +{{ get_config('state_events', 'False') }} + +# Enable extra routines for YAML renderer used states containing UTF characters. +{{ get_config('yaml_utf8', 'False') }} ##### File Server settings ##### ########################################## @@ -472,8 +647,9 @@ client_acl_blacklist: # prod: # - /srv/salt/prod/services # - /srv/salt/prod/states - +# {% if 'file_roots' in cfg_master -%} +{%- do default_keys.append('file_roots') %} {{ file_roots(cfg_master['file_roots']) }} {%- elif 'file_roots' in cfg_salt -%} {{ file_roots(cfg_salt['file_roots']) }} @@ -485,11 +661,27 @@ client_acl_blacklist: # - /srv/salt {%- endif %} +# When using multiple environments, each with their own top file, the +# default behaviour is an unordered merge. To prevent top files from +# being merged together and instead to only use the top file from the +# requested environment, set this value to 'same'. +{{ get_config('top_file_merging_strategy', 'merge') }} + +# To specify the order in which environments are merged, set the ordering +# in the env_order option. Given a conflict, the last matching value will +# win. +{{ get_config('env_order', '["base", "dev", "prod"]') }} + +# If top_file_merging_strategy is set to 'same' and an environment does not +# contain a top file, the top file in the environment specified by default_top +# will be used instead. +{{ get_config('default_top', 'base') }} + # The hash_type is the hash to use when discovering the hash of a file on # the master server. The default is md5, but sha1, sha224, sha256, sha384 # and sha512 are also supported. # -# Prior to changing this value, the master should be stopped and all Salt +# Prior to changing this value, the master should be stopped and all Salt # caches should be cleared. {{ get_config('hash_type', 'md5') }} @@ -503,6 +695,7 @@ client_acl_blacklist: # and don't want all the '.svn' folders and content synced to your minions, # you could set this to '/\.svn($|/)'. By default nothing is ignored. {% if 'file_ignore_regex' in cfg_master %} +{%- do default_keys.append('file_ignore_regex') %} file_ignore_regex: {% for regex in cfg_master['file_ignore_regex'] %} - {{ regex }} @@ -523,6 +716,7 @@ file_ignore_regex: # to file_ignore_regex above, but works on globs instead of regex. By default # nothing is ignored. {% if 'file_ignore_glob' in cfg_master %} +{%- do default_keys.append('file_ignore_glob') %} file_ignore_glob: {% for glob in cfg_master['file_ignore_glob'] %} - {{ glob }} @@ -555,31 +749,32 @@ file_ignore_glob: # - git # - roots {% if 'fileserver_backend' in cfg_master -%} +{%- do default_keys.append('fileserver_backend') %} fileserver_backend: {%- for backend in cfg_master['fileserver_backend'] %} - {{ backend }} {%- endfor -%} {%- endif %} -# + # Uncomment the line below if you do not want the file_server to follow # symlinks when walking the filesystem tree. This is set to True # by default. Currently this only applies to the default roots # fileserver_backend. {{ get_config('fileserver_followsymlinks', 'False') }} -# + # Uncomment the line below if you do not want symlinks to be # treated as the files they are pointing to. By default this is set to # False. By uncommenting the line below, any detected symlink while listing # files on the Master will not be returned to the Minion. {{ get_config('fileserver_ignoresymlinks', 'True') }} -# + # By default, the Salt fileserver recurses fully into all defined environments # to attempt to find files. To limit this behavior so that the fileserver only # traverses directories with SLS files and special Salt directories like _modules, # enable the option below. This might be useful for installations where a file root # has a very large number of files and performance is impacted. Default is False. {{ get_config('fileserver_limit_traversal', 'False') }} -# + # The fileserver can fire events off every time the fileserver is updated, # these are disabled by default, but can be easily turned on by setting this # flag to True @@ -587,10 +782,37 @@ fileserver_backend: # Git File Server Backend Configuration # -# Gitfs can be provided by one of two python modules: GitPython or pygit2. If -# using pygit2, both libgit2 and git must also be installed. -{{ get_config('gitfs_provider', 'gitpython') }} -# +# Optional parameter used to specify the provider to be used for gitfs. Must +# be one of the following: pygit2, gitpython, or dulwich. If unset, then each +# will be tried in that same order, and the first one with a compatible +# version installed will be the provider that is used. +{{ get_config('gitfs_provider', 'pygit2') }} + +# Along with gitfs_password, is used to authenticate to HTTPS remotes. +{{ get_config('gitfs_user', 'git') }} + +# Along with gitfs_user, is used to authenticate to HTTPS remotes. +# This parameter is not required if the repository does not use authentication. +{{ get_config('gitfs_password', '') }} + +# By default, Salt will not authenticate to an HTTP (non-HTTPS) remote. +# This parameter enables authentication over HTTP. Enable this at your own risk. +{{ get_config('gitfs_insecure_auth', 'False') }} + +# Along with gitfs_privkey (and optionally gitfs_passphrase), is used to +# authenticate to SSH remotes. This parameter (or its per-remote counterpart) +# is required for SSH remotes. +{{ get_config('gitfs_pubkey', '') }} + +# Along with gitfs_pubkey (and optionally gitfs_passphrase), is used to +# authenticate to SSH remotes. This parameter (or its per-remote counterpart) +# is required for SSH remotes. +{{ get_config('gitfs_privkey', '') }} + +# This parameter is optional, required only when the SSH key being used to +# authenticate is protected by a passphrase. +{{ get_config('gitfs_passphrase', '') }} + # When using the git fileserver backend at least one git remote needs to be # defined. The user running the salt master will need read access to the repo. # @@ -601,6 +823,7 @@ fileserver_backend: # Note: file:// repos will be treated as a remote, so refs you want used must # exist in that repo as *local* refs. {% if 'gitfs_remotes' in cfg_master -%} +{%- do default_keys.append('gitfs_remotes') %} gitfs_remotes: {%- for remote in cfg_master['gitfs_remotes'] %} {%- if remote is iterable and remote is not string %} @@ -628,12 +851,82 @@ gitfs_remotes: # keep in mind that setting this flag to anything other than the default of True # is a security concern, you may want to try using the ssh transport. {{ get_config('gitfs_ssl_verify', 'True') }} -# + # The gitfs_root option gives the ability to serve files from a subdirectory # within the repository. The path is defined relative to the root of the # repository and defaults to the repository root. {{ get_config('gitfs_root', 'somefolder/otherfolder') }} +# The gitfs_env_whitelist and gitfs_env_blacklist parameters allow for greater +# control over which branches/tags are exposed as fileserver environments. +{% if 'gitfs_env_whitelist' in cfg_master -%} +{%- do default_keys.append('gitfs_env_whitelist') %} +gitfs_env_whitelist: + {%- for git_env in cfg_master['gitfs_env_whitelist'] %} + - {{ git_env }} + {%- endfor -%} +{% else -%} +# gitfs_env_whitelist: +# - base +# - v1.* +{% endif %} + +{% if 'gitfs_env_blacklist' in cfg_master -%} +{%- do default_keys.append('gitfs_env_blacklist') %} +gitfs_env_blacklist: + {%- for git_env in cfg_master['gitfs_env_blacklist'] %} + - {{ git_env }} + {%- endfor -%} +{% else -%} +# gitfs_env_blacklist: +# - bug/* +# - feature/* +{% endif %} + +# S3 File Server Backend Configuration +# +# S3 credentials must be set in the master config file. +# Alternatively, if on EC2 these credentials can be automatically +# loaded from instance metadata. +{% if 's3.keyid' in cfg_master -%} +{{ get_config('s3.keyid', '') }} +{{ get_config('s3.key', '') }} +{% else -%} +# s3.keyid: GKTADJGHEIQSXMKKRBJ08H +# s3.key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs +{% endif %} +# This fileserver supports two modes of operation for the buckets: +# - A single bucket per environment +# - Multiple environments per bucket +# +# Note that bucket names must be all lowercase both in the AWS console +# and in Salt, otherwise you may encounter SignatureDoesNotMatch +# errors. +# +# A multiple-environment bucket must adhere to the following root +# directory structure: +# +# s3://// +# +# This fileserver back-end requires the use of the MD5 hashing +# algorithm. MD5 may not be compliant with all security policies. +{% if 's3.buckets' in cfg_master -%} +{{ get_config('s3.buckets', '') }} +{% else -%} +# s3.buckets: #single bucket per environment +# production: +# - bucket1 +# - bucket2 +# staging: +# - bucket3 +# - bucket4 +# +# s3.buckets: #multiple environments per bucket +# - bucket1 +# - bucket2 +# - bucket3 +# - bucket4 +{% endif %} ##### Pillar settings ##### ########################################## @@ -642,33 +935,51 @@ gitfs_remotes: # Pillar is laid out in the same fashion as the file server, with environments, # a top file and sls files. However, pillar data does not need to be in the # highstate format, and is generally just key/value pairs. -{% if 'pillar_roots' in cfg_master %} +{% if 'pillar_roots' in cfg_master -%} +{%- do default_keys.append('pillar_roots') %} pillar_roots: -{% for name, roots in cfg_master['pillar_roots']|dictsort %} +{%- for name, roots in cfg_master['pillar_roots']|dictsort %} {{ name }}: -{% for dir in roots %} +{%- for dir in roots %} - {{ dir }} -{% endfor %} -{% endfor %} -{% elif 'pillar_roots' in cfg_salt %} +{%- endfor -%} +{%- endfor -%} +{% elif 'pillar_roots' in cfg_salt -%} pillar_roots: -{% for name, roots in cfg_salt['pillar_roots']|dictsort %} +{%- for name, roots in cfg_salt['pillar_roots']|dictsort %} {{ name }}: -{% for dir in roots %} +{%- for dir in roots %} - {{ dir }} -{% endfor %} -{% endfor %} -{% else %} +{%- endfor -%} +{%- endfor -%} +{%- else -%} #pillar_roots: # base: # - /srv/pillar -{% endif %} -# +{%- endif %} + {% if 'ext_pillar' in cfg_master %} +{%- do default_keys.append('ext_pillar') %} ext_pillar: -{% for pillar in cfg_master['ext_pillar'] %} - - {{ pillar.items()[0][0] }}: {{ pillar.items()[0][1] }} -{% endfor %} +{%- for pillar in cfg_master['ext_pillar'] -%} + {%- for key in pillar -%} + {%- if pillar[key] is string %} + - {{ key }}: {{ pillar[key] }} + {%- elif pillar[key] is iterable and pillar[key] is not mapping %} + - {{ key }}: + {%- for parameter in pillar[key] %} + - {{ parameter }} + {%- endfor -%} + {%- elif pillar[key] is mapping and pillar[key] is not string %} + - {{ key }}: + {%- for parameter in pillar[key] %} + {{ parameter }}: {{pillar[key][parameter]}} + {%- endfor %} + {%- else %} +# Error in rendering {{ key }}, please read https://docs.saltstack.com/en/latest/topics/development/external_pillars.html#configuration + {% endif %} + {%- endfor -%} +{%- endfor %} {% elif 'ext_pillar' in cfg_salt %} ext_pillar: {% for pillar in cfg_salt['ext_pillar'] %} @@ -695,16 +1006,95 @@ ext_pillar: # The pillar_opts option adds the master configuration file data to a dict in # the pillar called "master". This is used to set simple configurations in the # master config file that can then be used on minions. -{{ get_config('pillar_opts', 'True') }} +{{ get_config('pillar_opts', 'False') }} +# The pillar_safe_render_error option prevents the master from passing pillar +# render errors to the minion. This is set on by default because the error could +# contain templating data which would give that minion information it shouldn't +# have, like a password! When set true the error message will only show: +# Rendering SLS 'my.sls' failed. Please see master log for details. +{{ get_config('pillar_safe_render_error', 'True') }} + +# The pillar_source_merging_strategy option allows you to configure merging strategy +# between different sources. It accepts four values: recurse, aggregate, overwrite, +# or smart. Recurse will merge recursively mapping of data. Aggregate instructs +# aggregation of elements between sources that use the #!yamlex renderer. Overwrite +# will verwrite elements according the order in which they are processed. This is +# behavior of the 2014.1 branch and earlier. Smart guesses the best strategy based +# on the "renderer" setting and is the default value. +{{ get_config('pillar_source_merging_strategy', 'smart') }} + +# Recursively merge lists by aggregating them instead of replacing them. +{{ get_config('pillar_merge_lists', False) }} + +# Git External Pillar (git_pillar) Configuration Options +# +# Specify the provider to be used for git_pillar. Must be either pygit2 or +# gitpython. If unset, then both will be tried in that same order, and the +# first one with a compatible version installed will be the provider that +# is used. +{{ get_config('git_pillar_provider', 'pygit2') }} + +# If the desired branch matches this value, and the environment is omitted +# from the git_pillar configuration, then the environment for that git_pillar +# remote will be base. +{{ get_config('git_pillar_base', 'master') }} + +# If the branch is omitted from a git_pillar remote, then this branch will +# be used instead. +{{ get_config('git_pillar_branch', 'master') }} + +# Environment to use for git_pillar remotes. This is normally derived from +# the branch/tag (or from a per-remote env parameter), but if set this will +# override the process of deriving the env from the branch/tag name. +{{ get_config('git_pillar_env', '') }} + +# Path relative to the root of the repository where the git_pillar top file +# and SLS files are located. +{{ get_config('git_pillar_root', 'pillar') }} + +# Specifies whether or not to ignore SSL certificate errors when contacting +# the remote repository. +{{ get_config('git_pillar_ssl_verify', True) }} + +# When set to False, if there is an update/checkout lock for a git_pillar +# remote and the pid written to it is not running on the master, the lock +# file will be automatically cleared and a new lock will be obtained. +{{ get_config('git_pillar_global_lock', False) }} + +# Git External Pillar Authentication Options +# +# Along with git_pillar_password, is used to authenticate to HTTPS remotes. +{{ get_config('git_pillar_user', '') }} + +# Along with git_pillar_user, is used to authenticate to HTTPS remotes. +# This parameter is not required if the repository does not use authentication. +{{ get_config('git_pillar_password', '') }} + +# By default, Salt will not authenticate to an HTTP (non-HTTPS) remote. +# This parameter enables authentication over HTTP. +{{ get_config('git_pillar_insecure_auth', False) }} + +# Along with git_pillar_privkey (and optionally git_pillar_passphrase), +# is used to authenticate to SSH remotes. +{{ get_config('git_pillar_pubkey', '') }} + +# Along with git_pillar_pubkey (and optionally git_pillar_passphrase), +# is used to authenticate to SSH remotes. +{{ get_config('git_pillar_privkey', '') }} + +# This parameter is optional, required only when the SSH key being used +# to authenticate is protected by a passphrase. +{{ get_config('git_pillar_passphrase', '') }} ##### Syndic settings ##### ########################################## # The Salt syndic is used to pass commands through a master from a higher -# master. Using the syndic is simple, if this is a master that will have -# syndic servers(s) below it set the "order_masters" setting to True, if this -# is a master that will be running a syndic daemon for passthrough the -# "syndic_master" setting needs to be set to the location of the master server +# master. Using the syndic is simple. If this is a master that will have +# syndic servers(s) below it, then set the "order_masters" setting to True. +# +# If this is a master that will be running a syndic daemon for passthrough, then +# the "syndic_master" setting needs to be set to the location of the master server # to receive commands from. # Set the order_masters setting to True if this master will command lower @@ -724,6 +1114,7 @@ ext_pillar: # LOG file of the syndic daemon: {{ get_config('syndic_log_file', 'syndic.log') }} + ##### Peer Publish settings ##### ########################################## # Salt minions can send commands to other minions, but only if the minion is @@ -748,6 +1139,7 @@ ext_pillar: # This is not recommended, since it would allow anyone who gets root on any # single minion to instantly have root on all of the minions! {% if 'peer' in cfg_master %} +{%- do default_keys.append('peer') %} peer: {% for name, roots in cfg_master['peer'].items() %} {{ name }}: @@ -781,6 +1173,7 @@ peer: # foo.example.com: # - manage.up {% if 'peer_run' in cfg_master %} +{%- do default_keys.append('peer_run') %} peer_run: {% for name, roots in cfg_master['peer_run'].items() %} {{ name }}: @@ -798,9 +1191,8 @@ peer_run: {% endfor %} {% endif %} - ##### Mine settings ##### -########################################## +##################################### # Restrict mine.get access from minions. By default any minion has a full access # to get all mine data from master cache. In acl definion below, only pcre matches # are allowed. @@ -812,6 +1204,7 @@ peer_run: # data only, minions web* to get all network.* and disk.* mine data and all other # minions won't get any mine data. {% if 'mine_get' in cfg_master -%} +{%- do default_keys.append('mine_get') %} mine_get: {%- for minion, data in cfg_master['mine_get']|dictsort %} {{ minion }}: @@ -836,7 +1229,6 @@ mine_get: # - disk.* {%- endif %} - ##### Logging settings ##### ########################################## # The location of the master log file @@ -853,10 +1245,15 @@ mine_get: # The level of messages to send to the console. # One of 'garbage', 'trace', 'debug', info', 'warning', 'error', 'critical'. +# +# The following log levels are considered INSECURE and may log sensitive data: +# ['garbage', 'trace', 'debug'] +# {{ get_config('log_level', 'warning') }} # The level of messages to send to the log file. # One of 'garbage', 'trace', 'debug', info', 'warning', 'error', 'critical'. +# If using 'log_granular_levels' this must be set to the highest desired level. {{ get_config('log_level_logfile', 'warning') }} # The date and time format used in log messages. Allowed date/time formating @@ -866,7 +1263,21 @@ mine_get: # The format of the console logging messages. Allowed formatting options can # be seen here: http://docs.python.org/library/logging.html#logrecord-attributes +# +# Console log colors are specified by these additional formatters: +# +# %(colorlevel)s +# %(colorname)s +# %(colorprocess)s +# %(colormsg)s +# +# Since it is desirable to include the surrounding brackets, '[' and ']', in +# the coloring of the messages, these color formatters also include padding as +# well. Color LogRecord attributes are only available for console logging. +# +{{ get_config('log_fmt_console', "'%(colorlevel)s %(colormsg)s'") }} {{ get_config('log_fmt_console', "'[%(levelname)-8s] %(message)s'") }} + {{ get_config('log_fmt_logfile', "'%(asctime)s,%(msecs)03.0f [%(name)-17s][%(levelname)-8s] %(message)s'") }} # This can be used to control logging levels more specificically. This @@ -877,6 +1288,7 @@ mine_get: # 'salt.modules': 'debug' # {% if 'log_granular_levels' in cfg_master %} +{%- do default_keys.append('log_granular_levels') %} log_granular_levels: {% for name, lvl in cfg_master['log_granular_levels'].items() %} {{ name }}: {{ lvl }} @@ -890,26 +1302,25 @@ log_granular_levels: #log_granular_levels: {} {% endif %} - -##### Node Groups ##### +##### Node Groups ###### ########################################## # Node groups allow for logical groupings of minion nodes. A group consists of a group # name and a compound target. #nodegroups: # group1: 'L@foo.domain.com,bar.domain.com,baz.domain.com and bl*.domain.com' # group2: 'G@os:Debian and foo.domain.com' -{% if 'nodegroups' in cfg_master %} +{%- if 'nodegroups' in cfg_master %} +{%- do default_keys.append('nodegroups') %} nodegroups: - {% for name, lvl in cfg_master['nodegroups'].items() %} + {%- for name, lvl in cfg_master['nodegroups'].items() %} {{ name }}: {{ lvl }} - {% endfor %} -{% elif 'nodegroups' in cfg_salt %} + {%- endfor %} +{%- elif 'nodegroups' in cfg_salt %} nodegroups: - {% for name, lvl in cfg_salt['nodegroups'].items() %} + {%- for name, lvl in cfg_salt['nodegroups'].items() %} {{ name }}: {{ lvl }} - {% endfor %} -{% endif %} - + {%- endfor %} +{%- endif %} ##### Range Cluster settings ##### ########################################## @@ -918,8 +1329,66 @@ nodegroups: # {{ get_config('range_server', 'range:80') }} -##### Windows Software Repo settings ##### -############################################## + +##### Windows Software Repo settings ##### +########################################### +# Specify the provider to be used for git_pillar. Must be either pygit2 or +# gitpython. If unset, then both will be tried in that same order, and the +# first one with a compatible version installed will be the provider that +# is used. +{{ get_config('winrepo_provider', 'pygit2') }} + +# Repo settings for 2015.8+ master used with 2015.8+ Windows minions +# +# Location of the repo on the master: +{{ get_config('winrepo_dir_ng', '/srv/salt/win/repo-ng') }} + +# List of git repositories to include with the local repo: +{% if 'winrepo_remotes_ng' in cfg_master %} +{%- do default_keys.append('winrepo_remotes_ng') %} +winrepo_remotes_ng: + {% for repo in cfg_master['winrepo_remotes_ng'] %} + - {{ repo }} + {% endfor %} +{% elif 'winrepo_remotes_ng' in cfg_salt %} +winrepo_remotes_ng: + {% for repo in cfg_salt['winrepo_remotes_ng'] %} + - {{ repo }} + {% endfor %} +{% else %} +#winrepo_remotes_ng: +# - 'https://github.com/saltstack/salt-winrepo-ng.git' +{% endif %} + +# Repo settings for 2015.8+ master used with pre-2015.8 Windows minions +# +# Location of the repo on the master: +{{ get_config('winrepo_dir', '/srv/salt/win/repo') }} + +# Location of the master's repo cache file: +{{ get_config('winrepo_cachefile', 'winrepo.p') }} + +# List of git repositories to include with the local repo: +{% if 'winrepo_remotes' in cfg_master %} +{%- do default_keys.append('winrepo_remotes') %} +winrepo_remotes: + {% for repo in cfg_master['winrepo_remotes'] %} + - {{ repo }} + {% endfor %} +{% elif 'winrepo_remotes' in cfg_salt %} +winrepo_remotes: + {% for repo in cfg_salt['winrepo_remotes'] %} + - {{ repo }} + {% endfor %} +{% else %} +#winrepo_remotes: +# - 'https://github.com/saltstack/salt-winrepo.git' +{% endif %} + +##### Windows Software Repo settings - Pre 2015.8 ##### +######################################################## +# Legacy repo settings for pre-2015.8 Windows minions. +# # Location of the repo on the master: {{ get_config('win_repo', '/srv/salt/win/repo') }} @@ -928,6 +1397,7 @@ nodegroups: # List of git repositories to include with the local repo: {% if 'win_gitrepos' in cfg_master %} +{%- do default_keys.append('win_gitrepos') %} win_gitrepos: {% for repo in cfg_master['win_gitrepos'] %} - {{ repo }} @@ -938,7 +1408,7 @@ win_gitrepos: - {{ repo }} {% endfor %} {% else %} -#win_gitrepos: +#winrepo_remotes: # - 'https://github.com/saltstack/salt-winrepo.git' {% endif %} @@ -946,36 +1416,78 @@ win_gitrepos: ############################################ # Which returner(s) will be used for minion's result: #return: mysql +{{ get_config('return', '')}} -{% if 'halite' in cfg_master %} + +###### Miscellaneous settings ###### +############################################ +# Default match type for filtering events tags: startswith, endswith, find, regex, fnmatch +{{ get_config('event_match_type', 'startswith') }} + +{%- if 'halite' in cfg_master %} +{%- do default_keys.append('halite') %} ##### Halite ##### ########################################## halite: - {% for name, value in cfg_master['halite'].items() %} + {%- for name, value in cfg_master['halite'].items() %} {{ name }}: {{ value }} - {% endfor %} -{% endif %} + {%- endfor %} +{%- endif %} -{% if 'rest_cherrypy' in cfg_master %} +{%- if 'rest_cherrypy' in cfg_master %} +{%- do default_keys.append('rest_cherrypy') %} ##### rest_cherrypy ##### ########################################## rest_cherrypy: - {% for name, value in cfg_master['rest_cherrypy'].items() %} + {%- for name, value in cfg_master['rest_cherrypy'].items() %} {{ name }}: {{ value }} {%- endfor %} {%- endif %} -{% if 'rest_tornado' in cfg_master %} +{%- if 'rest_tornado' in cfg_master %} +{%- do default_keys.append('rest_tornado') %} ##### rest_tornado ##### ########################################### rest_tornado: - {% for name, value in cfg_master['rest_tornado'].items() %} + {%- for name, value in cfg_master['rest_tornado'].items() %} {{ name }}: {{ value }} {%- endfor %} {%- endif %} -{% if 'presence_events' in cfg_master %} +{%- if 'presence_events' in cfg_master %} ##### presence events ##### ########################################## {{ get_config('presence_events', 'False') }} +{%- endif %} + +{%- if 'consul_config' in cfg_master %} +{%- do default_keys.append('consul_config') %} +##### consul_config ##### +########################################## +consul_config: + {%- for name, value in cfg_master['consul_config'].items() %} + {{ name }}: {{ value }} + {%- endfor %} +{%- endif %} + +{% if 'mongo' in cfg_master -%} +{%- do default_keys.append('mongo') %} +##### mongodb connection settings ##### +########################################## +{%- for name, value in cfg_master['mongo'].items() %} +mongo.{{ name }}: {{ value }} +{%- endfor %} + +{% if 'alternative.mongo' in cfg_master -%} +{%- do default_keys.append('alternative.mongo') %} +{%- for name, value in cfg_master['alternative.mongo'].items() %} +alternative.mongo.{{ name }}: {{ value }} +{%- endfor %} {% endif %} +{%- endif %} + +{%- for configname in cfg_master %} +{%- if configname not in reserved_keys and configname not in default_keys %} +{{ configname }}: {{ cfg_master[configname]|json }} +{%- endif %} +{%- endfor %} diff --git a/salt/files/master.d/lxc_profiles.conf b/salt/files/master.d/lxc_profiles.conf new file mode 100644 index 0000000..2538848 --- /dev/null +++ b/salt/files/master.d/lxc_profiles.conf @@ -0,0 +1,42 @@ +# This file managed by Salt, do not edit by hand!! +# Based on salt version 2015.8.7 default config +{% set cfg_salt = pillar.get('salt', {}) -%} +{% set cfg_master = cfg_salt.get('master', {}) -%} +{% set cfg_prof = cfg_master.get('lxc.container_profile', {}) -%} +{% set cfg_net = cfg_master.get('lxc.network_profile', {}) -%} + +###### Profile configurations ######### +####################################### +{% if cfg_prof %} +lxc.container_profile: +{%- for prof in cfg_prof %} + {{ prof }}: +{%- for conf in cfg_prof[prof] %} +{%- if cfg_prof[prof][conf] is mapping %} + {{ conf }}: +{%- for opt in cfg_prof[prof][conf] %} + {{ opt }}: {{ cfg_prof[prof][conf][opt] }} +{%- endfor %} +{%- else %} + {{ conf }}: {{ cfg_prof[prof][conf] }} +{%- endif %} +{%- endfor %} +{% endfor %} +{%- endif %} + +{% if cfg_net %} +lxc.network_profile: +{%- for prof in cfg_net %} + {{ prof }}: +{%- for conf in cfg_net[prof] -%} +{%- if cfg_net[prof][conf] is mapping %} + {{ conf }}: +{%- for opt in cfg_net[prof][conf] %} + {{ opt }}: {{ cfg_net[prof][conf][opt] }} +{%- endfor %} +{%- else %} + {{ conf }}: {{ cfg_net[prof][conf] }} +{%- endif %} +{%- endfor %} +{% endfor %} +{%- endif %} diff --git a/salt/files/minion.d/beacons.conf b/salt/files/minion.d/beacons.conf new file mode 100644 index 0000000..e9bb4f8 --- /dev/null +++ b/salt/files/minion.d/beacons.conf @@ -0,0 +1,9 @@ +# +# This file is managed by Salt! Do not edit by hand! +# +{%- set beacons = salt['pillar.get']('salt:beacons') -%} +{%- set beacons = salt['pillar.get']('salt:minion:beacons', default=beacons, merge=True) -%} +{%- if beacons %} +beacons: + {{ beacons | yaml(False) | indent(2) }} +{%- endif -%} diff --git a/salt/files/minion.d/engine.conf b/salt/files/minion.d/engine.conf new file mode 100644 index 0000000..695e3ed --- /dev/null +++ b/salt/files/minion.d/engine.conf @@ -0,0 +1,9 @@ +# +# This file is managed by Salt! Do not edit by hand! +# +{%- set engines = salt['pillar.get']('salt:engines', {}) -%} +{%- set engines = salt['pillar.get']('salt:minion:engines', default=engines, merge=True) -%} +{%- if engines %} +engines: + {{ engines | yaml(False) | indent(2) }} +{%- endif -%} diff --git a/salt/files/minion.d/f_defaults.conf b/salt/files/minion.d/f_defaults.conf index 3c234ca..d4110c8 100644 --- a/salt/files/minion.d/f_defaults.conf +++ b/salt/files/minion.d/f_defaults.conf @@ -1,20 +1,29 @@ # This file managed by Salt, do not edit by hand!! -# Based on salt version 0.17.4 default config -{% set reserved_keys = ['master', 'minion', 'cloud', 'salt_cloud_certs'] -%} +# Based on salt version 2015.8.7 default config +# +{% set reserved_keys = ['master', 'minion', 'cloud', 'salt_cloud_certs', 'engines', 'beacons'] -%} {% set cfg_salt = pillar.get('salt', {}) -%} {% set cfg_minion = cfg_salt.get('minion', {}) -%} +{% set default_keys = [] -%} {%- macro get_config(configname, default_value) -%} +{%- do default_keys.append(configname) %} {%- if configname in cfg_minion -%} -{{ configname }}: {{ cfg_minion[configname] }} +{{ configname }}: {{ cfg_minion[configname]|json }} {%- elif configname in cfg_salt and configname not in reserved_keys -%} -{{ configname }}: {{ cfg_salt[configname] }} +{{ configname }}: {{ cfg_salt[configname]|json }} {%- else -%} -#{{ configname }}: {{ default_value }} +#{{ configname }}: {{ default_value|json }} {%- endif -%} {%- endmacro -%} {%- from 'salt/formulas.jinja' import file_roots, formulas with context -%} + ##### Primary configuration settings ##### ########################################## +# This configuration file is used to manage the behavior of the Salt Minion. +# With the exception of the location of the Salt Master Server, values that are +# commented out but have an empty line after the comment are defaults that need +# not be set in the config. If there is no blank line after the comment, the +# value is presented as an example and is not the default. # Per default the minion will automatically include all config files # from minion.d/*.conf (minion.d is a directory in the same directory @@ -23,9 +32,7 @@ # Set the location of the salt master server. If the master server cannot be # resolved, then the minion will fail to start. -# master:salt -{%- if 'master' in cfg_minion -%} -{%- if cfg_minion['master'] is not string %} +{%- if 'master' in cfg_minion and cfg_minion['master'] is not string %} master: {% for name in cfg_minion['master'] -%} - {{ name }} @@ -33,24 +40,35 @@ master: {%- else %} {{ get_config('master', 'salt') }} {%- endif %} -{% elif 'master' in cfg_salt -%} -{%- if cfg_salt['master'] is not string %} -master: - {% for name in cfg_salt['master'] -%} - - {{ name }} - {% endfor -%} -{%- else %} -{{ get_config('master', 'salt') }} -{%- endif -%} -{%- endif %} # If multiple masters are specified in the 'master' setting, the default behavior # is to always try to connect to them in the order they are listed. If random_master is # set to True, the order will be randomized instead. This can be helpful in distributing # the load of many minions executing salt-call requests, for example, from a cron job. # If only one master is listed, this setting is ignored and a warning will be logged. +# NOTE: If master_type is set to failover, use master_shuffle instead. {{ get_config('random_master', 'False') }} +# Use if master_type is set to failover. +{{ get_config('master_shuffle', 'False') }} + +# Minions can connect to multiple masters simultaneously (all masters +# are "hot"), or can be configured to failover if a master becomes +# unavailable. Multiple hot masters are configured by setting this +# value to "str". Failover masters can be requested by setting +# to "failover". MAKE SURE TO SET master_alive_interval if you are +# using failover. +{{ get_config('master_type', 'str') }} + +# verify_master_pubkey_sign +{{ get_config('verify_master_pubkey_sign', 'False') }} + +# Poll interval in seconds for checking if the master is still there. Only +# respected if master_type above is "failover". To disable the interval entirely, +# set the value to -1. (This may be necessary on machines which have high numbers +# of TCP connections, such as load balancers.) +{{ get_config('master_alive_interval', '30') }} + # Set whether the minion should connect to the master via IPv6: {{ get_config('ipv6', 'False') }} @@ -65,6 +83,12 @@ master: # The user to run salt. {{ get_config('user', 'root') }} +# Setting sudo_user will cause salt to run all execution modules under an sudo +# to the user given in sudo_user. The user under which the salt minion process +# itself runs will still be that provided in the user config above, but all +# execution modules run by the minion will be rerouted through sudo. +{{ get_config('sudo_user', 'saltdev') }} + # Specify the location of the daemon process ID file. {{ get_config('pidfile', '/var/run/salt-minion.pid') }} @@ -81,6 +105,7 @@ master: # same machine but with different ids, this can be useful for salt compute # clusters. {% if 'id' in cfg_minion -%} +{%- do default_keys.append('id') %} id: {{ cfg_minion['id'] }} {% else -%} #id: @@ -104,6 +129,7 @@ id: {{ cfg_minion['id'] }} {{ get_config('grains', '{}') }} # Where cache data goes. +# This data may contain sensitive data and should be protected accordingly. {{ get_config('cachedir', '/var/cache/salt/minion') }} # Verify and set permissions on configuration directories at startup. @@ -121,7 +147,7 @@ id: {{ cfg_minion['id'] }} # Set the default outputter used by the salt-call command. The default is # "nested". {{ get_config('output', 'nested') }} -# + # By default output is colored. To disable colored output, set the color value # to False. {{ get_config('color', 'True') }} @@ -181,22 +207,19 @@ id: {{ cfg_minion['id'] }} # Ping Master to ensure connection is alive (minutes). {{ get_config('ping_interval', '0') }} -# The Salt Mine functions are executed when the minion starts and at a given interval by the scheduler. -# The default interval is every 60 minutes. -{{ get_config('mine_interval', '60') }} - {%- if 'mine_functions' in cfg_minion %} +{%- do default_keys.append('mine_functions') %} mine_functions: {%- for func, args in cfg_minion['mine_functions'].items() %} {{ func }}: {{ args }} {%- endfor %} {%- endif %} + # To auto recover minions if master changes IP address (DDNS) # auth_tries: 10 # auth_safemode: False # ping_interval: 90 -# restart_on_error: True # # Minions won't know master is missing until a ping fails. After the ping fail, # the minion will attempt authentication and likely fails out and cause a restart. @@ -316,13 +339,8 @@ mine_functions: # option then the minion will log a warning message. # # Include a config file from some other path: -# include: /etc/salt/extra_config -# -# Include config from several files and directories: -#include: -# - /etc/salt/extra_config -# - /etc/roles/webserver {% if 'include' in cfg_minion -%} +{%- do default_keys.append('include') %} {% if isinstance(cfg_minion['include'], list) -%} include: {% for include in cfg_minion['include'] -%} @@ -342,14 +360,13 @@ mine_functions: {% endif -%} {% endif -%} - ##### Minion module management ##### ########################################## # Disable specific modules. This allows the admin to limit the level of # access the master has to the minion. {{ get_config('disable_modules', '[cmd,test]') }} {{ get_config('disable_returners', '[]') }} -# + # Modules can be loaded from arbitrary paths. This enables the easy deployment # of third party modules. Modules for returners and minions can be loaded. # Specify a list of extra directories to search for minion modules and @@ -359,7 +376,7 @@ mine_functions: {{ get_config('states_dirs', '[]') }} {{ get_config('render_dirs', '[]') }} {{ get_config('utils_dirs', '[]') }} -# + # A module provider can be statically overwritten or extended for the minion # via the providers option, in this case the default module will be # overwritten by the specified module. In this example the pkg module will @@ -367,15 +384,14 @@ mine_functions: #providers: # pkg: yumpkg5 {{ get_config('providers', '{}') }} -# + # Enable Cython modules searching and loading. (Default: False) {{ get_config('cython_enable', 'False') }} -# + # Specify a max size (in bytes) for modules on import. This feature is currently # only supported on *nix operating systems and requires psutil. {{ get_config('modules_max_memory', '-1') }} - ##### State Management Settings ##### ########################################### # The state management system executes all of the state templates on the minion @@ -391,44 +407,42 @@ mine_functions: # json_wempy # {{ get_config('renderer', 'yaml_jinja') }} -# + # The failhard option tells the minions to stop immediately after the first # failure detected in the state execution. Defaults to False. {{ get_config('failhard', 'False') }} -# -# autoload_dynamic_modules turns on automatic loading of modules found in the -# environments on the master. This is turned on by default. To turn of -# autoloading modules when states run, set this value to False. + +# Reload the modules prior to a highstate run. {{ get_config('autoload_dynamic_modules', 'True') }} -# + # clean_dynamic_modules keeps the dynamic modules on the minion in sync with # the dynamic modules on the master, this means that if a dynamic module is # not on the master it will be deleted from the minion. By default, this is # enabled and can be disabled by changing this value to False. {{ get_config('clean_dynamic_modules', 'True') }} -# + # Normally, the minion is not isolated to any single environment on the master # when running states, but the environment can be isolated on the minion side # by statically setting it. Remember that the recommended way to manage # environments is to isolate via the top file. {{ get_config('environment', 'None') }} -# + # If using the local file directory, then the state top file name needs to be # defined, by default this is top.sls. {{ get_config('state_top', 'top.sls') }} -# + # Run states when the minion daemon starts. To enable, set startup_states to: # 'highstate' -- Execute state.highstate # 'sls' -- Read in the sls_list option and execute the named sls files # 'top' -- Read top_file option and execute based on that file on the Master {{ get_config('startup_states', "''") }} -# + # List of states to run when the minion starts up if startup_states is 'sls': #sls_list: # - edit.vim # - hyper {{ get_config('sls_list', '[]') }} -# + # Top file to execute if startup_states is 'top': {{ get_config('top_file', "''") }} @@ -440,6 +454,7 @@ mine_functions: # - pkg # #state_aggregate: False +{{ get_config('state_aggregate', '{}') }} ##### File Directory Settings ##### ########################################## @@ -450,7 +465,8 @@ mine_functions: # Set the file client. The client defaults to looking on the master server for # files, but can be directed to look at the local file directory setting -# defined below by setting it to local. +# defined below by setting it to "local". Setting a local file_client runs the +# minion in masterless mode. {%- if standalone %} file_client: local {%- else %} @@ -471,8 +487,8 @@ file_client: local # prod: # - /srv/salt/prod/services # - /srv/salt/prod/states -# {% if 'file_roots' in cfg_minion -%} +{%- do default_keys.append('file_roots') %} {{ file_roots(cfg_minion['file_roots']) }} {%- elif 'file_roots' in cfg_salt -%} {{ file_roots(cfg_salt['file_roots']) }} @@ -484,6 +500,30 @@ file_client: local # - /srv/salt {%- endif %} + +# File Server Backend +# +# Salt supports a modular fileserver backend system, this system allows +# the salt minion to link directly to third party systems to gather and +# manage the files available to minions. Multiple backends can be +# configured and will be searched for the requested file in the order in which +# they are defined here. The default setting only enables the standard backend +# "roots" which uses the "file_roots" option. +#fileserver_backend: +# - roots +# +# To use multiple backends list them in the order they are searched: +#fileserver_backend: +# - git +# - roots +{% if 'fileserver_backend' in cfg_minion -%} +{%- do default_keys.append('fileserver_backend') %} +fileserver_backend: +{%- for backend in cfg_minion['fileserver_backend'] %} + - {{ backend }} +{%- endfor -%} +{%- endif %} + # By default, the Salt fileserver recurses fully into all defined environments # to attempt to find files. To limit this behavior so that the fileserver only # traverses directories with SLS files and special Salt directories like _modules, @@ -492,13 +532,41 @@ file_client: local # is False. {{ get_config('fileserver_limit_traversal', 'False') }} +# The hash_type is the hash to use when discovering the hash of a file in +# the local fileserver. The default is md5, but sha1, sha224, sha256, sha384 +# and sha512 are also supported. # -# Git fileserver backend configuration -# -# Gitfs can be provided by one of two python modules: GitPython or pygit2. If -# using pygit2, both libgit2 and git must also be installed. +# Warning: Prior to changing this value, the minion should be stopped and all +# Salt caches should be cleared. +{{ get_config('hash_type', 'md5') }} + +# gitfs provider {{ get_config('gitfs_provider', 'pygit2') }} -# + +# Along with gitfs_password, is used to authenticate to HTTPS remotes. +{{ get_config('gitfs_user', 'git') }} + +# Along with gitfs_user, is used to authenticate to HTTPS remotes. +# This parameter is not required if the repository does not use authentication. +{{ get_config('gitfs_password', '') }} + +# By default, Salt will not authenticate to an HTTP (non-HTTPS) remote. +# This parameter enables authentication over HTTP. Enable this at your own risk. +{{ get_config('gitfs_insecure_auth', 'False') }} + +# Along with gitfs_privkey (and optionally gitfs_passphrase), is used to +# authenticate to SSH remotes. This parameter (or its per-remote counterpart) +# is required for SSH remotes. +{{ get_config('gitfs_pubkey', '') }} + +# Along with gitfs_pubkey (and optionally gitfs_passphrase), is used to +# authenticate to SSH remotes. This parameter (or its per-remote counterpart) +# is required for SSH remotes. +{{ get_config('gitfs_privkey', '') }} + +# This parameter is optional, required only when the SSH key being used to +# authenticate is protected by a passphrase. +{{ get_config('gitfs_passphrase', '') }} # When using the git fileserver backend at least one git remote needs to be # defined. The user running the salt master will need read access to the repo. # @@ -509,6 +577,7 @@ file_client: local # Note: file:// repos will be treated as a remote, so refs you want used must # exist in that repo as *local* refs. {% if 'gitfs_remotes' in cfg_minion -%} +{%- do default_keys.append('gitfs_remotes') %} gitfs_remotes: {%- for remote in cfg_minion['gitfs_remotes'] %} {%- if remote is iterable and remote is not string %} @@ -525,35 +594,52 @@ gitfs_remotes: {%- endif -%} {%- endfor -%} {%- endif %} -# -#gitfs_remotes: -# - git://github.com/saltstack/salt-states.git -# - file:///var/git/saltmaster -# + # The gitfs_ssl_verify option specifies whether to ignore ssl certificate # errors when contacting the gitfs backend. You might want to set this to # false if you're using a git backend that uses a self-signed certificate but # keep in mind that setting this flag to anything other than the default of True # is a security concern, you may want to try using the ssh transport. {{ get_config('gitfs_ssl_verify', 'True') }} - + # The gitfs_root option gives the ability to serve files from a subdirectory # within the repository. The path is defined relative to the root of the # repository and defaults to the repository root. {{ get_config('gitfs_root', 'somefolder/otherfolder') }} - -# The hash_type is the hash to use when discovering the hash of a file in -# the local fileserver. The default is md5, but sha1, sha224, sha256, sha384 -# and sha512 are also supported. -# -# Warning: Prior to changing this value, the minion should be stopped and all -# Salt caches should be cleared. -{{ get_config('hash_type', 'md5') }} +# The gitfs_env_whitelist and gitfs_env_blacklist parameters allow for greater +# control over which branches/tags are exposed as fileserver environments. +{% if 'gitfs_env_whitelist' in cfg_minion -%} +{%- do default_keys.append('gitfs_env_whitelist') %} +gitfs_env_whitelist: + {%- for git_env in cfg_minion['gitfs_env_whitelist'] %} + - {{ git_env }} + {%- endfor -%} +{% else -%} +# gitfs_env_whitelist: +# - base +# - v1.* +{% endif %} + +{% if 'gitfs_env_blacklist' in cfg_minion -%} +{%- do default_keys.append('gitfs_env_blacklist') %} +gitfs_env_blacklist: + {%- for git_env in cfg_minion['gitfs_env_blacklist'] %} + - {{ git_env }} + {%- endfor -%} +{% else -%} +# gitfs_env_blacklist: +# - bug/* +# - feature/* +{% endif %} + +##### Pillar settings ##### +########################################## # The Salt pillar is searched for locally if file_client is set to local. If # this is the case, and pillar data is defined, then the pillar_roots need to # also be configured on the minion: {% if 'pillar_roots' in cfg_minion -%} +{%- do default_keys.append('pillar_roots') %} pillar_roots: {%- for name, roots in cfg_minion['pillar_roots']|dictsort %} {{ name }}: @@ -569,12 +655,141 @@ pillar_roots: - {{ dir }} {%- endfor -%} {%- endfor -%} -{% else -%} +{%- else -%} #pillar_roots: # base: -# - /srv/salt +# - /srv/pillar {%- endif %} +{% if 'ext_pillar' in cfg_minion %} +{%- do default_keys.append('ext_pillar') %} +ext_pillar: +{%- for pillar in cfg_minion['ext_pillar'] -%} + {%- for key in pillar -%} + {%- if pillar[key] is string %} + - {{ key }}: {{ pillar[key] }} + {%- elif pillar[key] is iterable and pillar[key] is not mapping %} + - {{ key }}: + {%- for parameter in pillar[key] %} + - {{ parameter }} + {%- endfor -%} + {%- elif pillar[key] is mapping and pillar[key] is not string %} + - {{ key }}: + {%- for parameter in pillar[key] %} + {{ parameter }}: {{pillar[key][parameter]}} + {%- endfor %} + {%- else %} +# Error in rendering {{ key }}, please read https://docs.saltstack.com/en/latest/topics/development/external_pillars.html#configuration + {% endif %} + {%- endfor -%} +{%- endfor %} +{% elif 'ext_pillar' in cfg_salt %} +ext_pillar: +{% for pillar in cfg_salt['ext_pillar'] %} + - {{ pillar.items()[0][0] }}: {{ pillar.items()[0][1] }} +{% endfor %} +{% else %} +#ext_pillar: +# - hiera: /etc/hiera.yaml +# - cmd_yaml: cat /etc/salt/yaml +{% endif %} + +# The ext_pillar_first option allows for external pillar sources to populate +# before file system pillar. This allows for targeting file system pillar from +# ext_pillar. +{{ get_config('ext_pillar_first', 'False') }} + +# The pillar_gitfs_ssl_verify option specifies whether to ignore ssl certificate +# errors when contacting the pillar gitfs backend. You might want to set this to +# false if you're using a git backend that uses a self-signed certificate but +# keep in mind that setting this flag to anything other than the default of True +# is a security concern, you may want to try using the ssh transport. +{{ get_config('pillar_gitfs_ssl_verify', 'True') }} + +# The pillar_opts option adds the master configuration file data to a dict in +# the pillar called "master". This is used to set simple configurations in the +# master config file that can then be used on minions. +{{ get_config('pillar_opts', 'True') }} + +# The pillar_safe_render_error option prevents the master from passing pillar +# render errors to the minion. This is set on by default because the error could +# contain templating data which would give that minion information it shouldn't +# have, like a password! When set true the error message will only show: +# Rendering SLS 'my.sls' failed. Please see master log for details. +{{ get_config('pillar_safe_render_error', 'True') }} + +# The pillar_source_merging_strategy option allows you to configure merging strategy +# between different sources. It accepts four values: recurse, aggregate, overwrite, +# or smart. Recurse will merge recursively mapping of data. Aggregate instructs +# aggregation of elements between sources that use the #!yamlex renderer. Overwrite +# will verwrite elements according the order in which they are processed. This is +# behavior of the 2014.1 branch and earlier. Smart guesses the best strategy based +# on the "renderer" setting and is the default value. +{{ get_config('pillar_source_merging_strategy', 'smart') }} + +# Recursively merge lists by aggregating them instead of replacing them. +{{ get_config('pillar_merge_lists', False) }} + +# Git External Pillar (git_pillar) Configuration Options +# +# Specify the provider to be used for git_pillar. Must be either pygit2 or +# gitpython. If unset, then both will be tried in that same order, and the +# first one with a compatible version installed will be the provider that +# is used. +{{ get_config('git_pillar_provider', 'pygit2') }} + +# If the desired branch matches this value, and the environment is omitted +# from the git_pillar configuration, then the environment for that git_pillar +# remote will be base. +{{ get_config('git_pillar_base', 'master') }} + +# If the branch is omitted from a git_pillar remote, then this branch will +# be used instead. +{{ get_config('git_pillar_branch', 'master') }} + +# Environment to use for git_pillar remotes. This is normally derived from +# the branch/tag (or from a per-remote env parameter), but if set this will +# override the process of deriving the env from the branch/tag name. +{{ get_config('git_pillar_env', '') }} + +# Path relative to the root of the repository where the git_pillar top file +# and SLS files are located. +{{ get_config('git_pillar_root', 'pillar') }} + +# Specifies whether or not to ignore SSL certificate errors when contacting +# the remote repository. +{{ get_config('git_pillar_ssl_verify', True) }} + +# When set to False, if there is an update/checkout lock for a git_pillar +# remote and the pid written to it is not running on the master, the lock +# file will be automatically cleared and a new lock will be obtained. +{{ get_config('git_pillar_global_lock', False) }} + +# Git External Pillar Authentication Options +# +# Along with git_pillar_password, is used to authenticate to HTTPS remotes. +{{ get_config('git_pillar_user', '') }} + +# Along with git_pillar_user, is used to authenticate to HTTPS remotes. +# This parameter is not required if the repository does not use authentication. +{{ get_config('git_pillar_password', '') }} + +# By default, Salt will not authenticate to an HTTP (non-HTTPS) remote. +# This parameter enables authentication over HTTP. +{{ get_config('git_pillar_insecure_auth', False) }} + +# Along with git_pillar_privkey (and optionally git_pillar_passphrase), +# is used to authenticate to SSH remotes. +{{ get_config('git_pillar_pubkey', '') }} + +# Along with git_pillar_pubkey (and optionally git_pillar_passphrase), +# is used to authenticate to SSH remotes. +{{ get_config('git_pillar_privkey', '') }} + +# This parameter is optional, required only when the SSH key being used +# to authenticate is protected by a passphrase. +{{ get_config('git_pillar_passphrase', '') }} + ###### Security settings ##### ########################################### @@ -606,11 +821,16 @@ pillar_roots: # states is cluttering the logs. Set it to True to ignore them. {{ get_config('state_output_diff', 'False') }} -# Fingerprint of the master public key to double verify the master is valid, -# the master fingerprint can be found by running "salt-key -F master" on the -# salt master. +# The state_output_profile setting changes whether profile information +# will be shown for each state run. +{{ get_config('state_output_profile', 'True') }} + +# Fingerprint of the master public key to validate the identity of your Salt master +# before the initial key exchange. The master fingerprint can be found by running +# "salt-key -F master" on the Salt master. {{ get_config('master_finger', "''") }} + ###### Thread settings ##### ########################################### # Disable multiprocessing support, by default when a minion receives a @@ -634,6 +854,10 @@ pillar_roots: # The level of messages to send to the console. # One of 'garbage', 'trace', 'debug', info', 'warning', 'error', 'critical'. +# +# The following log levels are considered INSECURE and may log sensitive data: +# ['garbage', 'trace', 'debug'] +# # Default: 'warning' {{ get_config('log_level', 'warning') }} @@ -650,7 +874,21 @@ pillar_roots: # The format of the console logging messages. Allowed formatting options can # be seen here: http://docs.python.org/library/logging.html#logrecord-attributes +# +# Console log colors are specified by these additional formatters: +# +# %(colorlevel)s +# %(colorname)s +# %(colorprocess)s +# %(colormsg)s +# +# Since it is desirable to include the surrounding brackets, '[' and ']', in +# the coloring of the messages, these color formatters also include padding as +# well. Color LogRecord attributes are only available for console logging. +# +{{ get_config('log_fmt_console', "'%(colorlevel)s %(colormsg)s'") }} {{ get_config('log_fmt_console', "'[%(levelname)-8s] %(message)s'") }} +# {{ get_config('log_fmt_logfile', "'%(asctime)s,%(msecs)03.0f [%(name)-17s][%(levelname)-8s] %(message)s'") }} # This can be used to control logging levels more specificically. This @@ -662,6 +900,24 @@ pillar_roots: # {{ get_config('log_granular_levels', '{}') }} +# To diagnose issues with minions disconnecting or missing returns, ZeroMQ +# supports the use of monitor sockets to log connection events. This +# feature requires ZeroMQ 4.0 or higher. +# +# To enable ZeroMQ monitor sockets, set 'zmq_monitor' to 'True' and log at a +# debug level or higher. +# +# A sample log event is as follows: +# +# [DEBUG ] ZeroMQ event: {'endpoint': 'tcp://127.0.0.1:4505', 'event': 512, +# 'value': 27, 'description': 'EVENT_DISCONNECTED'} +# +# All events logged will include the string 'ZeroMQ event'. A connection event +# should be logged as the minion starts up and initially connects to the +# master. If not, check for debug log level and that the necessary version of +# ZeroMQ is installed. +# +{{ get_config('zmq_monitor', 'False') }} ###### Module configuration ##### ########################################### @@ -672,8 +928,8 @@ pillar_roots: # data must be applied via the yaml dict construct, some examples: # # You can specify that all modules should run in test mode: -#test: True -# +{{ get_config('test', 'True') }} + # A simple value for the test module: #test.foo: foo # @@ -682,13 +938,17 @@ pillar_roots: # # A dict for the test module: #test.baz: {spam: sausage, cheese: bread} +# + + {%- if 'module_config' in cfg_minion %} -{%- for modkey, modval in cfg_minion.module_config.items() %} +{%- do default_keys.append('module_config') %} + {%- for modkey, modval in cfg_minion.module_config.items() %} {{ modkey }}: {{ modval }} -{%- endfor %} + {%- endfor %} {%- endif %} - +# ###### Update settings ###### ########################################### # Using the features in Esky, a salt minion can both run as a frozen app and @@ -729,8 +989,7 @@ pillar_roots: # /proc/sys/net/ipv4/tcp_keepalive_intvl. {{ get_config('tcp_keepalive_intvl', '-1') }} - -###### Windows Software settings ###### +###### Windows Software settings ###### ############################################ # Location of the repository cache file on the master: {{ get_config('win_repo_cachefile', 'salt://win/repo/winrepo.p') }} @@ -738,4 +997,32 @@ pillar_roots: ###### Returner settings ###### ############################################ # Which returner(s) will be used for minion's result: -#return: mysql +{{ get_config('return', '') }} + +###### Miscellaneous settings ###### +############################################ +# Default match type for filtering events tags: startswith, endswith, find, regex, fnmatch +#event_match_type: startswith +{{ get_config('event_match_type', 'startswith') }} + +{% if 'mongo' in cfg_minion -%} +{%- do default_keys.append('mongo') %} +##### mongodb connection settings ##### +########################################## +{%- for name, value in cfg_minion['mongo'].items() %} +mongo.{{ name }}: {{ value }} +{%- endfor %} + +{% if 'alternative.mongo' in cfg_minion -%} +{%- do default_keys.append('alternative.mongo') %} +{%- for name, value in cfg_minion['alternative.mongo'].items() %} +alternative.mongo.{{ name }}: {{ value }} +{%- endfor %} +{% endif %} +{%- endif %} + +{%- for configname in cfg_minion %} +{%- if configname not in reserved_keys and configname not in default_keys %} +{{ configname }}: {{ cfg_minion[configname]|json }} +{%- endif %} +{%- endfor %} diff --git a/salt/files/minion.d/reactor.conf b/salt/files/minion.d/reactor.conf new file mode 100644 index 0000000..dd7fbb5 --- /dev/null +++ b/salt/files/minion.d/reactor.conf @@ -0,0 +1,15 @@ +# +# This file is managed by Salt! Do not edit by hand! +# +{%- set reactors = salt['pillar.get']('salt:reactor') -%} +{%- if reactors %} +reactor: + {%- for reactor in reactors %} + {%- for event_tag, reactor_files in reactor.items() %} + - '{{ event_tag }}': + {%- for reactor_file in reactor_files %} + - {{ reactor_file }} + {%- endfor %} + {%- endfor %} + {% endfor -%} +{%- endif -%} diff --git a/salt/formulas.jinja b/salt/formulas.jinja index 071312c..2a466a2 100644 --- a/salt/formulas.jinja +++ b/salt/formulas.jinja @@ -8,20 +8,17 @@ {% set formulas = salt['pillar.get']('salt_formulas:list', {}) %} {%- macro formulas_git_opt(env, opt) -%} -{%- set value = salt['pillar.get']('salt_formulas:git_opts:{}:{}'.format(env, opt), - salt['pillar.get']('salt_formulas:git_opts:default:{}'.format(opt), +{%- set value = salt['pillar.get']('salt_formulas:git_opts:{0}:{1}'.format(env, opt), + salt['pillar.get']('salt_formulas:git_opts:default:{0}'.format(opt), defaults[opt])) -%} -{%- if value is mapping -%} {{ value|yaml }} -{%- else -%} -{{ value }} -{%- endif -%} {%- endmacro -%} {%- macro formulas_roots(env) -%} {%- set value = [] -%} {%- for dir in formulas.get(env, []) -%} -{%- do value.append('{}/{}'.format(formulas_git_opt(env, 'basedir'), dir)) -%} +{%- set basedir = formulas_git_opt(env, 'basedir')|load_yaml -%} +{%- do value.append('{0}/{1}'.format(basedir, dir)) -%} {%- endfor -%} {{ value|yaml }} {%- endmacro -%} diff --git a/salt/formulas.sls b/salt/formulas.sls index 55c31fe..b433bb5 100644 --- a/salt/formulas.sls +++ b/salt/formulas.sls @@ -4,11 +4,11 @@ {% from "salt/formulas.jinja" import formulas_git_opt with context %} # Loop over all formulas listed in pillar data -{% for env, entries in salt['pillar.get']('salt_formulas:list').iteritems() %} +{% for env, entries in salt['pillar.get']('salt_formulas:list', {}).items() %} {% for entry in entries %} -{% set basedir = formulas_git_opt(env, 'basedir') %} -{% set gitdir = '{}/{}'.format(basedir, entry) %} +{% set basedir = formulas_git_opt(env, 'basedir')|load_yaml %} +{% set gitdir = '{0}/{1}'.format(basedir, entry) %} {% set update = formulas_git_opt(env, 'update')|load_yaml %} # Setup the directory hosting the Git repository @@ -17,7 +17,7 @@ {{ basedir }}: file.directory: {%- for key, value in salt['pillar.get']('salt_formulas:basedir_opts', - {'makedirs': True}).iteritems() %} + {'makedirs': True}).items() %} - {{ key }}: {{ value }} {%- endfor %} {% endif %} @@ -26,11 +26,12 @@ {% if gitdir not in processed_gitdirs %} {% do processed_gitdirs.append(gitdir) %} {% set options = formulas_git_opt(env, 'options')|load_yaml %} +{% set baseurl = formulas_git_opt(env, 'baseurl')|load_yaml %} {{ gitdir }}: git.latest: - - name: {{ formulas_git_opt(env, 'baseurl') }}/{{ entry }}.git + - name: {{ baseurl }}/{{ entry }}.git - target: {{ gitdir }} - {%- for key, value in options.iteritems() %} + {%- for key, value in options.items() %} - {{ key }}: {{ value }} {%- endfor %} - require: diff --git a/salt/gitfs/dulwich.sls b/salt/gitfs/dulwich.sls index b5c2589..e8e1a42 100644 --- a/salt/gitfs/dulwich.sls +++ b/salt/gitfs/dulwich.sls @@ -15,7 +15,9 @@ install-dulwich: - name: dulwich {% else %} -# install from package -# TODO haven't actually found a distro that has a good version to test + +python-dulwich: + pkg.installed: + - name: {{ salt_settings.python_dulwich }} {% endif %} diff --git a/salt/gitfs/gitpython.sls b/salt/gitfs/gitpython.sls index 7fa09ef..f1a48e6 100644 --- a/salt/gitfs/gitpython.sls +++ b/salt/gitfs/gitpython.sls @@ -8,6 +8,7 @@ GitPython: {% else %} python-git: - pkg.installed + pkg.installed: + - name: {{ salt_settings.python_git }} {% endif %} diff --git a/salt/gitfs/keys.sls b/salt/gitfs/keys.sls new file mode 100644 index 0000000..3b002b8 --- /dev/null +++ b/salt/gitfs/keys.sls @@ -0,0 +1,20 @@ +{%- from "salt/map.jinja" import salt_settings with context %} + +{%- set gitfs_keys=salt['pillar.get']('salt:gitfs:keys', {}) %} + +{%- for key, keyvalues in gitfs_keys.items() %} +{%- for type, keydata in keyvalues.items() %} +gitfs-key-{{ key }}-{{ type }}: + file.managed: + - name: {{ salt_settings.config_path }}/pki/gitfs/{{ key }}.{{ type }} + - source: salt://salt/files/gitfs_key.jinja + - template: jinja + - user: root + - group: root + - mode: 600 + - makedirs: True + - defaults: + key: {{ key }} + type: {{ type }} +{%- endfor %} +{%- endfor %} diff --git a/salt/gitfs/pygit2.sls b/salt/gitfs/pygit2.sls index 22e9da1..2439efe 100644 --- a/salt/gitfs/pygit2.sls +++ b/salt/gitfs/pygit2.sls @@ -1,12 +1,29 @@ {% from "salt/map.jinja" import salt_settings with context %} +{% set pygit2_settings = salt_settings.gitfs.pygit2 %} + +{% if pygit2_settings.git.get('require_state', False) %} +include: + - {{ pygit2_settings.git.require_state }} +{% elif pygit2_settings.git.get('install_from_package', 'git') %} +pygit2-git: + pkg.installed: + - name: {{ pygit2_settings.git.install_from_package }} +{% endif %} + +{% if pygit2_settings.install_from_source %} +{% set libgit2_settings = pygit2_settings.libgit2 %} + +{% if libgit2_settings.install_from_source %} +{% set libgit2_src_dir = libgit2_settings.build_parent_dir + 'libgit2-' + libgit2_settings.version %} +{% set libgit2_build_dir = libgit2_src_dir + '/_build' %} -{% if salt_settings.gitfs.pygit2.install_from_source %} # we probably don't have a package or it's not a high enough version # install latest from source/pip pygit-deps: pkg.installed: - pkgs: - build-essential + - pkg-config - python-dev - libssh-dev - libffi-dev @@ -14,32 +31,32 @@ pygit-deps: dl-libgit2-src: archive.extracted: - - name: /usr/src - - source: https://github.com/libgit2/libgit2/archive/v0.22.1.tar.gz - - source_hash: md5=dbf516d18e176bbb131de3efccfee533 + - name: {{ libgit2_settings.build_parent_dir }} + - source: https://github.com/libgit2/libgit2/archive/v{{ libgit2_settings.version }}.tar.gz + - source_hash: md5={{ libgit2_settings.download_hash }} - archive_format: tar - keep: True - - if_missing: /usr/src/libgit2-0.22.1 + - if_missing: /usr/src/libgit2-{{ libgit2_settings.version }} -/usr/src/libgit2-0.22.1/_build: +{{ libgit2_build_dir }}: file.directory configure-libgit2: cmd.run: - name: cmake .. - - cwd: /usr/src/libgit2-0.22.1/_build - - creates: /usr/src/libgit2-0.22.1/_build/Makefile + - cwd: {{ libgit2_build_dir }} + - creates: {{ libgit2_build_dir }}/Makefile build-libgit2: cmd.run: - name: make -j4 - - cwd: /usr/src/libgit2-0.22.1/_build - - creates: /usr/src/libgit2-0.22.1/_build/libgit2.so + - cwd: {{ libgit2_build_dir }} + - creates: {{ libgit2_build_dir }}/libgit2.so install-libgit2: cmd.run: - name: make install - - cwd: /usr/src/libgit2-0.22.1/_build + - cwd: {{ libgit2_build_dir }} - creates: /usr/local/lib/libgit2.so run-ldconfig-after-lib-install: @@ -48,13 +65,18 @@ run-ldconfig-after-lib-install: - onchanges: - cmd: install-libgit2 -install-pygit2: - pip.installed: - - name: pygit2 - {% else %} -# install from package -# TODO haven't actually found a distro that has a good version to test -# debian jessie will have libgit2-21 +{{ salt_settings.libgit2 }}: + pkg.installed + +{% endif %} + +install-pygit2: + pip.installed: + - name: pygit2 == {{ pygit2_settings.version }} + +{% else %} +{{ salt_settings.pygit2 }}: + pkg.installed {% endif %} diff --git a/salt/map.jinja b/salt/map.jinja index 0f989e7..21008f2 100644 --- a/salt/map.jinja +++ b/salt/map.jinja @@ -1,72 +1,190 @@ +# -*- coding: utf-8 -*- +# vim: ft=jinja + +{%- macro deep_merge(a, b) %} +{%- for k,v in b.iteritems() %} +{%- if v is string or v is number %} +{%- do a.update({ k: v }) %} +{%- elif v is not mapping %} +{%- if a[k] is not defined %} +{%- do a.update({ k: v }) %} +{%- elif a[k] is iterable and a[k] is not mapping and a[k] is not string %} +{%- do a.update({ k: v|list + a[k]|list}) %} +{%- else %} +{%- do a.update({ k: v }) %} +{%- endif %} +{%- elif v is mapping %} +{%- if a[k] is not defined %} +{%- do a.update({ k: v }) %} +{%- elif a[k] is not mapping %} +{%- do a.update({ k: v }) %} +{%- else %} +{%- do deep_merge(a[k], v) %} +{%- endif %} +{%- else %} +{%- do a.update({ k: 'ERROR: case not contempled in merging!' }) %} +{%- endif %} +{%- endfor %} +{%- endmacro %} + + +{## Start with defaults from defaults.yaml ##} {% import_yaml "salt/defaults.yaml" as default_settings %} -{% set distro_map = salt['grains.filter_by']({ - 'Debian': {'salt_master': 'salt-master', - 'salt_minion': 'salt-minion', - 'salt_syndic': 'salt-syndic', - 'salt_cloud': 'salt-cloud', - 'salt_api': 'salt-api', - 'salt_ssh': 'salt-ssh'}, - 'Ubuntu': {'salt_master': 'salt-master', - 'salt_minion': 'salt-minion', - 'salt_syndic': 'salt-syndic', - 'salt_cloud': 'salt-cloud', - 'salt_api': 'salt-api', - 'salt_ssh': 'salt-ssh'}, - 'CentOS': {'salt_master': 'salt-master', - 'salt_minion': 'salt-minion', - 'salt_syndic': 'salt-syndic', - 'salt_cloud': 'salt-cloud', - 'salt_api': 'salt-api', - 'salt_ssh': 'salt-ssh'}, - 'Amazon': {'salt_master': 'salt-master', - 'salt_minion': 'salt-minion', - 'salt_syndic': 'salt-syndic', - 'salt_cloud': 'salt-cloud', - 'salt_api': 'salt-api', - 'salt_ssh': 'salt-ssh'}, - 'Fedora': {'salt_master': 'salt-master', - 'salt_minion': 'salt-minion', - 'salt_syndic': 'salt-syndic', - 'salt_cloud': 'salt-cloud', - 'salt_api': 'salt-api', - 'salt_ssh': 'salt-ssh'}, - 'RedHat': {'salt_master': 'salt-master', - 'salt_minion': 'salt-minion', - 'salt_syndic': 'salt-syndic', - 'salt_cloud': 'salt-cloud', - 'salt_api': 'salt-api', - 'salt_ssh': 'salt-ssh'}, - 'Gentoo': {'salt_master': 'app-admin/salt', - 'salt_minion': 'app-admin/salt', - 'salt_syndic': 'app-admin/salt', - 'salt_api': 'app-admin/salt', - 'salt_cloud': 'app-admin/salt'}, - 'Arch': {'salt_master': 'salt-zmq', - 'salt_minion': 'salt-zmq', - 'salt_syndic': 'salt-zmq', - 'salt_cloud': 'salt-zmq', - 'salt_api': 'salt-zmq', - 'salt_ssh': 'salt-zmq'}, - 'Suse': {'salt_master': 'salt-master', - 'salt_minion': 'salt-minion', - 'salt_syndic': 'salt-syndic', - 'salt_api': 'salt-api', - 'salt_cloud': 'salt-cloud', - 'salt_ssh': 'salt-ssh'}, - 'FreeBSD': {'salt_master': 'py27-salt', - 'salt_minion': 'py27-salt', - 'salt_syndic': 'py27-salt', - 'salt_cloud': 'py27-salt', - 'salt_api': 'py27-salt', - 'config_path': '/usr/local/etc/salt', - 'minion_service': 'salt_minion', - 'master_service': 'salt_master', - 'api_service': 'salt_api', - 'syndic_service': 'salt_syndic'}, -}, merge=salt['pillar.get']('salt:lookup')) %} +{## +Setup variable using grains['os_family'] based logic, only add key:values here +that differ from whats in defaults.yaml +##} +{% set osrelease = salt['grains.get']('osrelease') %} +{% set os_family_map = salt['grains.filter_by']({ + 'Debian': { + 'pkgrepo': 'deb http://repo.saltstack.com/apt/' + + salt['grains.get']('os')|lower + '/' + salt['grains.get']('osmajorrelease', osrelease) + '/amd64/latest ' + salt['grains.get']('oscodename') + ' main', + 'key_url': 'https://repo.saltstack.com/apt/' + salt['grains.get']('os')|lower + '/' + salt['grains.get']('osmajorrelease', osrelease) + '/amd64/latest/SALTSTACK-GPG-KEY.pub', + 'libgit2': 'libgit2-22', + 'gitfs': { + 'pygit2': { + 'install_from_source': True, + 'version': '0.22.1', + 'git': { + 'require_state': False, + 'install_from_package': 'git', + }, + 'libgit2': { + 'install_from_source': False, + }, + }, + }, + }, + 'RedHat': { + 'pygit2': salt['grains.filter_by']({ + 'Fedora': 'python2-pygit2', + 'default': 'python-pygit2', + }, grain='os'), + 'python_git': 'GitPython', + 'gitfs': { + 'pygit2': { + 'install_from_source': False, + 'git': { + 'require_state': False, + 'install_from_package': 'git', + }, + }, + }, + 'master': { + 'gitfs_provider': 'pygit2' + }, + }, + 'Suse': {}, + 'Gentoo': { + 'salt_master': 'app-admin/salt', + 'salt_minion': 'app-admin/salt', + 'salt_syndic': 'app-admin/salt', + 'salt_api': 'app-admin/salt', + 'salt_cloud': 'app-admin/salt', + }, + 'Arch': { + 'salt_master': 'salt', + 'salt_minion': 'salt', + 'salt_syndic': 'salt', + 'salt_cloud': 'salt', + 'salt_api': 'salt', + 'salt_ssh': 'salt', + 'pygit2': 'python2-pygit2', + 'libgit2': 'libgit2', + }, + 'Alpine': { + 'salt_master': 'salt-master', + 'salt_minion': 'salt-minion', + 'salt_syndic': 'salt-syndic', + 'salt_cloud': 'salt-cloud', + 'salt_api': 'salt-api', + 'salt_ssh': 'salt-ssh', + 'pygit2': 'py2-pygit2', + 'libgit2': 'libgit2', + }, + 'FreeBSD': { + 'salt_master': 'py27-salt', + 'salt_minion': 'py27-salt', + 'salt_syndic': 'py27-salt', + 'salt_cloud': 'py27-salt', + 'salt_api': 'py27-salt', + 'salt_ssh': 'py27-salt', + 'python_git': 'py27-GitPython', + 'pygit2': 'py27-pygit2', + 'config_path': '/usr/local/etc/salt', + 'minion_service': 'salt_minion', + 'master_service': 'salt_master', + 'api_service': 'salt_api', + 'syndic_service': 'salt_syndic', + }, + 'OpenBSD': { + 'salt_master': 'salt', + 'salt_minion': 'salt', + 'salt_syndic': 'salt', + 'salt_cloud': 'salt', + 'salt_api': 'salt', + 'salt_ssh': 'salt', + 'config_path': '/etc/salt', + 'minion_service': 'salt_minion', + 'master_service': 'salt_master', + 'python_git': 'py-GitPython', + }, + 'Windows': { + 'salt_minion': 'saltstack.minion', + 'config_path': 'C:\salt\conf', + 'minion_service': 'salt-minion', + }, + }, merge=salt['grains.filter_by']({ + 'Ubuntu': { + 'pkgrepo': 'deb http://repo.saltstack.com/apt/' + + salt['grains.get']('os')|lower + '/' + osrelease + '/amd64/latest ' + salt['grains.get']('oscodename') + ' main', + 'key_url': 'https://repo.saltstack.com/apt/' + salt['grains.get']('os')|lower + '/' + osrelease + '/amd64/latest/SALTSTACK-GPG-KEY.pub', + 'pygit2': 'python-pygit2', + 'gitfs': { + 'pygit2': { + 'install_from_source': False, + 'git': { + 'require_state': False, + 'install_from_package': None, + }, + }, + }, + }, + 'Raspbian': { + 'pkgrepo': 'deb http://repo.saltstack.com/apt/' + + salt['grains.get']('os_family')|lower + '/' + salt['grains.get']('osmajorrelease', osrelease) + '/armhf/latest ' + salt['grains.get']('oscodename') + ' main', + 'key_url': 'https://repo.saltstack.com/apt/' + salt['grains.get']('os_family')|lower + '/' + salt['grains.get']('osmajorrelease', osrelease) + '/armhf/latest/SALTSTACK-GPG-KEY.pub', + }, + 'SmartOS': { + 'salt_master': 'salt', + 'salt_minion': 'salt', + 'salt_syndic': 'salt', + 'salt_cloud': 'salt', + 'salt_api': 'salt', + 'salt_ssh': 'salt', + 'minion_service': 'salt:minion', + 'master_service': 'salt:master', + 'python_dulwich': 'py27-dulwich', + 'gitfs': { + 'dulwich': { + 'install_from_source': False, + } + }, + 'config_path': '/opt/local/etc/salt', + 'master': { + 'gitfs_provider': 'dulwich' + }, + } + }, grain='os', merge=salt['pillar.get']('salt:lookup'))) +%} -{% do default_settings.salt.update(distro_map) %} +{## Merge the flavor_map to the default settings ##} +{% do deep_merge(default_settings.salt,os_family_map) %} -{% set salt_settings = salt['pillar.get']('salt', default=default_settings.salt, - merge=True) %} +{## Merge in salt:lookup pillar ##} +{% set salt_settings = salt['pillar.get']( + 'salt', + default=default_settings.salt, + merge=True) +%} diff --git a/salt/master.sls b/salt/master.sls index 234ffca..e7918e6 100644 --- a/salt/master.sls +++ b/salt/master.sls @@ -8,7 +8,7 @@ salt-master: file.recurse: - name: {{ salt_settings.config_path }}/master.d - template: jinja - - source: salt://salt/files/master.d + - source: salt://{{ slspath }}/files/master.d - clean: {{ salt_settings.clean_config_d_dir }} - exclude_pat: _* service.running: @@ -21,7 +21,13 @@ salt-master: - file: salt-master - file: remove-old-master-conf-file +{% if salt_settings.master_remove_config %} +remove-default-master-conf-file: + file.absent: + - name: {{ salt_settings.config_path }}/master +{% endif %} + # clean up old _defaults.conf file if they have it around remove-old-master-conf-file: file.absent: - - name: /etc/salt/master.d/_defaults.conf + - name: {{ salt_settings.config_path }}/master.d/_defaults.conf diff --git a/salt/minion.sls b/salt/minion.sls index 7f0cd52..9d141b7 100644 --- a/salt/minion.sls +++ b/salt/minion.sls @@ -8,7 +8,7 @@ salt-minion: file.recurse: - name: {{ salt_settings.config_path }}/minion.d - template: jinja - - source: salt://salt/files/minion.d + - source: salt://{{ slspath }}/files/minion.d - clean: {{ salt_settings.clean_config_d_dir }} - exclude_pat: _* - context: @@ -23,7 +23,13 @@ salt-minion: - file: salt-minion - file: remove-old-minion-conf-file +{% if salt_settings.minion_remove_config %} +remove-default-minion-conf-file: + file.absent: + - name: {{ salt_settings.config_path }}/minion +{% endif %} + # clean up old _defaults.conf file if they have it around remove-old-minion-conf-file: file.absent: - - name: /etc/salt/minion.d/_defaults.conf + - name: {{ salt_settings.config_path }}/minion.d/_defaults.conf diff --git a/salt/pkgrepo/absent.sls b/salt/pkgrepo/absent.sls index d79b15f..b66c8e3 100644 --- a/salt/pkgrepo/absent.sls +++ b/salt/pkgrepo/absent.sls @@ -1,2 +1,2 @@ include: - - .{{ grains['os']|lower }}.absent + - .{{ grains['os_family']|lower }}.absent diff --git a/salt/pkgrepo/debian/absent.sls b/salt/pkgrepo/debian/absent.sls index 2ace193..a3eb838 100644 --- a/salt/pkgrepo/debian/absent.sls +++ b/salt/pkgrepo/debian/absent.sls @@ -1,4 +1,8 @@ +{% from "salt/map.jinja" import salt_settings with context %} + drop-saltstack-pkgrepo: + pkgrepo.absent: + - name: {{ salt_settings.pkgrepo }} file.absent: - name: /etc/apt/sources.list.d/saltstack.list diff --git a/salt/pkgrepo/debian/init.sls b/salt/pkgrepo/debian/init.sls index ffe7165..350713f 100644 --- a/salt/pkgrepo/debian/init.sls +++ b/salt/pkgrepo/debian/init.sls @@ -1,21 +1,12 @@ -saltstack-apt-key: - file.managed: - - name: /etc/apt/trusted.gpg.d/saltstack.gpg - - source: salt://salt/pkgrepo/debian/saltstack.gpg - - user: root - - group: root - - mode: 644 +{% from "salt/map.jinja" import salt_settings with context %} saltstack-pkgrepo: - file.managed: - - name: /etc/apt/sources.list.d/saltstack.list - - source: salt://salt/pkgrepo/debian/sources.list - - user: root - - group: root - - mode: 644 - - template: jinja - - require: - - file: saltstack-apt-key + pkgrepo.managed: + - humanname: SaltStack Debian Repo + - name: {{ salt_settings.pkgrepo }} + - file: /etc/apt/sources.list.d/saltstack.list + - key_url: {{ salt_settings.key_url }} + - clean_file: True # Order: 1 because we can't put a require_in on "pkg: salt-{master,minion}" # because we don't know if they are used. - order: 1 diff --git a/salt/pkgrepo/debian/saltstack.gpg b/salt/pkgrepo/debian/saltstack.gpg deleted file mode 100644 index 78da01e..0000000 Binary files a/salt/pkgrepo/debian/saltstack.gpg and /dev/null differ diff --git a/salt/pkgrepo/debian/sources.list b/salt/pkgrepo/debian/sources.list deleted file mode 100644 index f99e426..0000000 --- a/salt/pkgrepo/debian/sources.list +++ /dev/null @@ -1,2 +0,0 @@ -# saltstack -deb http://debian.saltstack.com/debian {{ grains['oscodename'] }}-saltstack main diff --git a/salt/pkgrepo/init.sls b/salt/pkgrepo/init.sls index 67e3596..b2c794c 100644 --- a/salt/pkgrepo/init.sls +++ b/salt/pkgrepo/init.sls @@ -1,4 +1,2 @@ -{% if grains['os_family'] == 'Debian' %} include: - - .{{ grains['os']|lower }} -{% endif %} + - .{{ grains['os_family']|lower }} diff --git a/salt/pkgrepo/ubuntu/absent.sls b/salt/pkgrepo/redhat/absent.sls similarity index 58% rename from salt/pkgrepo/ubuntu/absent.sls rename to salt/pkgrepo/redhat/absent.sls index 27b5fd6..9945714 100644 --- a/salt/pkgrepo/ubuntu/absent.sls +++ b/salt/pkgrepo/redhat/absent.sls @@ -1,3 +1,3 @@ drop-saltstack-pkgrepo: pkgrepo.absent: - - ppa: saltstack/salt + - name: saltstack-pkgrepo diff --git a/salt/pkgrepo/redhat/init.sls b/salt/pkgrepo/redhat/init.sls new file mode 100644 index 0000000..a99827a --- /dev/null +++ b/salt/pkgrepo/redhat/init.sls @@ -0,0 +1,9 @@ +{% from "salt/map.jinja" import salt_settings with context %} + +saltstack-pkgrepo: + pkgrepo.managed: + - humanname: SaltStack repo for RHEL/CentOS $releasever + - baseurl: https://repo.saltstack.com/yum/redhat/$releasever/$basearch/latest + - enabled: 1 + - gpgcheck: 1 + - gpgkey: https://repo.saltstack.com/yum/redhat/$releasever/$basearch/latest/SALTSTACK-GPG-KEY.pub diff --git a/salt/pkgrepo/ubuntu/init.sls b/salt/pkgrepo/ubuntu/init.sls deleted file mode 100644 index bd3986a..0000000 --- a/salt/pkgrepo/ubuntu/init.sls +++ /dev/null @@ -1,3 +0,0 @@ -saltstack-pkgrepo: - pkgrepo.managed: - - ppa: saltstack/salt diff --git a/salt/ssh.sls b/salt/ssh.sls index ad2b5be..fad6463 100644 --- a/salt/ssh.sls +++ b/salt/ssh.sls @@ -1,17 +1,17 @@ {% from "salt/map.jinja" import salt_settings with context %} {% if salt_settings.install_packages %} -ensure salt-ssh is installed: +ensure-salt-ssh-is-installed: pkg.installed: - name: {{ salt_settings.salt_ssh }} {% endif %} -ensure roster config: +ensure-roster-config: file.managed: - name: {{ salt_settings.config_path }}/roster - - source: salt://salt/files/roster.jinja + - source: salt://{{ slspath }}/files/roster.jinja - template: jinja - - require: {% if salt_settings.install_packages %} - - pkg: ensure salt-ssh is installed + - require: + - pkg: ensure-salt-ssh-is-installed {% endif %} diff --git a/salt/standalone.sls b/salt/standalone.sls index 1b3c2a1..e76e2c3 100644 --- a/salt/standalone.sls +++ b/salt/standalone.sls @@ -8,13 +8,18 @@ salt-minion: file.recurse: - name: {{ salt_settings.config_path }}/minion.d - template: jinja - - source: salt://salt/files/minion.d + - source: salt://{{ slspath }}/files/minion.d - clean: {{ salt_settings.clean_config_d_dir }} - exclude_pat: _* - context: standalone: True +{%- if salt_settings.minion.master_type is defined and salt_settings.minion.master_type == 'disable' %} + service.running: + - enable: True +{%- else %} service.dead: - enable: False +{%- endif %} - name: {{ salt_settings.minion_service }} - require: {% if salt_settings.install_packages %} @@ -25,4 +30,4 @@ salt-minion: # clean up old _defaults.conf file if they have it around remove-old-standalone-conf-file: file.absent: - - name: /etc/salt/minion.d/_defaults.conf + - name: {{ salt_settings.config_path }}/minion.d/_defaults.conf diff --git a/salt/syndic.sls b/salt/syndic.sls index 9079552..e372b2e 100644 --- a/salt/syndic.sls +++ b/salt/syndic.sls @@ -8,12 +8,12 @@ salt-syndic: pkg.installed: - name: {{ salt_settings.salt_syndic }} {% endif %} - service: - - running + service.running: + - name: {{ salt_settings.syndic_service }} - require: - - service: {{ salt_settings.syndic_service }} + - service: salt-master - watch: {% if salt_settings.install_packages %} - pkg: salt-master {% endif %} - - file: {{ salt_settings.config_path }}/master + - file: salt-master