Merge "Adding environment variables for salt minion"
diff --git a/.kitchen.yml b/.kitchen.yml
index ebfa3b9..888f83f 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -8,7 +8,7 @@
name: salt_solo
salt_install: bootstrap
salt_bootstrap_url: https://bootstrap.saltstack.com
- salt_version: latest
+ salt_version: <%=ENV['SALT_VERSION'] || 'latest'%>
salt_minion_id: salt.ci.local
require_chef: false
log_level: error
@@ -150,6 +150,7 @@
control_cloud_digitalocean.sls: tests/pillar/control_cloud_digitalocean.sls
control_cloud_openstack.sls: tests/pillar/control_cloud_openstack.sls
control_virt.sls: tests/pillar/control_virt.sls
+ control_virt_custom.sls: tests/pillar/control_virt_custom.sls
- name: minion_multi_master_failover
provisioner:
diff --git a/.travis.yml b/.travis.yml
index eed1da2..cdba2b5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,16 +17,29 @@
- bundle install
env:
- - PLATFORM=trevorj/salty-whales:trusty SUITE=minion-default
- - PLATFORM=trevorj/salty-whales:xenial SUITE=minion-default
- - PLATFORM=trevorj/salty-whales:trusty SUITE=master-default
- - PLATFORM=trevorj/salty-whales:xenial SUITE=master-default
- - PLATFORM=trevorj/salty-whales:trusty SUITE=minion-default
- - PLATFORM=trevorj/salty-whales:xenial SUITE=minion-default
+
+ - PLATFORM=trevorj/salty-whales:trusty-2017.7 SUITE=control-default
+ - PLATFORM=trevorj/salty-whales:trusty-2017.7 SUITE=master-default
+ - PLATFORM=trevorj/salty-whales:trusty-2017.7 SUITE=minion-default
+ - PLATFORM=trevorj/salty-whales:trusty-2017.7 SUITE=minion-multi-master-failover
+ - PLATFORM=trevorj/salty-whales:xenial-2017.7 SUITE=control-default
+ - PLATFORM=trevorj/salty-whales:xenial-2017.7 SUITE=master-default
+ - PLATFORM=trevorj/salty-whales:xenial-2017.7 SUITE=minion-default
+ - PLATFORM=trevorj/salty-whales:xenial-2017.7 SUITE=minion-multi-master-failover
+# TODO, once 18.04 LTS Bionic Beaver is released, rename trusty to bionic
+ - PLATFORM=trevorj/salty-whales:bionic-2017.7 SUITE=master-default
+ - PLATFORM=trevorj/salty-whales:bionic-2017.7 SUITE=minion-default
- PLATFORM=trevorj/salty-whales:trusty SUITE=control-default
- - PLATFORM=trevorj/salty-whales:xenial SUITE=control-default
+ - PLATFORM=trevorj/salty-whales:trusty SUITE=master-default
+ - PLATFORM=trevorj/salty-whales:trusty SUITE=minion-default
- PLATFORM=trevorj/salty-whales:trusty SUITE=minion-multi-master-failover
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=control-default
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=master-default
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=minion-default
- PLATFORM=trevorj/salty-whales:xenial SUITE=minion-multi-master-failover
+# TODO, once 18.04 LTS Bionic Beaver is released, rename trusty to bionic
+ - PLATFORM=trevorj/salty-whales:bionic SUITE=master-default
+ - PLATFORM=trevorj/salty-whales:bionic SUITE=minion-default
before_script:
- set -o pipefail
diff --git a/README.rst b/README.rst
index d8d8674..60c5c7b 100644
--- a/README.rst
+++ b/README.rst
@@ -28,6 +28,21 @@
.. literalinclude:: tests/pillar/master_single_reclass.sls
:language: yaml
+Salt master with Architect ENC metadata backend
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ enabled: true
+ pillar:
+ engine: architect
+ project: project-name
+ host: architect-api
+ port: 8181
+ username: salt
+ password: password
+
Salt master with multiple ext_pillars
.. literalinclude:: tests/pillar/master_single_extpillars.sls
@@ -150,7 +165,6 @@
host: 127.0.0.1
port: 9999
-
Salt engine definition for saltgraph metadata collector
.. code-block:: yaml
@@ -166,6 +180,21 @@
password: salt
database: salt
+Salt engine definition for Architect service
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ engine:
+ architect:
+ engine: architect
+ project: project-name
+ host: architect-api
+ port: 8181
+ username: salt
+ password: password
+
Salt engine definition for sending events from docker events
.. code-block:: yaml
@@ -476,6 +505,21 @@
:language: yaml
+Common salt config options
+--------------------------
+
+Pass pillar render error to minion log.
+
+.. Note: When set to `False` this option is great for debuging. However it is not recomended for
+ any production environment as it may contain templating data as passwords, etc...,
+ that minion should not have.
+
+.. code-block:: yaml
+
+ salt:
+ master:
+ pillar_safe_render_error: False
+
Salt minion
-----------
@@ -568,6 +612,11 @@
.. literalinclude:: tests/pillar/control_virt.sls
:language: yaml
+salt virt with custom destination for image file
+
+.. literalinclude:: tests/pillar/control_virt_custom.sls
+ :language: yaml
+
Usage
=====
diff --git a/_engines/architect.py b/_engines/architect.py
new file mode 100644
index 0000000..4096a73
--- /dev/null
+++ b/_engines/architect.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+"""
+Salt engine for intercepting state jobs and forwarding to the Architect
+service.
+"""
+
+# Import python libs
+from __future__ import absolute_import
+import json
+import logging
+
+# Import salt libs
+import salt.utils.event
+import salt.utils.http
+
+log = logging.getLogger(__name__)
+
+
+def start(project='default',
+ host='127.0.0.1',
+ port=8181,
+ username=None,
+ password=None):
+ '''
+ Listen to state jobs events and forward Salt states
+ '''
+ url = "{}://{}:{}/salt/{}/event/{}".format('http',
+ host,
+ port,
+ 'v1',
+ project)
+ target_functions = ['state.sls', 'state.apply', 'state.highstate']
+
+ if __opts__['__role'] == 'master':
+ event_bus = salt.utils.event.get_master_event(__opts__,
+ __opts__['sock_dir'],
+ listen=True)
+ else:
+ event_bus = salt.utils.event.get_event(
+ 'minion',
+ transport=__opts__['transport'],
+ opts=__opts__,
+ sock_dir=__opts__['sock_dir'],
+ listen=True)
+
+ log.info('Salt Architect engine initialised')
+
+ while True:
+ event = event_bus.get_event()
+ if event and event.get('fun', None) in target_functions:
+ is_test_run = 'test=true' in [arg.lower() for arg in event.get('fun_args', [])]
+ if not is_test_run:
+ data = salt.utils.http.query(url=url,
+ method='POST',
+ decode=False,
+ data=json.dumps(event))
+ if 'OK' in data.get('body', ''):
+ log.info("Architect Engine request to '{}'"
+ " was successful".format(url))
+ else:
+ log.warning("Problem with Architect Engine"
+ " request to '{}' ({})".format(url, data))
diff --git a/_modules/modelschema.py b/_modules/modelschema.py
index cb45153..5e319ae 100644
--- a/_modules/modelschema.py
+++ b/_modules/modelschema.py
@@ -132,7 +132,7 @@
data = 'Schema is valid'
except SchemaError as exc:
LOG.error("SchemaError:{}".format(exc))
- data = repr(exc)
+ raise Exception("SchemaError")
return {'{}-{}'.format(service, role): data}
@@ -154,10 +154,15 @@
data = 'Model is valid'
except SchemaError as exc:
LOG.error("SchemaError:{}".format(exc))
- data = repr(exc)
+ raise Exception("SchemaError")
except ValidationError as exc:
LOG.error("ValidationError:{}\nInstance:{}\n"
- "SchemaPath:{}".format(exc.message, exc.instance,
+ "Schema title:{}\n"
+ "SchemaPath:{}".format(exc.message,
+ exc.instance,
+ exc.schema.get(
+ "title",
+ "Schema title not set!"),
exc.schema_path))
raise Exception("ValidationError")
return {'{}-{}'.format(service, role): data}
@@ -176,10 +181,15 @@
data = 'Model is valid'
except SchemaError as exc:
LOG.error("SchemaError:{}".format(exc))
- data = str(exc)
+ raise Exception("SchemaError")
except ValidationError as exc:
LOG.error("ValidationError:{}\nInstance:{}\n"
- "SchemaPath:{}".format(exc.message, exc.instance,
+ "Schema title:{}\n"
+ "SchemaPath:{}".format(exc.message,
+ exc.instance,
+ exc.schema.get(
+ "title",
+ "Schema title not set!"),
exc.schema_path))
raise Exception("ValidationError")
return data
@@ -214,9 +224,10 @@
except Exception as exc:
LOG.error('{}: {}'.format(pillar, repr(exc)))
if service not in raw_data.keys():
- raise Exception(
- "Could not find applicable data "
- "for:{}\n at:{}".format(service, _get_base_dir()))
+ LOG.error("Could not find applicable data "
+ "for:{}\n at:{}".format(service, _get_base_dir()))
+ raise Exception("DataError")
+
data = raw_data[service]
output = {}
for role_name, role in data.items():
diff --git a/_modules/virtng.py b/_modules/virtng.py
index a79e5dd..304a6bb 100644
--- a/_modules/virtng.py
+++ b/_modules/virtng.py
@@ -313,7 +313,7 @@
Detect information for the image at path
'''
ret = {}
- out = __salt__['cmd.run']('qemu-img info {0}'.format(path))
+ out = __salt__['cmd.shell']('qemu-img info {0}'.format(path))
match_map = {'size': r'virtual size: \w+ \((\d+) byte[s]?\)',
'format': r'file format: (\w+)'}
@@ -332,7 +332,7 @@
'''
Detect what driver needs to be used for the given image
'''
- out = __salt__['cmd.run']('qemu-img info {0}'.format(vda))
+ out = __salt__['cmd.shell']('qemu-img info {0}'.format(vda))
if 'file format: qcow2' in out:
return 'qcow2'
else:
@@ -354,7 +354,10 @@
elif hypervisor in ['kvm', 'qemu']:
ret['disktype'] = 'qcow2'
ret['filename'] = '{0}{1}'.format(name, '.qcow2')
- ret['pool'] = __salt__['config.option']('virt.images')
+ if 'img_dest' in kwargs:
+ ret['pool'] = kwargs['img_dest']
+ else:
+ ret['pool'] = __salt__['config.option']('virt.images')
return ret
@@ -408,10 +411,11 @@
'pool': '[{0}] '.format(kwargs.get('pool', '0'))
}
elif hypervisor in ['qemu', 'kvm']:
- overlay = {'format': 'qcow2',
- 'model': 'virtio',
- 'pool': __salt__['config.option']('virt.images')
- }
+ if 'img_dest' in kwargs:
+ pool = kwargs['img_dest']
+ else:
+ pool = __salt__['config.option']('virt.images')
+ overlay = {'format': 'qcow2', 'model': 'virtio', 'pool': pool}
else:
overlay = {}
@@ -589,7 +593,8 @@
xml = _gen_vol_xml(name,
disk_name,
args['size'],
- hypervisor)
+ hypervisor,
+ **kwargs)
define_vol_xml_str(xml)
elif hypervisor in ['qemu', 'kvm']:
@@ -599,7 +604,10 @@
# disk size TCP cloud
disk_size = args['size']
- img_dir = __salt__['config.option']('virt.images')
+ if 'img_dest' in kwargs:
+ img_dir = kwargs['img_dest']
+ else:
+ img_dir = __salt__['config.option']('virt.images')
img_dest = os.path.join(
img_dir,
name,
@@ -1591,7 +1599,7 @@
except IOError:
# No /proc/modules? Are we on Windows? Or Solaris?
return False
- return 'libvirtd' in __salt__['cmd.run'](__grains__['ps'])
+ return 'libvirtd' in __salt__['cmd.shell'](__grains__['ps'])
def is_xen_hyper():
@@ -1616,7 +1624,7 @@
except IOError:
# No /proc/modules? Are we on Windows? Or Solaris?
return False
- return 'libvirtd' in __salt__['cmd.run'](__grains__['ps'])
+ return 'libvirtd' in __salt__['cmd.shell'](__grains__['ps'])
def is_hyper():
diff --git a/_states/httpng.py b/_states/httpng.py
new file mode 100644
index 0000000..a539ec0
--- /dev/null
+++ b/_states/httpng.py
@@ -0,0 +1,172 @@
+# -*- coding: utf-8 -*-
+'''
+HTTP monitoring states
+
+Perform an HTTP query and statefully return the result
+
+TODO: This is a copy of upstream state file: https://github.com/saltstack/salt/blob/2017.7.3/salt/states/http.py.
+It have to be removed when MCP Salt will be upgreaded up to 2017 or higher.
+
+.. versionadded:: 2015.5.0
+'''
+
+# Import python libs
+from __future__ import absolute_import
+import re
+import logging
+import time
+
+__monitor__ = [
+ 'query',
+ ]
+
+log = logging.getLogger(__name__)
+
+
+def query(name, match=None, match_type='string', status=None, wait_for=None, **kwargs):
+ '''
+ Perform an HTTP query and statefully return the result
+
+ .. versionadded:: 2015.5.0
+
+ name
+ The name of the query.
+
+ match
+ Specifies a pattern to look for in the return text. By default, this will
+ perform a string comparison of looking for the value of match in the return
+ text.
+
+ match_type
+ Specifies the type of pattern matching to use. Default is ``string``, but
+ can also be set to ``pcre`` to use regular expression matching if a more
+ complex pattern matching is required.
+
+ .. note::
+
+ Despite the name of ``match_type`` for this argument, this setting
+ actually uses Python's ``re.search()`` function rather than Python's
+ ``re.match()`` function.
+
+ status
+ The status code for a URL for which to be checked. Can be used instead of
+ or in addition to the ``match`` setting.
+
+ If both ``match`` and ``status`` options are set, both settings will be checked.
+ However, note that if only one option is ``True`` and the other is ``False``,
+ then ``False`` will be returned. If this case is reached, the comments in the
+ return data will contain troubleshooting information.
+
+ For more information about the ``http.query`` state, refer to the
+ :ref:`HTTP Tutorial <tutorial-http>`.
+
+ .. code-block:: yaml
+
+ query_example:
+ http.query:
+ - name: 'http://example.com/'
+ - status: 200
+
+ '''
+ # Monitoring state, but changes may be made over HTTP
+ ret = {'name': name,
+ 'result': None,
+ 'comment': '',
+ 'changes': {},
+ 'data': {}} # Data field for monitoring state
+
+ if match is None and status is None:
+ ret['result'] = False
+ ret['comment'] += (
+ ' Either match text (match) or a status code (status) is required.'
+ )
+ return ret
+
+ if 'decode' not in kwargs:
+ kwargs['decode'] = False
+ kwargs['text'] = True
+ kwargs['status'] = True
+ if __opts__['test']:
+ kwargs['test'] = True
+
+ if wait_for:
+ data = __salt__['http.wait_for_successful_query'](name, wait_for=wait_for, **kwargs)
+ else:
+ data = __salt__['http.query'](name, **kwargs)
+
+ if match is not None:
+ if match_type == 'string':
+ if match in data.get('text', ''):
+ ret['result'] = True
+ ret['comment'] += ' Match text "{0}" was found.'.format(match)
+ else:
+ ret['result'] = False
+ ret['comment'] += ' Match text "{0}" was not found.'.format(match)
+ elif match_type == 'pcre':
+ if re.search(match, data.get('text', '')):
+ ret['result'] = True
+ ret['comment'] += ' Match pattern "{0}" was found.'.format(match)
+ else:
+ ret['result'] = False
+ ret['comment'] += ' Match pattern "{0}" was not found.'.format(match)
+
+ if status is not None:
+ if data.get('status', '') == status:
+ ret['comment'] += 'Status {0} was found, as specified.'.format(status)
+ if ret['result'] is None:
+ ret['result'] = True
+ else:
+ ret['comment'] += 'Status {0} was not found, as specified.'.format(status)
+ ret['result'] = False
+
+ if __opts__['test'] is True:
+ ret['result'] = None
+ ret['comment'] += ' (TEST MODE'
+ if 'test_url' in kwargs:
+ ret['comment'] += ', TEST URL WAS: {0}'.format(kwargs['test_url'])
+ ret['comment'] += ')'
+
+ ret['data'] = data
+ return ret
+
+
+def wait_for_successful_query(name, wait_for=300, **kwargs):
+ '''
+ Like query but, repeat and wait until match/match_type or status is fulfilled. State returns result from last
+ query state in case of success or if no successful query was made within wait_for timeout.
+
+ name
+ The name of the query.
+
+ wait_for
+ Total time to wait for requests that succeed.
+
+ request_interval
+ Optional interval to delay requests by N seconds to reduce the number of requests sent.
+
+ .. note::
+
+ All other arguements are passed to the http.query state.
+ '''
+ starttime = time.time()
+
+ while True:
+ caught_exception = None
+ ret = None
+ try:
+ ret = query(name, **kwargs)
+ if ret['result']:
+ return ret
+ except Exception as exc:
+ caught_exception = exc
+
+ if time.time() > starttime + wait_for:
+ if not ret and caught_exception:
+ # workaround pylint bug https://www.logilab.org/ticket/3207
+ raise caught_exception # pylint: disable=E0702
+ return ret
+ else:
+ # Space requests out by delaying for an interval
+ if 'request_interval' in kwargs:
+ log.debug("delaying query for {0} seconds.".format(kwargs['request_interval']))
+ time.sleep(kwargs['request_interval'])
diff --git a/debian/control b/debian/control
index 8c56def..9f78368 100644
--- a/debian/control
+++ b/debian/control
@@ -11,7 +11,7 @@
Package: salt-formula-salt
Architecture: all
-Depends: ${misc:Depends}, salt-master, reclass,
+Depends: ${misc:Depends},
salt-formula-git, salt-formula-reclass
Description: Salt salt formula
Install and configure Salt masters and minions.
diff --git a/metadata/service/master/syndic.yml b/metadata/service/master/syndic.yml
new file mode 100644
index 0000000..470cbe0
--- /dev/null
+++ b/metadata/service/master/syndic.yml
@@ -0,0 +1,4 @@
+parameters:
+ salt:
+ master:
+ order_masters: true
diff --git a/metadata/service/syndic/cluster.yml b/metadata/service/syndic/cluster.yml
new file mode 100644
index 0000000..278b7ce
--- /dev/null
+++ b/metadata/service/syndic/cluster.yml
@@ -0,0 +1,7 @@
+parameters:
+ salt:
+ syndic:
+ enabled: true
+ masters:
+ - host: ${_param:salt_syndic_master_address_01}
+ - host: ${_param:salt_syndic_master_address_02}
diff --git a/metadata/service/syndic/single.yml b/metadata/service/syndic/single.yml
new file mode 100644
index 0000000..088cbdf
--- /dev/null
+++ b/metadata/service/syndic/single.yml
@@ -0,0 +1,6 @@
+parameters:
+ salt:
+ syndic:
+ enabled: true
+ master:
+ host: ${_param:salt_syndic_master_address}
diff --git a/salt/control/virt.sls b/salt/control/virt.sls
index b30f7af..84d9c12 100644
--- a/salt/control/virt.sls
+++ b/salt/control/virt.sls
@@ -30,6 +30,7 @@
{%- set size = control.size.get(node.size) %}
+
salt_control_virt_{{ cluster_name }}_{{ node_name }}:
module.run:
- name: virtng.init
@@ -44,6 +45,9 @@
seed: True
serial_type: pty
console: True
+ {%- if node.img_dest is defined %}
+ img_dest: {{ node.img_dest }}
+ {%- endif %}
- unless: virsh list --all --name| grep -E "^{{ node_name }}.{{ cluster.domain }}$"
#salt_control_seed_{{ cluster_name }}_{{ node_name }}:
@@ -61,9 +65,9 @@
- vm_: {{ node_name }}.{{ cluster.domain }}
- state: true
- unless: virsh list --autostart --name| grep -E "^{{ node_name }}.{{ cluster.domain }}$"
-
+
{%- endif %}
-
+
{%- endif %}
{%- endfor %}
diff --git a/salt/files/architect.yml b/salt/files/architect.yml
new file mode 100644
index 0000000..dcba23f
--- /dev/null
+++ b/salt/files/architect.yml
@@ -0,0 +1,8 @@
+{% from "salt/map.jinja" import master with context %}
+project: {{ master.pillar.project }}
+host: {{ master.pillar.host }}
+port: {{ master.pillar.port }}
+{%- if master.pillar.username is defined %}
+username: {{ master.pillar.username }}
+password: {{ master.pillar.password }}
+{%- endif %}
diff --git a/salt/files/master.conf b/salt/files/master.conf
index d8952e9..9f9b00a 100644
--- a/salt/files/master.conf
+++ b/salt/files/master.conf
@@ -40,6 +40,8 @@
pillar_opts: False
+pillar_safe_render_error: {{ master.pillar_safe_render_error }}
+
{%- if master.accept_policy == 'open_mode' %}
open_mode: True
{%- endif %}
@@ -58,6 +60,14 @@
- {{ master.pillar.get('salt', {}).get('path', '/srv/salt/pillar') }}
{%- endif %}
+{%- if master.pillar.engine == 'architect' %}
+ext_pillar:
+ - cmd_yaml: 'architect-salt-pillar %s'
+
+master_tops:
+ ext_nodes: architect-salt-top
+{%- endif %}
+
{%- if master.pillar.engine == 'reclass' or (master.pillar.engine == 'composite' and master.pillar.reclass is defined) %}
reclass: &reclass
@@ -177,6 +187,10 @@
{%- endif %}
{%- endif %}
+file_recv: {{ master.get('file_recv', False) }}
+
+id: {{ system.name }}.{{ system.domain }}
+
{#-
vim: syntax=jinja
-#}
diff --git a/salt/files/orchestrate.sls b/salt/files/orchestrate.sls
index dde20cb..378d570 100644
--- a/salt/files/orchestrate.sls
+++ b/salt/files/orchestrate.sls
@@ -30,7 +30,7 @@
{%- if salt['file.directory_exists']('/srv/salt/env/'+environment_name+'/'+formula.0+'/orchestrate') and formula|length > 1 and salt['file.file_exists']('/srv/salt/env/'+environment_name+'/'+formula.0+'/orchestrate/'+formula.1+'.sls') %}
-{{ salt['cmd.run']('cat /srv/salt/env/'+environment_name+'/'+formula.0+'/orchestrate/'+formula.1+'.sls') }}
+{{ salt['cmd.shell']('cat /srv/salt/env/'+environment_name+'/'+formula.0+'/orchestrate/'+formula.1+'.sls') }}
{%- else %}
{%- if args[ state.0 ] is defined %}
diff --git a/salt/map.jinja b/salt/map.jinja
index 213e95f..68a7cf2 100644
--- a/salt/map.jinja
+++ b/salt/map.jinja
@@ -19,6 +19,7 @@
base_environment: dev
dir:
files: /srv/salt/env
+ pillar_safe_render_error: true
pillar:
engine: salt
max_event_size: 100000000
diff --git a/salt/master/pillar.sls b/salt/master/pillar.sls
index 806511d..709cc8c 100644
--- a/salt/master/pillar.sls
+++ b/salt/master/pillar.sls
@@ -31,6 +31,25 @@
{%- endif %}
+{%- elif master.pillar.engine == 'architect' %}
+
+salt_pillar_architect_package:
+ pip.installed:
+ - name: architect-client
+
+salt_pillar_architect_package_config_dir:
+ file.directory:
+ - name: /etc/architect
+
+salt_pillar_architect_package_config_file:
+ file.managed:
+ - name: /etc/architect/client.yml
+ - source: salt://salt/files/architect.yml
+ - user: root
+ - template: jinja
+ - require:
+ - file: salt_pillar_architect_package_config_dir
+
{%- elif master.pillar.engine == 'reclass' %}
include:
diff --git a/salt/meta/sphinx.yml b/salt/meta/sphinx.yml
index 41df43c..2ae6452 100644
--- a/salt/meta/sphinx.yml
+++ b/salt/meta/sphinx.yml
@@ -8,7 +8,7 @@
name: minion
param:
version:
- value: {{ salt['cmd.run']('salt-minion --version')|replace('salt-minion ', '') }}
+ value: {{ salt['cmd.shell']('salt-minion --version')|replace('salt-minion ', '') }}
{%- endif %}
{%- if pillar.salt.master is defined %}
{%- from "salt/map.jinja" import master with context %}
@@ -16,5 +16,5 @@
name: master
param:
version:
- value: {{ salt['cmd.run']('salt --version')|replace('salt ', '') }}
+ value: {{ salt['cmd.shell']('salt --version')|replace('salt ', '') }}
{%- endif %}
diff --git a/salt/minion/cert.sls b/salt/minion/cert.sls
index 09ef9d1..720a695 100644
--- a/salt/minion/cert.sls
+++ b/salt/minion/cert.sls
@@ -69,6 +69,7 @@
{% if cert.country is defined %}- C: {{ cert.country }}{%- endif %}
{% if cert.locality is defined %}- L: {{ cert.locality }}{%- endif %}
{% if cert.organization is defined %}- O: {{ cert.organization }}{%- endif %}
+ {% if cert.organization_name is defined %}- organizationName: {{ cert.organization_name }}{%- endif %}
{% if cert.signing_private_key is defined and cert.signing_cert is defined %}
- signing_private_key: "{{ cert.signing_private_key }}"
- signing_cert: "{{ cert.signing_cert }}"
diff --git a/salt/minion/service.sls b/salt/minion/service.sls
index 36d8aff..2d03c62 100644
--- a/salt/minion/service.sls
+++ b/salt/minion/service.sls
@@ -59,6 +59,37 @@
- cmd: salt_minion_service_restart
{%- endfor %}
{%- endif %}
+
+ {%- if support_yaml %}
+ {%- set dependency = support_yaml.get('dependency') %}
+ {%- if dependency %}
+ {%- if dependency.get('engine', 'pkg') == 'pkg' %}
+
+salt_minion_{{ service_name }}_dependencies:
+ pkg.installed:
+ - names: {{ dependency.get('pkgs') }}
+ - onchanges_in:
+ - cmd: salt_minion_service_restart
+ {%- elif dependency.get('engine', 'pkg') == 'pip' %}
+ {%- if dependency.get('pkgs') %}
+salt_minion_{{ service_name }}_dependencies:
+ pkg.installed:
+ - names: {{ dependency.get('pkgs') }}
+ - onchanges_in:
+ - cmd: salt_minion_service_restart
+ - require_in:
+ - pip: salt_minion_{{ service_name }}_dependencies_pip
+ {%- endif %}
+
+salt_minion_{{ service_name }}_dependencies_pip:
+ pip.installed:
+ - names: {{ dependency.get('python_pkgs') }}
+ - onchanges_in:
+ - cmd: salt_minion_service_restart
+
+ {%- endif %}
+ {%- endif %}
+ {%- endif %}
{%- endfor %}
salt_minion_service:
diff --git a/tests/pillar/control_virt_custom.sls b/tests/pillar/control_virt_custom.sls
new file mode 100644
index 0000000..7397494
--- /dev/null
+++ b/tests/pillar/control_virt_custom.sls
@@ -0,0 +1,55 @@
+virt:
+ disk:
+ three_disks:
+ - system:
+ size: 4096
+ image: ubuntu.qcow
+ - repository_snapshot:
+ size: 8192
+ image: snapshot.qcow
+ - cinder-volume:
+ size: 2048
+salt:
+ minion:
+ enabled: true
+ master:
+ host: config01.dc01.domain.com
+ control:
+ enabled: true
+ virt_enabled: true
+ size:
+ small:
+ cpu: 1
+ ram: 1
+ medium:
+ cpu: 2
+ ram: 4
+ large:
+ cpu: 4
+ ram: 8
+ medium_three_disks:
+ cpu: 2
+ ram: 4
+ disk_profile: three_disks
+ cluster:
+ vpc20_infra:
+ domain: neco.virt.domain.com
+ engine: virt
+ config:
+ engine: salt
+ host: master.domain.com
+ node:
+ ubuntu1:
+ provider: node01.domain.com
+ image: ubuntu.qcow
+ size: medium
+ img_dest: /var/lib/libvirt/ssdimages
+ ubuntu2:
+ provider: node02.domain.com
+ image: bubuntu.qcomw
+ size: small
+ img_dest: /var/lib/libvirt/hddimages
+ ubuntu3:
+ provider: node03.domain.com
+ image: meowbuntu.qcom2
+ size: medium_three_disks
diff --git a/tests/pillar/master_single_extpillars.sls b/tests/pillar/master_single_extpillars.sls
index 03521eb..d2d2422 100644
--- a/tests/pillar/master_single_extpillars.sls
+++ b/tests/pillar/master_single_extpillars.sls
@@ -17,6 +17,7 @@
command_timeout: 5
worker_threads: 2
base_environment: prd
+ pillar_safe_render_error: False
#environment:
# prd:
# formula: