Skip to content

Commit

Permalink
Merge pull request #985 from untergeek/fix/656
Browse files Browse the repository at this point in the history
Add index settings feature, docs, tests
  • Loading branch information
untergeek committed Jun 8, 2017
2 parents cde8cdf + 7bf6a9e commit b97f717
Show file tree
Hide file tree
Showing 14 changed files with 397 additions and 42 deletions.
2 changes: 1 addition & 1 deletion curator/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = '5.1.0.dev0'
__version__ = '5.1.0'

125 changes: 125 additions & 0 deletions curator/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,131 @@ def do_action(self):
except Exception as e:
report_failure(e)

class IndexSettings(object):
def __init__(self, ilo, index_settings={}, ignore_unavailable=False,
preserve_existing=False):
"""
:arg ilo: A :class:`curator.indexlist.IndexList` object
:arg index_settings: A dictionary structure with one or more index
settings to change.
:arg ignore_unavailable: Whether specified concrete indices should be
ignored when unavailable (missing or closed)
:arg preserve_existing: Whether to update existing settings. If set to
``True`` existing settings on an index remain unchanged. The default
is ``False``
"""
verify_index_list(ilo)
if not index_settings:
raise ConfigurationError('Missing value for "index_settings"')
#: Instance variable.
#: The Elasticsearch Client object derived from `ilo`
self.client = ilo.client
#: Instance variable.
#: Internal reference to `ilo`
self.index_list = ilo
#: Instance variable.
#: Internal reference to `index_settings`
self.body = index_settings
#: Instance variable.
#: Internal reference to `ignore_unavailable`
self.ignore_unavailable = ignore_unavailable
#: Instance variable.
#: Internal reference to `preserve_settings`
self.preserve_existing = preserve_existing

self.loggit = logging.getLogger('curator.actions.index_settings')
self._body_check()

def _body_check(self):
# The body only passes the skimpiest of requirements by having 'index'
# as the only root-level key, and having a 'dict' as its value
if len(self.body) == 1:
if 'index' in self.body:
if isinstance(self.body['index'], dict):
return True
raise ConfigurationError(
'Bad value for "index_settings": {0}'.format(self.body))

def _static_settings(self):
return [
'number_of_shards',
'shard',
'codec',
'routing_partition_size',
]

def _dynamic_settings(self):
return [
'number_of_replicas',
'auto_expand_replicas',
'refresh_interval',
'max_result_window',
'max_rescore_window',
'blocks',
'max_refresh_listeners',
'mapping',
'merge',
'translog',
]

def _settings_check(self):
# Detect if even one index is open. Save all found to open_index_list.
open_index_list = []
open_indices = False
for idx in self.index_list.indices:
if self.index_list.index_info[idx]['state'] == 'open':
open_index_list.append(idx)
open_indices = True
for k in self.body['index']:
if k in self._static_settings():
if not self.ignore_unavailable:
if open_indices:
raise ActionError(
'Static Setting "{0}" detected with open indices: '
'{1}. Static settings can only be used with closed '
'indices. Recommend filtering out open indices, '
'or setting ignore_unavailable to True'.format(
k, open_index_list
)
)
elif k in self._dynamic_settings():
# Dynamic settings should be appliable to open or closed indices
# Act here if the case is different for some settings.
pass
else:
self.loggit.warn(
'"{0}" is not a setting Curator recognizes and may or may '
'not work.'.format(k)
)

def do_dry_run(self):
"""
Log what the output would be, but take no action.
"""
show_dry_run(self.index_list, 'indexsettings', **self.body)

def do_action(self):
self._settings_check()
# Ensure that the open indices filter applied in _settings_check()
# didn't result in an empty list (or otherwise empty)
self.index_list.empty_list_check()
self.loggit.info(
'Applying index settings to indices: '
'{0}'.format(self.index_list.indices)
)
try:
index_lists = chunk_index_list(self.index_list.indices)
for l in index_lists:
response = self.client.indices.put_settings(
index=to_csv(l), body=self.body,
ignore_unavailable=self.ignore_unavailable,
preserve_existing=self.preserve_existing
)
self.loggit.debug('PUT SETTINGS RESPONSE: {0}'.format(response))
except Exception as e:
report_failure(e)


class Open(object):
def __init__(self, ilo):
"""
Expand Down
1 change: 1 addition & 0 deletions curator/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
'delete_indices' : DeleteIndices,
'delete_snapshots' : DeleteSnapshots,
'forcemerge' : ForceMerge,
'index_settings' : IndexSettings,
'open' : Open,
'reindex' : Reindex,
'replicas' : Replicas,
Expand Down
6 changes: 6 additions & 0 deletions curator/defaults/option_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ def include_global_state(action):
default = True
return { Optional('include_global_state', default=default): Any(bool, All(Any(str, unicode), Boolean())) }

def index_settings():
return { Required('index_settings'): {'index': dict} }

def indices():
return { Optional('indices', default=None): Any(None, list) }

Expand Down Expand Up @@ -93,6 +96,9 @@ def new_index():
def partial():
return { Optional('partial', default=False): Any(bool, All(Any(str, unicode), Boolean())) }

def preserve_existing():
return { Optional('preserve_existing', default=False): Any(bool, All(Any(str, unicode), Boolean())) }

def refresh():
return { Optional('refresh', default=True): Any(bool, All(Any(str, unicode), Boolean())) }

Expand Down
1 change: 1 addition & 0 deletions curator/defaults/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def index_actions():
'create_index',
'delete_indices',
'forcemerge',
'index_settings',
'open',
'reindex',
'replicas',
Expand Down
5 changes: 5 additions & 0 deletions curator/validators/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ def action_specific(action):
option_defaults.delay(),
option_defaults.max_num_segments(),
],
'index_settings' : [
option_defaults.index_settings(),
option_defaults.ignore_unavailable(),
option_defaults.preserve_existing(),
],
'open' : [],
'reindex' : [
option_defaults.request_body(),
Expand Down
6 changes: 5 additions & 1 deletion docs/Changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
Changelog
=========

5.1.0 (? ? ?)
5.1.0 (8 June 2017)

**New Features**

* Index Settings are here! First requested as far back as #160, it's been
requested in various forms culminating in #656. The official documentation
addresses the usage. (untergeek)
* Remote reindex now adds the ability to migrate from one cluster to another,
preserving the index names, or optionally adding a prefix and/or a suffix.
The official documentation shows you how. (untergeek)
* Added support for naming rollover indices. #970 (jurajseffer)
* Testing against ES 5.4.1, 5.3.3

**Bug Fixes**
Expand Down

0 comments on commit b97f717

Please sign in to comment.