"""
Salt state module
"""
import logging
import salt.utils.dictdiffer
import salt.utils.json
log = logging.getLogger(__name__)
__virtualname__ = "elasticsearch"
def __virtual__():
if "elasticsearch" in __salt__:
return __virtualname__
return (
False,
"elasticsearch execution module missing",
)
[docs]
def index_absent(name, hosts=None, profile=None):
"""
Ensure that the named index is absent.
name
Name of the index to remove
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
try:
index = __salt__["elasticsearch.index_get"](index=name, hosts=hosts, profile=profile)
if index and name in index:
if __opts__.get("test", False):
ret["comment"] = f"Index {name} will be removed"
ret["changes"]["old"] = index[name]
ret["result"] = None
else:
ret["result"] = __salt__["elasticsearch.index_delete"](
index=name, hosts=hosts, profile=profile
)
if ret["result"]:
ret["comment"] = f"Successfully removed index {name}".format(name)
ret["changes"]["old"] = index[name]
else:
ret["comment"] = f"Failed to remove index {name} for unknown reasons"
else:
ret["comment"] = f"Index {name} is already absent"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret
[docs]
def index_present(name, hosts=None, profile=None, **kwargs):
"""
Ensure that the named index is present.
name
Name of the index to add
source
URL to file specifying index definition. Cannot be used in combination with body.
aliases
The list of aliases
mappings
Mapping for fields in the index. If specified, this mapping
can include: - Field namelastic - Field data types - Mapping parameters
master_timeout
Specify timeout for connection to master
settings
Settings
timeout
Explicit operation timeout
wait_for_active_shards
Set the number of active shards to wait for before
the operation returns. It also accepts ('all', 'index-setting')
**Example:**
.. code-block:: yaml
# Default settings
mytestindex:
elasticsearch_index.present
# Extra settings
mytestindex2:
elasticsearch_index.present:
- settings:
index:
number_of_shards: 10
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
source = kwargs.pop("source", None)
try:
index_exists = __salt__["elasticsearch.index_exists"](
index=name, hosts=hosts, profile=profile
)
if not index_exists:
if __opts__["test"]:
ret["comment"] = f"Index {name} does not exist and will be created"
ret["changes"] = {"new": kwargs}
ret["result"] = None
else:
output = __salt__["elasticsearch.index_create"](
index=name, hosts=hosts, profile=profile, source=source, **kwargs
)
if output:
ret["comment"] = f"Successfully created index {name}"
ret["changes"] = {
"new": __salt__["elasticsearch.index_get"](
index=name, hosts=hosts, profile=profile
)[name]
}
else:
ret["result"] = False
ret["comment"] = f"Cannot create index {name}, {output}"
else:
ret["comment"] = f"Index {name} is already present"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret
[docs]
def alias_absent(name, index, hosts=None, profile=None):
"""
Ensure that the index alias is absent.
name
Name of the index alias to remove
index
Name of the index for the alias
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
try:
alias = __salt__["elasticsearch.alias_get"](
aliases=name, indices=index, hosts=hosts, profile=profile
)
if alias and alias.get(index, {}).get("aliases", {}).get(name, None) is not None:
if __opts__["test"]:
ret["comment"] = f"Alias {name} for index {index} will be removed"
ret["changes"]["old"] = alias.get(index, {}).get("aliases", {}).get(name, {})
ret["result"] = None
else:
ret["result"] = __salt__["elasticsearch.alias_delete"](
aliases=name, indices=index, hosts=hosts, profile=profile
)
if ret["result"]:
ret["comment"] = f"Successfully removed alias {name} for index {index}"
ret["changes"]["old"] = alias.get(index, {}).get("aliases", {}).get(name, {})
else:
ret["comment"] = (
f"Failed to remove alias {name} for index {index} for unknown reasons"
)
else:
ret["comment"] = f"Alias {name} for index {index} is already absent"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret
[docs]
def alias_present(name, indices, hosts=None, profile=None, **kwargs):
"""
Ensure that the named index alias is present.
name
Name of the alias
indices
Name of the index
`filter_`
Optional dict for filters as per
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
index_routing
index_routing
is_write_index
is_write_index
master_timeout
Specify timeout for connection to master
routing
Routing definition
search_routing
search_routing
timeout
Explicit timestamp for the document
**Example:**
.. code-block:: yaml
mytestalias:
elasticsearch.alias_present:
- index: testindex
- filter_:
term:
user: kimchy
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
filter_definition = kwargs.get("filter_")
try:
alias = __salt__["elasticsearch.alias_get"](
aliases=name, indices=indices, hosts=hosts, profile=profile
)
old = {}
if alias:
old = alias.get(indices, {}).get("aliases", {}).get(name, {})
if filter_definition is None:
filter_definition = {}
ret["changes"] = salt.utils.dictdiffer.deep_diff(old, filter_definition)
if ret["changes"] or not filter_definition:
if __opts__["test"]:
if not old:
ret["comment"] = (
f"Alias {name} for index {indices} does not exist and will be created"
)
else:
ret["comment"] = (
f"Alias {name} for index {indices} exists with wrong configuration and will be overridden"
)
ret["result"] = None
else:
output = __salt__["elasticsearch.alias_create"](
alias=name, indices=indices, hosts=hosts, profile=profile, **kwargs
)
if output:
if not old:
ret["comment"] = f"Successfully created alias {name} for index {indices}"
else:
ret["comment"] = f"Successfully replaced alias {name} for index {indices}"
else:
ret["result"] = False
ret["comment"] = f"Cannot create alias {name} for index {indices}, {output}"
else:
ret["comment"] = f"Alias {name} for index {indices} is already present"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret
[docs]
def index_template_absent(name, hosts=None, profile=None):
"""
Ensure that the named index template is absent.
name
Name of the index to remove
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
try:
index_template = __salt__["elasticsearch.index_template_get"](
name=name, hosts=hosts, profile=profile
)
if index_template and name in index_template:
if __opts__["test"]:
ret["comment"] = f"Index template {name} will be removed"
ret["changes"]["old"] = index_template[name]
ret["result"] = None
else:
ret["result"] = __salt__["elasticsearch.index_template_delete"](
name=name, hosts=hosts, profile=profile
)
if ret["result"]:
ret["comment"] = f"Successfully removed index template {name}"
ret["changes"]["old"] = index_template[name]
else:
ret["comment"] = f"Failed to remove index template {name} for unknown reasons"
else:
ret["comment"] = f"Index template {name} is already absent"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret
[docs]
def index_template_present(name, hosts=None, profile=None, check_definition=False, **kwargs):
"""
Ensure that the named index template is present.
name
Name of the index to add
check_definition
If the template already exists and the definition is up to date
source
URL to file specifying template definition. Cannot be used in combination with body.
aliases
Aliases for the index.
create
If true, this request cannot replace or update existing index
templatelastic.
error_trace
error_trace
filter_path
filter_path
flat_settings
Return settings in flat format (default: false)
index_patterns
Array of wildcard expressions used to match the names
of indices during creation.
mappings
Mapping for fields in the index.
master_timeout
Period to wait for a connection to the master node. If
no response is received before the timeout expires, the request fails and
returns an error.
order
Order in which Elasticsearch applielastic this template if index matches
multiple templatelastic. Templatelastic with lower 'order' values are merged first.
Templatelastic with higher 'order' values are merged later, overriding templates
with lower valuelastic.
settings
Configuration options for the index.
timeout
timeout
version
ersion number used to manage index templatelastic externally. This
number is not automatically generated by Elasticsearch.
**Example:**
.. code-block:: yaml
mytestindex2_template:
elasticsearch.index_template_present:
- definition:
template: logstash-*
order: 1
settings:
number_of_shards: 1
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
try:
index_template_exists = __salt__["elasticsearch.index_template_exists"](
name=name, hosts=hosts, profile=profile
)
settings = kwargs.get("settings")
mappings = kwargs.get("mappings")
aliases = kwargs.get("aliases")
if not index_template_exists:
if __opts__["test"]:
ret["comment"] = f"Index template {name} does not exist and will be created"
ret["changes"] = {
"new": {"settings": settings, "mappings": mappings, "aliases": aliases}
}
ret["result"] = None
else:
output = __salt__["elasticsearch.index_template_create"](
name=name, hosts=hosts, profile=profile, **kwargs
)
if output:
ret["comment"] = f"Successfully created index template {name}"
ret["changes"] = {
"new": __salt__["elasticsearch.index_template_get"](
name=name, hosts=hosts, profile=profile
)[name]
}
else:
ret["result"] = False
ret["comment"] = f"Cannot create index template {name}, {output}"
else:
if check_definition:
definition = {"settings": settings, "mappings": mappings, "aliases": aliases}
if isinstance(definition, str):
definition_parsed = salt.utils.json.loads(definition)
else:
definition_parsed = definition
current_template = __salt__["elasticsearch.index_template_get"](
name=name, hosts=hosts, profile=profile
)[name]
# Prune empty keys (avoid false positive diff)
for key in ("mappings", "aliases", "settings"):
if current_template[key] == {} and key not in definition_parsed:
del current_template[key]
diff = salt.utils.dictdiffer.deep_diff(current_template, definition_parsed)
if len(diff) != 0:
if __opts__["test"]:
ret["comment"] = f"Index template {name} exist but need to be updated"
ret["changes"] = diff
ret["result"] = None
else:
output = __salt__["elasticsearch.index_template_create"](
name=name, **kwargs
)
if output:
ret["comment"] = f"Successfully updated index template {name}"
ret["changes"] = diff
else:
ret["result"] = False
ret["comment"] = f"Cannot update index template {name}, {output}"
else:
ret["comment"] = f"Index template {name} is already present and up to date"
else:
ret["comment"] = f"Index template {name} is already present"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret
[docs]
def pipeline_absent(name, hosts=None, profile=None):
"""
Ensure that the named pipeline is absent
name
Name of the pipeline to remove
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
try:
pipeline = __salt__["elasticsearch.pipeline_get"](id_=name, hosts=hosts, profile=profile)
if pipeline and name in pipeline:
if __opts__["test"]:
ret["comment"] = f"Pipeline {name} will be removed"
ret["changes"]["old"] = pipeline[name]
ret["result"] = None
else:
ret["result"] = __salt__["elasticsearch.pipeline_delete"](
id_=name, hosts=hosts, profile=profile
)
if ret["result"]:
ret["comment"] = f"Successfully removed pipeline {name}"
ret["changes"]["old"] = pipeline[name]
else:
ret["comment"] = f"Failed to remove pipeline {name} for unknown reasons"
else:
ret["comment"] = f"Pipeline {name} is already absent"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret
[docs]
def pipeline_present(name, hosts=None, profile=None, **kwargs):
"""
Ensure that the named pipeline is present.
name
Name/ID of the pipeline to add
description
Description of the ingest pipeline.
if_version
Required version for optimistic concurrency control for pipeline updates
master_timeout
Period to wait for a connection to the master node. If
no response is received before the timeout expires, the request fails and
returns an error.
meta
Optional metadata about the ingest pipeline. May have any contents.
This map is not automatically generated by Elasticsearch.
on_failure
Processors to run immediately after a processor failure. Each
processor supports a processor-level on_failure value. If a processor without
an on_failure value fails, Elasticsearch uselastic this pipeline-level parameter
as a fallback. The processors in this parameter run sequentially in the order
specified. Elasticsearch will not attempt to run the pipeline's remaining
processors.
processors
Processors used to perform transformations on documents before
indexing. Processors run sequentially in the order specified.
timeout
Period to wait for a response. If no response is received before
the timeout expires, the request fails and returns an error.
version
Version number used by external systems to track ingest pipelinelastic.
This parameter is intended for external systems only. Elasticsearch does
not use or validate pipeline version numbers.
definition
Required dict for creation parameters as per
https://www.elastic.co/guide/en/elasticsearch/reference/master/pipeline.html
**Example:**
.. code-block:: yaml
test_pipeline:
elasticsearch.pipeline_present:
- description: example pipeline
- processors:
- set:
field: collector_timestamp_millis
value: '{{ '{{' }}_ingest.timestamp{{ '}}' }}'
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
processors = kwargs.get("processors")
description = kwargs.get("description")
definition = {"description": description, "processors": processors}
try:
pipeline = __salt__["elasticsearch.pipeline_get"](id_=name, hosts=hosts, profile=profile)
old = {}
if pipeline and name in pipeline:
old = pipeline[name]
ret["changes"] = salt.utils.dictdiffer.deep_diff(old, definition)
if ret["changes"] or (not description or not processors):
if __opts__["test"]:
if not pipeline:
ret["comment"] = f"Pipeline {name} does not exist and will be created"
else:
ret["comment"] = (
f"Pipeline {name} exists with wrong configuration and will be overridden"
)
ret["result"] = None
else:
output = __salt__["elasticsearch.pipeline_create"](
id_=name, hosts=hosts, profile=profile, **kwargs
)
if output:
if not pipeline:
ret["comment"] = f"Successfully created pipeline {name}"
else:
ret["comment"] = f"Successfully replaced pipeline {name}"
else:
ret["result"] = False
ret["comment"] = f"Cannot create pipeline {name}, {output}"
else:
ret["comment"] = f"Pipeline {name} is already present"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret
[docs]
def script_absent(name, hosts=None, profile=None):
"""
Ensure that the script is absent
name
Name of the script to remove
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
try:
template = __salt__["elasticsearch.script_get"](id_=name, hosts=hosts, profile=profile)
if template:
if __opts__["test"]:
ret["comment"] = f"Search template {name} will be removed"
ret["changes"]["old"] = salt.utils.json.loads(template["template"])
ret["result"] = None
else:
ret["result"] = __salt__["elasticsearch.script_delete"](
id_=name, hosts=hosts, profile=profile
)
if ret["result"]:
ret["comment"] = f"Successfully removed search template {name}"
ret["changes"]["old"] = salt.utils.json.loads(template["template"])
else:
ret["comment"] = f"Failed to remove search template {name} for unknown reasons"
else:
ret["comment"] = f"Search template {name} is already absent"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret
[docs]
def script_present(name, hosts=None, profile=None, **kwargs):
"""
Ensure that the named script is present.
name
Name of the search template to add
**Example:**
.. code-block:: yaml
test_pipeline:
elasticsearch.script_present:
- script:
inline:
size: 10
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
script = kwargs.get("script")
try:
template = __salt__["elasticsearch.script_get"](id_=name, hosts=hosts, profile=profile)
old = {}
if template:
old = salt.utils.json.loads(template["template"])
ret["changes"] = salt.utils.dictdiffer.deep_diff(old, script)
if ret["changes"] or not script:
if __opts__["test"]:
if not template:
ret["comment"] = f"Search template {name} does not exist and will be created"
else:
ret["comment"] = (
f"Search template {name} exists with wrong configuration and will be overridden"
)
ret["result"] = None
else:
output = __salt__["elasticsearch.script_create"](
id_=name, hosts=hosts, profile=profile, **kwargs
)
if output:
if not template:
ret["comment"] = f"Successfully created search template {name}"
else:
ret["comment"] = f"Successfully replaced search template {name}"
else:
ret["result"] = False
ret["comment"] = f"Cannot create search template {name}, {output}"
else:
ret["comment"] = f"Search template {name} is already present"
except Exception as err: # pylint: disable=broad-except
ret["result"] = False
ret["comment"] = str(err)
return ret