mirror of
https://github.com/valitydev/salt.git
synced 2024-11-06 16:45:27 +00:00
Merge branch '2016.3' into 'develop'
Conflicts: - salt/config/__init__.py - salt/utils/parsers.py - tests/unit/config/config_test.py
This commit is contained in:
commit
d679c09e65
@ -84,6 +84,11 @@
|
|||||||
# Set the default outputter used by the salt command. The default is "nested".
|
# Set the default outputter used by the salt command. The default is "nested".
|
||||||
#output: nested
|
#output: nested
|
||||||
|
|
||||||
|
# Set the default output file used by the salt command. Default is to output
|
||||||
|
# to the CLI and not to a file. Functions the same way as the "--out-file"
|
||||||
|
CLI option, only sets this to a single file for all salt commands.
|
||||||
|
#output_file: None
|
||||||
|
|
||||||
# Return minions that timeout when running commands like test.ping
|
# Return minions that timeout when running commands like test.ping
|
||||||
#show_timeout: True
|
#show_timeout: True
|
||||||
|
|
||||||
|
@ -348,6 +348,21 @@ Default: ``nested``
|
|||||||
|
|
||||||
Set the default outputter used by the salt command.
|
Set the default outputter used by the salt command.
|
||||||
|
|
||||||
|
.. conf_master:: output_file
|
||||||
|
|
||||||
|
``output_file``
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Default: None
|
||||||
|
|
||||||
|
# Set the default output file used by the salt command. Default is to output
|
||||||
|
# to the CLI and not to a file. Functions the same way as the "--out-file"
|
||||||
|
CLI option, only sets this to a single file for all salt commands.
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
output_file: /path/output/file
|
||||||
|
|
||||||
.. conf_master:: color
|
.. conf_master:: color
|
||||||
|
|
||||||
``color``
|
``color``
|
||||||
|
@ -18,7 +18,7 @@ Installation from the SUSE Repository
|
|||||||
Since openSUSE 13.2, Salt 2014.1.11 is available in the primary repositories.
|
Since openSUSE 13.2, Salt 2014.1.11 is available in the primary repositories.
|
||||||
With the release of SUSE manager 3 a new repository setup has been created.
|
With the release of SUSE manager 3 a new repository setup has been created.
|
||||||
The new repo will by systemsmanagement:saltstack, which is the source
|
The new repo will by systemsmanagement:saltstack, which is the source
|
||||||
for newer stable packages. For backward compatibilty a linkpackage will be
|
for newer stable packages. For backward compatibility a linkpackage will be
|
||||||
created to the old devel:language:python repo.
|
created to the old devel:language:python repo.
|
||||||
All development of suse packages will be done in systemsmanagement:saltstack:testing.
|
All development of suse packages will be done in systemsmanagement:saltstack:testing.
|
||||||
This will ensure that salt will be in mainline suse repo's, a stable release
|
This will ensure that salt will be in mainline suse repo's, a stable release
|
||||||
|
@ -537,7 +537,7 @@ authentication every ten seconds by default.
|
|||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
{# Ink server faild to authenticate -- remove accepted key #}
|
{# Ink server failed to authenticate -- remove accepted key #}
|
||||||
{% if not data['result'] and data['id'].startswith('ink') %}
|
{% if not data['result'] and data['id'].startswith('ink') %}
|
||||||
minion_remove:
|
minion_remove:
|
||||||
wheel.key.delete:
|
wheel.key.delete:
|
||||||
|
@ -45,7 +45,7 @@ Changes:
|
|||||||
* a983942 Merge pull request `#25095`_ from jfindlay/win_groupadd_test
|
* a983942 Merge pull request `#25095`_ from jfindlay/win_groupadd_test
|
||||||
* 564dffd depend on win libs rather than mocking them
|
* 564dffd depend on win libs rather than mocking them
|
||||||
|
|
||||||
* 9b9aeb8 resolved all erors.
|
* 9b9aeb8 resolved all errors.
|
||||||
|
|
||||||
* aaf8935 adding win_groupadd unit test case.
|
* aaf8935 adding win_groupadd unit test case.
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ Changes:
|
|||||||
|
|
||||||
- **PR** `#32588`_: (*anlutro*) Fix salt-ssh module function call argument type juggling by JSON encoding them
|
- **PR** `#32588`_: (*anlutro*) Fix salt-ssh module function call argument type juggling by JSON encoding them
|
||||||
|
|
||||||
* 5e7edfc yumpkg: Ignore epoch in version comparison for explict versions without an epoch (`#32563`_)
|
* 5e7edfc yumpkg: Ignore epoch in version comparison for explicit versions without an epoch (`#32563`_)
|
||||||
|
|
||||||
* fea6056 Fixing critical bug to remove only the specified Host instead of the entire Host cluster (`#32640`_)
|
* fea6056 Fixing critical bug to remove only the specified Host instead of the entire Host cluster (`#32640`_)
|
||||||
|
|
||||||
@ -296,7 +296,7 @@ Changes:
|
|||||||
|
|
||||||
- **PR** `#32423`_: (*jtand*) Update glusterfs_test to be inline with `#32312`_
|
- **PR** `#32423`_: (*jtand*) Update glusterfs_test to be inline with `#32312`_
|
||||||
|
|
||||||
- **PR** `#32425`_: (*cachedout*) Fix salt-cloud paralell provisioning
|
- **PR** `#32425`_: (*cachedout*) Fix salt-cloud parallel provisioning
|
||||||
|
|
||||||
* 51fb2ac FreeBSD supports packages in format java/openjdk7 so the prior commit broke that functionality. Check freebsd/pkg`#1409`_ for more info.
|
* 51fb2ac FreeBSD supports packages in format java/openjdk7 so the prior commit broke that functionality. Check freebsd/pkg`#1409`_ for more info.
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ Changes:
|
|||||||
|
|
||||||
- **PR** `#33851`_: (*ticosax*) [dockerng] Add support for edge case when `Cmd` and `Entrypoint` can't be blanked
|
- **PR** `#33851`_: (*ticosax*) [dockerng] Add support for edge case when `Cmd` and `Entrypoint` can't be blanked
|
||||||
|
|
||||||
- **PR** `#33821`_: (*cachedout*) Restore deafault log level to warning
|
- **PR** `#33821`_: (*cachedout*) Restore default log level to warning
|
||||||
|
|
||||||
- **PR** `#33767`_: (*amontalban*) Fix `#33604`_ implementation when 'geom disk list' does not output rotat…
|
- **PR** `#33767`_: (*amontalban*) Fix `#33604`_ implementation when 'geom disk list' does not output rotat…
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ primarily used for fetching files and returning job returns. The req channels
|
|||||||
have two basic interfaces when talking to the master. ``send`` is the basic
|
have two basic interfaces when talking to the master. ``send`` is the basic
|
||||||
method that guarantees the message is encrypted at least so that only minions
|
method that guarantees the message is encrypted at least so that only minions
|
||||||
attached to the same master can read it-- but no guarantee of minion-master
|
attached to the same master can read it-- but no guarantee of minion-master
|
||||||
confidentiality, wheras the ``crypted_transfer_decode_dictentry`` method does
|
confidentiality, whereas the ``crypted_transfer_decode_dictentry`` method does
|
||||||
guarantee minion-master confidentiality.
|
guarantee minion-master confidentiality.
|
||||||
|
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ Salt Master Auth Flooding
|
|||||||
|
|
||||||
In large installations, care must be taken not to overwhealm the master with
|
In large installations, care must be taken not to overwhealm the master with
|
||||||
authentication requests. Several options can be set on the master which
|
authentication requests. Several options can be set on the master which
|
||||||
mitigate the chances of an authentication flood from causing an interuption in
|
mitigate the chances of an authentication flood from causing an interruption in
|
||||||
service.
|
service.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
@ -391,6 +391,8 @@ def expand_ldap_entries(entries, opts=None):
|
|||||||
bind = _bind_for_search(opts=opts)
|
bind = _bind_for_search(opts=opts)
|
||||||
acl_tree = []
|
acl_tree = []
|
||||||
for user_or_group_dict in entries:
|
for user_or_group_dict in entries:
|
||||||
|
if not isinstance(user_or_group_dict, dict):
|
||||||
|
acl_tree.append(user_or_group_dict)
|
||||||
for minion_or_ou, matchers in six.iteritems(user_or_group_dict):
|
for minion_or_ou, matchers in six.iteritems(user_or_group_dict):
|
||||||
permissions = matchers
|
permissions = matchers
|
||||||
retrieved_minion_ids = []
|
retrieved_minion_ids = []
|
||||||
|
@ -39,6 +39,7 @@ import salt.utils.validate.path
|
|||||||
import salt.utils.xdg
|
import salt.utils.xdg
|
||||||
import salt.exceptions
|
import salt.exceptions
|
||||||
from salt.utils.locales import sdecode
|
from salt.utils.locales import sdecode
|
||||||
|
import salt.defaults.exitcodes
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -1563,18 +1564,18 @@ def _read_conf_file(path):
|
|||||||
try:
|
try:
|
||||||
conf_opts = yaml.safe_load(conf_file.read()) or {}
|
conf_opts = yaml.safe_load(conf_file.read()) or {}
|
||||||
except yaml.YAMLError as err:
|
except yaml.YAMLError as err:
|
||||||
log.error(
|
message = 'Error parsing configuration file: {0} - {1}'.format(path, err)
|
||||||
'Error parsing configuration file: {0} - {1}'.format(path, err)
|
log.error(message)
|
||||||
)
|
raise salt.exceptions.SaltConfigurationError(message)
|
||||||
conf_opts = {}
|
|
||||||
# only interpret documents as a valid conf, not things like strings,
|
# only interpret documents as a valid conf, not things like strings,
|
||||||
# which might have been caused by invalid yaml syntax
|
# which might have been caused by invalid yaml syntax
|
||||||
if not isinstance(conf_opts, dict):
|
if not isinstance(conf_opts, dict):
|
||||||
log.error(
|
message = 'Error parsing configuration file: {0} - conf ' \
|
||||||
'Error parsing configuration file: {0} - conf should be a '
|
'should be a document, not {1}.'.format(path, type(conf_opts))
|
||||||
'document, not {1}.'.format(path, type(conf_opts))
|
log.error(message)
|
||||||
)
|
raise salt.exceptions.SaltConfigurationError(message)
|
||||||
conf_opts = {}
|
|
||||||
# allow using numeric ids: convert int to string
|
# allow using numeric ids: convert int to string
|
||||||
if 'id' in conf_opts:
|
if 'id' in conf_opts:
|
||||||
if not isinstance(conf_opts['id'], six.string_types):
|
if not isinstance(conf_opts['id'], six.string_types):
|
||||||
@ -1657,15 +1658,19 @@ def load_config(path, env_var, default_path=None):
|
|||||||
out.write(ifile.read())
|
out.write(ifile.read())
|
||||||
|
|
||||||
if salt.utils.validate.path.is_readable(path):
|
if salt.utils.validate.path.is_readable(path):
|
||||||
|
try:
|
||||||
opts = _read_conf_file(path)
|
opts = _read_conf_file(path)
|
||||||
opts['conf_file'] = path
|
opts['conf_file'] = path
|
||||||
return opts
|
return opts
|
||||||
|
except salt.exceptions.SaltConfigurationError as error:
|
||||||
|
log.error(error)
|
||||||
|
sys.exit(salt.defaults.exitcodes.EX_GENERIC)
|
||||||
|
|
||||||
log.debug('Missing configuration file: {0}'.format(path))
|
log.debug('Missing configuration file: {0}'.format(path))
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def include_config(include, orig_path, verbose):
|
def include_config(include, orig_path, verbose, exit_on_config_errors=False):
|
||||||
'''
|
'''
|
||||||
Parses extra configuration file(s) specified in an include list in the
|
Parses extra configuration file(s) specified in an include list in the
|
||||||
main config file.
|
main config file.
|
||||||
@ -1700,8 +1705,13 @@ def include_config(include, orig_path, verbose):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for fn_ in sorted(glob.glob(path)):
|
for fn_ in sorted(glob.glob(path)):
|
||||||
log.debug("Including configuration from '{0}'".format(fn_))
|
log.debug('Including configuration from \'{0}\''.format(fn_))
|
||||||
|
try:
|
||||||
opts = _read_conf_file(fn_)
|
opts = _read_conf_file(fn_)
|
||||||
|
except salt.exceptions.SaltConfigurationError as error:
|
||||||
|
log.error(error)
|
||||||
|
if exit_on_config_errors:
|
||||||
|
sys.exit(salt.defaults.exitcodes.EX_GENERIC)
|
||||||
|
|
||||||
include = opts.get('include', [])
|
include = opts.get('include', [])
|
||||||
if include:
|
if include:
|
||||||
@ -1744,7 +1754,8 @@ def insert_system_path(opts, paths):
|
|||||||
def minion_config(path,
|
def minion_config(path,
|
||||||
env_var='SALT_MINION_CONFIG',
|
env_var='SALT_MINION_CONFIG',
|
||||||
defaults=None,
|
defaults=None,
|
||||||
cache_minion_id=False):
|
cache_minion_id=False,
|
||||||
|
ignore_config_errors=True):
|
||||||
'''
|
'''
|
||||||
Reads in the minion configuration file and sets up special options
|
Reads in the minion configuration file and sets up special options
|
||||||
|
|
||||||
@ -1779,8 +1790,10 @@ def minion_config(path,
|
|||||||
defaults['default_include'])
|
defaults['default_include'])
|
||||||
include = overrides.get('include', [])
|
include = overrides.get('include', [])
|
||||||
|
|
||||||
overrides.update(include_config(default_include, path, verbose=False))
|
overrides.update(include_config(default_include, path, verbose=False,
|
||||||
overrides.update(include_config(include, path, verbose=True))
|
exit_on_config_errors=not ignore_config_errors))
|
||||||
|
overrides.update(include_config(include, path, verbose=True,
|
||||||
|
exit_on_config_errors=not ignore_config_errors))
|
||||||
|
|
||||||
opts = apply_minion_config(overrides, defaults, cache_minion_id=cache_minion_id)
|
opts = apply_minion_config(overrides, defaults, cache_minion_id=cache_minion_id)
|
||||||
_validate_opts(opts)
|
_validate_opts(opts)
|
||||||
@ -3006,7 +3019,7 @@ def apply_minion_config(overrides=None,
|
|||||||
return opts
|
return opts
|
||||||
|
|
||||||
|
|
||||||
def master_config(path, env_var='SALT_MASTER_CONFIG', defaults=None):
|
def master_config(path, env_var='SALT_MASTER_CONFIG', defaults=None, exit_on_config_errors=False):
|
||||||
'''
|
'''
|
||||||
Reads in the master configuration file and sets up default options
|
Reads in the master configuration file and sets up default options
|
||||||
|
|
||||||
@ -3033,8 +3046,8 @@ def master_config(path, env_var='SALT_MASTER_CONFIG', defaults=None):
|
|||||||
defaults['default_include'])
|
defaults['default_include'])
|
||||||
include = overrides.get('include', [])
|
include = overrides.get('include', [])
|
||||||
|
|
||||||
overrides.update(include_config(default_include, path, verbose=False))
|
overrides.update(include_config(default_include, path, verbose=False), exit_on_config_errors=exit_on_config_errors)
|
||||||
overrides.update(include_config(include, path, verbose=True))
|
overrides.update(include_config(include, path, verbose=True), exit_on_config_errors=exit_on_config_errors)
|
||||||
opts = apply_master_config(overrides, defaults)
|
opts = apply_master_config(overrides, defaults)
|
||||||
_validate_opts(opts)
|
_validate_opts(opts)
|
||||||
# If 'nodegroups:' is uncommented in the master config file, and there are
|
# If 'nodegroups:' is uncommented in the master config file, and there are
|
||||||
|
@ -305,6 +305,12 @@ class SaltWheelError(SaltException):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class SaltConfigurationError(SaltException):
|
||||||
|
'''
|
||||||
|
Configuration error
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
class SaltSystemExit(SystemExit):
|
class SaltSystemExit(SystemExit):
|
||||||
'''
|
'''
|
||||||
This exception is raised when an unsolvable problem is found. There's
|
This exception is raised when an unsolvable problem is found. There's
|
||||||
|
@ -924,7 +924,9 @@ class AESFuncs(object):
|
|||||||
self.mminion = salt.minion.MasterMinion(
|
self.mminion = salt.minion.MasterMinion(
|
||||||
self.opts,
|
self.opts,
|
||||||
states=False,
|
states=False,
|
||||||
rend=False)
|
rend=False,
|
||||||
|
ignore_config_errors=True
|
||||||
|
)
|
||||||
self.__setup_fileserver()
|
self.__setup_fileserver()
|
||||||
self.masterapi = salt.daemons.masterapi.RemoteFuncs(opts)
|
self.masterapi = salt.daemons.masterapi.RemoteFuncs(opts)
|
||||||
|
|
||||||
@ -1600,7 +1602,9 @@ class ClearFuncs(object):
|
|||||||
self.mminion = salt.minion.MasterMinion(
|
self.mminion = salt.minion.MasterMinion(
|
||||||
self.opts,
|
self.opts,
|
||||||
states=False,
|
states=False,
|
||||||
rend=False)
|
rend=False,
|
||||||
|
ignore_config_errors=True
|
||||||
|
)
|
||||||
# Make a wheel object
|
# Make a wheel object
|
||||||
self.wheel_ = salt.wheel.Wheel(opts)
|
self.wheel_ = salt.wheel.Wheel(opts)
|
||||||
# Make a masterapi object
|
# Make a masterapi object
|
||||||
|
@ -670,8 +670,9 @@ class MasterMinion(object):
|
|||||||
states=True,
|
states=True,
|
||||||
rend=True,
|
rend=True,
|
||||||
matcher=True,
|
matcher=True,
|
||||||
whitelist=None):
|
whitelist=None,
|
||||||
self.opts = salt.config.minion_config(opts['conf_file'])
|
ignore_config_errors=True):
|
||||||
|
self.opts = salt.config.minion_config(opts['conf_file'], ignore_config_errors=ignore_config_errors)
|
||||||
self.opts.update(opts)
|
self.opts.update(opts)
|
||||||
self.whitelist = whitelist
|
self.whitelist = whitelist
|
||||||
self.opts['grains'] = salt.loader.grains(opts)
|
self.opts['grains'] = salt.loader.grains(opts)
|
||||||
|
@ -813,10 +813,10 @@ def add_source(name, source_location, username=None, password=None):
|
|||||||
Location of the source you want to work with.
|
Location of the source you want to work with.
|
||||||
|
|
||||||
username
|
username
|
||||||
Provide username for chocolatey sources that need authentification credentials.
|
Provide username for chocolatey sources that need authentication credentials.
|
||||||
|
|
||||||
password
|
password
|
||||||
Provide password for chocolatey sources that need authentification credentials.
|
Provide password for chocolatey sources that need authentication credentials.
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
|
@ -2635,7 +2635,7 @@ def powershell(cmd,
|
|||||||
|
|
||||||
This passes the cmd argument directly to PowerShell
|
This passes the cmd argument directly to PowerShell
|
||||||
without any further processing! Be absolutely sure that you
|
without any further processing! Be absolutely sure that you
|
||||||
have properly santized the command passed to this function
|
have properly sanitized the command passed to this function
|
||||||
and do not use untrusted inputs.
|
and do not use untrusted inputs.
|
||||||
|
|
||||||
Note that ``env`` represents the environment variables for the command, and
|
Note that ``env`` represents the environment variables for the command, and
|
||||||
|
@ -12,7 +12,7 @@ Module to import docker-compose via saltstack
|
|||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
This module allows to deal with docker-compose file in a directory.
|
This module allows one to deal with docker-compose file in a directory.
|
||||||
|
|
||||||
This is a first version only, the following commands are missing at the moment
|
This is a first version only, the following commands are missing at the moment
|
||||||
but will be built later on if the community is interested in this module:
|
but will be built later on if the community is interested in this module:
|
||||||
@ -93,7 +93,7 @@ Functions
|
|||||||
- Manage containers image:
|
- Manage containers image:
|
||||||
- :py:func:`dockercompose.pull <salt.modules.dockercompose.pull>`
|
- :py:func:`dockercompose.pull <salt.modules.dockercompose.pull>`
|
||||||
- :py:func:`dockercompose.build <salt.modules.dockercompose.build>`
|
- :py:func:`dockercompose.build <salt.modules.dockercompose.build>`
|
||||||
- Gather informations about containers:
|
- Gather information about containers:
|
||||||
- :py:func:`dockercompose.ps <salt.modules.dockercompose.ps>`
|
- :py:func:`dockercompose.ps <salt.modules.dockercompose.ps>`
|
||||||
|
|
||||||
Detailed Function Documentation
|
Detailed Function Documentation
|
||||||
@ -356,7 +356,7 @@ def build(path, service_names=None):
|
|||||||
python list, if omitted build images for all containers. Please note
|
python list, if omitted build images for all containers. Please note
|
||||||
that at the moment the module does not allow you to upload your Dockerfile,
|
that at the moment the module does not allow you to upload your Dockerfile,
|
||||||
nor any other file you could need with your docker-compose.yml, you will
|
nor any other file you could need with your docker-compose.yml, you will
|
||||||
have to make sure the files you need are actually in the directory sepcified
|
have to make sure the files you need are actually in the directory specified
|
||||||
in the `build` keyword
|
in the `build` keyword
|
||||||
|
|
||||||
path
|
path
|
||||||
|
@ -1674,7 +1674,7 @@ def replace(path,
|
|||||||
|
|
||||||
Replace occurrences of a pattern in a file. If ``show_changes`` is
|
Replace occurrences of a pattern in a file. If ``show_changes`` is
|
||||||
``True``, then a diff of what changed will be returned, otherwise a
|
``True``, then a diff of what changed will be returned, otherwise a
|
||||||
``True`` will be returnd when changes are made, and ``False`` when
|
``True`` will be returned when changes are made, and ``False`` when
|
||||||
no changes are made.
|
no changes are made.
|
||||||
|
|
||||||
This is a pure Python implementation that wraps Python's :py:func:`~re.sub`.
|
This is a pure Python implementation that wraps Python's :py:func:`~re.sub`.
|
||||||
|
@ -97,7 +97,7 @@ def delete_record(name,
|
|||||||
the infoblox user's password (can also use the infolblox:password pillar)
|
the infoblox user's password (can also use the infolblox:password pillar)
|
||||||
|
|
||||||
infoblox_api_version
|
infoblox_api_version
|
||||||
the infoblox api verison to use
|
the infoblox api version to use
|
||||||
|
|
||||||
sslVerify
|
sslVerify
|
||||||
should ssl verification be done on the connection to the Infoblox REST API
|
should ssl verification be done on the connection to the Infoblox REST API
|
||||||
@ -175,7 +175,7 @@ def update_record(name,
|
|||||||
the infoblox user's password (can also use the infolblox:password pillar)
|
the infoblox user's password (can also use the infolblox:password pillar)
|
||||||
|
|
||||||
infoblox_api_version
|
infoblox_api_version
|
||||||
the infoblox api verison to use
|
the infoblox api version to use
|
||||||
|
|
||||||
sslVerify
|
sslVerify
|
||||||
should ssl verification be done on the connection to the Infoblox REST API
|
should ssl verification be done on the connection to the Infoblox REST API
|
||||||
@ -270,7 +270,7 @@ def add_record(name,
|
|||||||
the infoblox user's password (can also use the infolblox:password pillar)
|
the infoblox user's password (can also use the infolblox:password pillar)
|
||||||
|
|
||||||
infoblox_api_version
|
infoblox_api_version
|
||||||
the infoblox api verison to use
|
the infoblox api version to use
|
||||||
|
|
||||||
sslVerify
|
sslVerify
|
||||||
should ssl verification be done on the connection to the Infoblox REST API
|
should ssl verification be done on the connection to the Infoblox REST API
|
||||||
@ -353,7 +353,7 @@ def get_network(network_name,
|
|||||||
the infoblox user's password (can also use the infolblox:password pillar)
|
the infoblox user's password (can also use the infolblox:password pillar)
|
||||||
|
|
||||||
infoblox_api_version
|
infoblox_api_version
|
||||||
the infoblox api verison to use
|
the infoblox api version to use
|
||||||
|
|
||||||
sslVerify
|
sslVerify
|
||||||
should ssl verification be done on the connection to the Infoblox REST API
|
should ssl verification be done on the connection to the Infoblox REST API
|
||||||
@ -426,7 +426,7 @@ def get_record(record_name,
|
|||||||
the infoblox DNS view to search, if not specified all views are searched
|
the infoblox DNS view to search, if not specified all views are searched
|
||||||
|
|
||||||
infoblox_api_version
|
infoblox_api_version
|
||||||
the infoblox api verison to use
|
the infoblox api version to use
|
||||||
|
|
||||||
sslVerify
|
sslVerify
|
||||||
should ssl verification be done on the connection to the Infoblox REST API
|
should ssl verification be done on the connection to the Infoblox REST API
|
||||||
|
@ -12,7 +12,7 @@ Support for Opkg
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
For version comparision support, the ``opkg-utils`` package must be
|
For version comparison support, the ``opkg-utils`` package must be
|
||||||
installed.
|
installed.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
@ -406,10 +406,10 @@ def lookup(search=None, order=None, one=False):
|
|||||||
|
|
||||||
def sysrq(vm, action='nmi', key='uuid'):
|
def sysrq(vm, action='nmi', key='uuid'):
|
||||||
'''
|
'''
|
||||||
Send non-maskable interupt to vm or capture a screenshot
|
Send non-maskable interrupt to vm or capture a screenshot
|
||||||
|
|
||||||
vm : string
|
vm : string
|
||||||
vm to be targetted
|
vm to be targeted
|
||||||
action : string
|
action : string
|
||||||
nmi or screenshot -- Default: nmi
|
nmi or screenshot -- Default: nmi
|
||||||
key : string [uuid|alias|hostname]
|
key : string [uuid|alias|hostname]
|
||||||
@ -490,7 +490,7 @@ def get(vm, key='uuid'):
|
|||||||
Output the JSON object describing a VM
|
Output the JSON object describing a VM
|
||||||
|
|
||||||
vm : string
|
vm : string
|
||||||
vm to be targetted
|
vm to be targeted
|
||||||
key : string [uuid|alias|hostname]
|
key : string [uuid|alias|hostname]
|
||||||
value type of 'vm' parameter
|
value type of 'vm' parameter
|
||||||
|
|
||||||
@ -527,7 +527,7 @@ def info(vm, info_type='all', key='uuid'):
|
|||||||
Lookup info on running kvm
|
Lookup info on running kvm
|
||||||
|
|
||||||
vm : string
|
vm : string
|
||||||
vm to be targetted
|
vm to be targeted
|
||||||
info_type : string [all|block|blockstats|chardev|cpus|kvm|pci|spice|version|vnc]
|
info_type : string [all|block|blockstats|chardev|cpus|kvm|pci|spice|version|vnc]
|
||||||
info type to return
|
info type to return
|
||||||
key : string [uuid|alias|hostname]
|
key : string [uuid|alias|hostname]
|
||||||
@ -572,7 +572,7 @@ def create_snapshot(vm, name, key='uuid'):
|
|||||||
Create snapshot of a vm
|
Create snapshot of a vm
|
||||||
|
|
||||||
vm : string
|
vm : string
|
||||||
vm to be targetted
|
vm to be targeted
|
||||||
name : string
|
name : string
|
||||||
snapshot name
|
snapshot name
|
||||||
The snapname must be 64 characters or less
|
The snapname must be 64 characters or less
|
||||||
@ -625,7 +625,7 @@ def delete_snapshot(vm, name, key='uuid'):
|
|||||||
Delete snapshot of a vm
|
Delete snapshot of a vm
|
||||||
|
|
||||||
vm : string
|
vm : string
|
||||||
vm to be targetted
|
vm to be targeted
|
||||||
name : string
|
name : string
|
||||||
snapshot name
|
snapshot name
|
||||||
The snapname must be 64 characters or less
|
The snapname must be 64 characters or less
|
||||||
@ -675,7 +675,7 @@ def rollback_snapshot(vm, name, key='uuid'):
|
|||||||
Rollback snapshot of a vm
|
Rollback snapshot of a vm
|
||||||
|
|
||||||
vm : string
|
vm : string
|
||||||
vm to be targetted
|
vm to be targeted
|
||||||
name : string
|
name : string
|
||||||
snapshot name
|
snapshot name
|
||||||
The snapname must be 64 characters or less
|
The snapname must be 64 characters or less
|
||||||
|
@ -518,7 +518,7 @@ def faulty():
|
|||||||
|
|
||||||
def healthy():
|
def healthy():
|
||||||
'''
|
'''
|
||||||
Return wether fmadm is reporting faults
|
Return whether fmadm is reporting faults
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
|
@ -1083,7 +1083,7 @@ def time_(format='%A, %d. %B %Y %I:%M%p'):
|
|||||||
.. versionadded:: 2016.3.0
|
.. versionadded:: 2016.3.0
|
||||||
|
|
||||||
Return the current time on the minion,
|
Return the current time on the minion,
|
||||||
formated based on the format parameter.
|
formatted based on the format parameter.
|
||||||
|
|
||||||
Default date format: Monday, 27. July 2015 07:55AM
|
Default date format: Monday, 27. July 2015 07:55AM
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ def get_alert_config(deployment_id, metric_name=None, api_key=None, profile="tel
|
|||||||
def get_notification_channel_id(notify_channel, profile="telemetry"):
|
def get_notification_channel_id(notify_channel, profile="telemetry"):
|
||||||
'''
|
'''
|
||||||
Given an email address, creates a notification-channels
|
Given an email address, creates a notification-channels
|
||||||
if one is not found and also returns the corresponsing
|
if one is not found and also returns the corresponding
|
||||||
notification channel id.
|
notification channel id.
|
||||||
|
|
||||||
notify_channel
|
notify_channel
|
||||||
|
@ -65,7 +65,7 @@ def add_store(source, store, saltenv='base'):
|
|||||||
Add the given cert into the given Certificate Store
|
Add the given cert into the given Certificate Store
|
||||||
|
|
||||||
source
|
source
|
||||||
The source certficate file this can be in the form
|
The source certificate file this can be in the form
|
||||||
salt://path/to/file
|
salt://path/to/file
|
||||||
|
|
||||||
store
|
store
|
||||||
@ -91,7 +91,7 @@ def del_store(source, store, saltenv='base'):
|
|||||||
Delete the given cert into the given Certificate Store
|
Delete the given cert into the given Certificate Store
|
||||||
|
|
||||||
source
|
source
|
||||||
The source certficate file this can be in the form
|
The source certificate file this can be in the form
|
||||||
salt://path/to/file
|
salt://path/to/file
|
||||||
|
|
||||||
store
|
store
|
||||||
|
@ -520,7 +520,7 @@ def create_task_from_xml(name,
|
|||||||
(C:\Windows\System32\tasks).
|
(C:\Windows\System32\tasks).
|
||||||
|
|
||||||
:param str xml_text: A string of xml representing the task to be created.
|
:param str xml_text: A string of xml representing the task to be created.
|
||||||
This will be overriden by `xml_path` if passed.
|
This will be overridden by `xml_path` if passed.
|
||||||
|
|
||||||
:param str xml_path: The path to an XML file on the local system containing
|
:param str xml_path: The path to an XML file on the local system containing
|
||||||
the xml that defines the task. This will override `xml_text`
|
the xml that defines the task. This will override `xml_text`
|
||||||
|
@ -320,7 +320,7 @@ def list_(name=None, **kwargs):
|
|||||||
depth : int
|
depth : int
|
||||||
limit recursion to depth
|
limit recursion to depth
|
||||||
properties : string
|
properties : string
|
||||||
comma-seperated list of properties to list, the name property will always be added
|
comma-separated list of properties to list, the name property will always be added
|
||||||
type : string
|
type : string
|
||||||
comma-separated list of types to display, where type is one of
|
comma-separated list of types to display, where type is one of
|
||||||
filesystem, snapshot, volume, bookmark, or all.
|
filesystem, snapshot, volume, bookmark, or all.
|
||||||
@ -885,7 +885,7 @@ def hold(tag, *snapshot, **kwargs):
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
A comma-seperated list can be provided for the tag parameter to hold multiple tags.
|
A comma-separated list can be provided for the tag parameter to hold multiple tags.
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
@ -963,7 +963,7 @@ def release(tag, *snapshot, **kwargs):
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
A comma-seperated list can be provided for the tag parameter to release multiple tags.
|
A comma-separated list can be provided for the tag parameter to release multiple tags.
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
@ -1192,7 +1192,7 @@ def get(*dataset, **kwargs):
|
|||||||
depth : int
|
depth : int
|
||||||
recursively list children to depth
|
recursively list children to depth
|
||||||
fields : string
|
fields : string
|
||||||
comma-seperated list of fields to include, the name and property field will always be added
|
comma-separated list of fields to include, the name and property field will always be added
|
||||||
type : string
|
type : string
|
||||||
comma-separated list of types to display, where type is one of
|
comma-separated list of types to display, where type is one of
|
||||||
filesystem, snapshot, volume, bookmark, or all.
|
filesystem, snapshot, volume, bookmark, or all.
|
||||||
|
@ -345,7 +345,7 @@ def list_(properties='size,alloc,free,cap,frag,health', zpool=None):
|
|||||||
optional zpool
|
optional zpool
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
multiple storage pool can be provded as a space seperated list
|
multiple storage pool can be provded as a space separated list
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
@ -1085,7 +1085,7 @@ def import_(zpool=None, new_name=None, **kwargs):
|
|||||||
altroot : string
|
altroot : string
|
||||||
equivalent to "-o cachefile=none,altroot=root"
|
equivalent to "-o cachefile=none,altroot=root"
|
||||||
dir : string
|
dir : string
|
||||||
searches for devices or files in dir, mutiple dirs can be specified as follows:: dir="dir1,dir2"
|
searches for devices or files in dir, multiple dirs can be specified as follows:: dir="dir1,dir2"
|
||||||
no_mount : boolean
|
no_mount : boolean
|
||||||
import the pool without mounting any file systems.
|
import the pool without mounting any file systems.
|
||||||
only_destroyed : boolean
|
only_destroyed : boolean
|
||||||
|
@ -125,7 +125,7 @@ Configuring git_pillar for Salt releases 2015.8.0 and later
|
|||||||
will also be logged.
|
will also be logged.
|
||||||
|
|
||||||
Beginning with Salt version 2015.8.0, pygit2_ is now supported in addition to
|
Beginning with Salt version 2015.8.0, pygit2_ is now supported in addition to
|
||||||
GitPython_ (Dulwich_ will not be supported for the forseeable future). The
|
GitPython_ (Dulwich_ will not be supported for the foreseeable future). The
|
||||||
requirements for GitPython_ and pygit2_ are the same as for gitfs, as described
|
requirements for GitPython_ and pygit2_ are the same as for gitfs, as described
|
||||||
:ref:`here <gitfs-dependencies>`.
|
:ref:`here <gitfs-dependencies>`.
|
||||||
|
|
||||||
|
@ -77,8 +77,8 @@ You can also provide a list of config files:
|
|||||||
Select config files through grains|pillar|opts matching
|
Select config files through grains|pillar|opts matching
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
You can also opt for a much more flexible configuration: PillarStack allows to
|
You can also opt for a much more flexible configuration: PillarStack allows one
|
||||||
select the config files for the current minion based on matching values from
|
to select the config files for the current minion based on matching values from
|
||||||
either grains, or pillar, or opts objects.
|
either grains, or pillar, or opts objects.
|
||||||
|
|
||||||
Here is an example of such a configuration, which should speak by itself:
|
Here is an example of such a configuration, which should speak by itself:
|
||||||
|
@ -374,7 +374,7 @@ def list_jobs(ext_source=None,
|
|||||||
else:
|
else:
|
||||||
log.error(
|
log.error(
|
||||||
'\'dateutil\' library not available, skipping start_time '
|
'\'dateutil\' library not available, skipping start_time '
|
||||||
'comparision.'
|
'comparison.'
|
||||||
)
|
)
|
||||||
|
|
||||||
if end_time and _match:
|
if end_time and _match:
|
||||||
@ -387,7 +387,7 @@ def list_jobs(ext_source=None,
|
|||||||
else:
|
else:
|
||||||
log.error(
|
log.error(
|
||||||
'\'dateutil\' library not available, skipping end_time '
|
'\'dateutil\' library not available, skipping end_time '
|
||||||
'comparision.'
|
'comparison.'
|
||||||
)
|
)
|
||||||
|
|
||||||
if _match:
|
if _match:
|
||||||
|
@ -15,7 +15,7 @@ module:
|
|||||||
kmod.absent:
|
kmod.absent:
|
||||||
- name: pcspkr
|
- name: pcspkr
|
||||||
|
|
||||||
Mutiple modules can be specified for both kmod.present and kmod.absent.
|
Multiple modules can be specified for both kmod.present and kmod.absent.
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def managed(name, entries, connect_spec=None):
|
def managed(name, entries, connect_spec=None):
|
||||||
'''Ensure the existance (or not) of LDAP entries and their attributes
|
'''Ensure the existence (or not) of LDAP entries and their attributes
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ def exists(name, attributes):
|
|||||||
attributes
|
attributes
|
||||||
The attributes that should exist on the file/directory, this is accepted as
|
The attributes that should exist on the file/directory, this is accepted as
|
||||||
an array, with key and value split with an equals sign, if you want to specify
|
an array, with key and value split with an equals sign, if you want to specify
|
||||||
a hex value then add 0x to the begining of the value.
|
a hex value then add 0x to the beginning of the value.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
ret = {'name': name,
|
ret = {'name': name,
|
||||||
|
@ -69,14 +69,14 @@ class ContextDict(collections.MutableMapping):
|
|||||||
def __init__(self, **data):
|
def __init__(self, **data):
|
||||||
# state should be thread local, so this object can be threadsafe
|
# state should be thread local, so this object can be threadsafe
|
||||||
self._state = threading.local()
|
self._state = threading.local()
|
||||||
# variable for the overriden data
|
# variable for the overridden data
|
||||||
self._state.data = None
|
self._state.data = None
|
||||||
self.global_data = {}
|
self.global_data = {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def active(self):
|
def active(self):
|
||||||
'''Determine if this ContextDict is currently overriden
|
'''Determine if this ContextDict is currently overridden
|
||||||
Since the ContextDict can be overriden in each thread, we check whether
|
Since the ContextDict can be overridden in each thread, we check whether
|
||||||
the _state.data is set or not.
|
the _state.data is set or not.
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
|
@ -2910,7 +2910,7 @@ class GitPillar(GitBase):
|
|||||||
def __init__(self, opts):
|
def __init__(self, opts):
|
||||||
self.role = 'git_pillar'
|
self.role = 'git_pillar'
|
||||||
# Dulwich has no function to check out a branch/tag, so this will be
|
# Dulwich has no function to check out a branch/tag, so this will be
|
||||||
# limited to GitPython and Pygit2 for the forseeable future.
|
# limited to GitPython and Pygit2 for the foreseeable future.
|
||||||
GitBase.__init__(self,
|
GitBase.__init__(self,
|
||||||
opts,
|
opts,
|
||||||
valid_providers=('gitpython', 'pygit2'))
|
valid_providers=('gitpython', 'pygit2'))
|
||||||
@ -2951,7 +2951,7 @@ class WinRepo(GitBase):
|
|||||||
def __init__(self, opts, winrepo_dir):
|
def __init__(self, opts, winrepo_dir):
|
||||||
self.role = 'winrepo'
|
self.role = 'winrepo'
|
||||||
# Dulwich has no function to check out a branch/tag, so this will be
|
# Dulwich has no function to check out a branch/tag, so this will be
|
||||||
# limited to GitPython and Pygit2 for the forseeable future.
|
# limited to GitPython and Pygit2 for the foreseeable future.
|
||||||
GitBase.__init__(self,
|
GitBase.__init__(self,
|
||||||
opts,
|
opts,
|
||||||
valid_providers=('gitpython', 'pygit2'),
|
valid_providers=('gitpython', 'pygit2'),
|
||||||
|
@ -38,6 +38,7 @@ import salt.utils.jid
|
|||||||
from salt.utils import kinds
|
from salt.utils import kinds
|
||||||
from salt.defaults import DEFAULT_TARGET_DELIM
|
from salt.defaults import DEFAULT_TARGET_DELIM
|
||||||
from salt.utils.validate.path import is_writeable
|
from salt.utils.validate.path import is_writeable
|
||||||
|
import salt.exceptions
|
||||||
|
|
||||||
# Import 3rd-party libs
|
# Import 3rd-party libs
|
||||||
import salt.ext.six as six
|
import salt.ext.six as six
|
||||||
@ -396,7 +397,12 @@ class SaltfileMixIn(six.with_metaclass(MixInMeta, object)):
|
|||||||
'Loading Saltfile from \'{0}\''.format(self.options.saltfile)
|
'Loading Saltfile from \'{0}\''.format(self.options.saltfile)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
saltfile_config = config._read_conf_file(saltfile)
|
saltfile_config = config._read_conf_file(saltfile)
|
||||||
|
except salt.exceptions.SaltConfigurationError as error:
|
||||||
|
self.error(error.message)
|
||||||
|
self.exit(salt.defaults.exitcodes.EX_GENERIC,
|
||||||
|
'{0}: error: {1}\n'.format(self.get_prog_name(), error.message))
|
||||||
|
|
||||||
if not saltfile_config:
|
if not saltfile_config:
|
||||||
# No configuration was loaded from the Saltfile
|
# No configuration was loaded from the Saltfile
|
||||||
@ -1697,7 +1703,8 @@ class MinionOptionParser(six.with_metaclass(OptionParserMeta, MasterOptionParser
|
|||||||
|
|
||||||
def setup_config(self):
|
def setup_config(self):
|
||||||
opts = config.minion_config(self.get_config_file_path(), # pylint: disable=no-member
|
opts = config.minion_config(self.get_config_file_path(), # pylint: disable=no-member
|
||||||
cache_minion_id=True)
|
cache_minion_id=True,
|
||||||
|
ignore_config_errors=False)
|
||||||
# Optimization: disable multiprocessing logging if running as a
|
# Optimization: disable multiprocessing logging if running as a
|
||||||
# daemon, without engines and without multiprocessing
|
# daemon, without engines and without multiprocessing
|
||||||
if not opts.get('engines') and not opts.get('multiprocessing', True) \
|
if not opts.get('engines') and not opts.get('multiprocessing', True) \
|
||||||
|
@ -17,7 +17,7 @@ import tempfile
|
|||||||
# Import Salt Testing libs
|
# Import Salt Testing libs
|
||||||
from salttesting import TestCase
|
from salttesting import TestCase
|
||||||
from salttesting.mock import MagicMock, patch
|
from salttesting.mock import MagicMock, patch
|
||||||
from salttesting.helpers import ensure_in_syspath, TestsLoggingHandler
|
from salttesting.helpers import ensure_in_syspath
|
||||||
from salt.exceptions import CommandExecutionError
|
from salt.exceptions import CommandExecutionError
|
||||||
|
|
||||||
ensure_in_syspath('../')
|
ensure_in_syspath('../')
|
||||||
@ -331,33 +331,27 @@ class ConfigTestCase(TestCase, integration.AdaptedConfigurationTestCaseMixIn):
|
|||||||
self.assertEqual(syndic_opts['_master_conf_file'], minion_conf_path)
|
self.assertEqual(syndic_opts['_master_conf_file'], minion_conf_path)
|
||||||
self.assertEqual(syndic_opts['_minion_conf_file'], syndic_conf_path)
|
self.assertEqual(syndic_opts['_minion_conf_file'], syndic_conf_path)
|
||||||
|
|
||||||
def test_issue_6714_parsing_errors_logged(self):
|
@patch('salt.utils.network.get_fqhostname', MagicMock(return_value='localhost'))
|
||||||
try:
|
def test_get_id_etc_hostname(self):
|
||||||
tempdir = tempfile.mkdtemp(dir=integration.SYS_TMP_DIR)
|
'''
|
||||||
test_config = os.path.join(tempdir, 'config')
|
Test calling salt.config.get_id() and falling back to looking at
|
||||||
|
/etc/hostname.
|
||||||
# Let's populate a master configuration file with some basic
|
'''
|
||||||
# settings
|
with patch('salt.utils.fopen', _fopen_side_effect_etc_hostname):
|
||||||
salt.utils.fopen(test_config, 'w').write(
|
self.assertEqual(
|
||||||
'root_dir: {0}\n'
|
sconfig.get_id({'root_dir': None, 'minion_id_caching': False}), (MOCK_HOSTNAME, False)
|
||||||
'log_file: {0}/foo.log\n'.format(tempdir) +
|
|
||||||
'\n\n\n'
|
|
||||||
'blah:false\n'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
with TestsLoggingHandler() as handler:
|
@patch('salt.utils.network.get_fqhostname', MagicMock(return_value='localhost'))
|
||||||
# Let's load the configuration
|
def test_get_id_etc_hosts(self):
|
||||||
config = sconfig.master_config(test_config)
|
'''
|
||||||
for message in handler.messages:
|
Test calling salt.config.get_id() and falling back all the way to
|
||||||
if message.startswith('ERROR:Error parsing configuration'):
|
looking up data from /etc/hosts.
|
||||||
break
|
'''
|
||||||
else:
|
with patch('salt.utils.fopen', _fopen_side_effect_etc_hosts):
|
||||||
raise AssertionError(
|
self.assertEqual(
|
||||||
'No parsing error message was logged'
|
sconfig.get_id({'root_dir': None, 'minion_id_caching': False}), (MOCK_HOSTNAME, False)
|
||||||
)
|
)
|
||||||
finally:
|
|
||||||
if os.path.isdir(tempdir):
|
|
||||||
shutil.rmtree(tempdir)
|
|
||||||
|
|
||||||
# <---- Salt Cloud Configuration Tests ---------------------------------------------
|
# <---- Salt Cloud Configuration Tests ---------------------------------------------
|
||||||
|
|
||||||
|
@ -937,7 +937,7 @@ class PostgresTestCase(TestCase):
|
|||||||
@patch('salt.modules.postgres.language_exists', Mock(return_value=True))
|
@patch('salt.modules.postgres.language_exists', Mock(return_value=True))
|
||||||
def test_language_exists(self):
|
def test_language_exists(self):
|
||||||
'''
|
'''
|
||||||
Test language existance check
|
Test language existence check
|
||||||
'''
|
'''
|
||||||
ret = postgres.language_exists(
|
ret = postgres.language_exists(
|
||||||
'sql',
|
'sql',
|
||||||
|
Loading…
Reference in New Issue
Block a user