Coverage for curator/actions/allocation.py: 100%

1"""Allocation action class"""

2 import logging

3# pylint: disable=import-error

4 from curator.exceptions import MissingArgument

5 from curator.helpers.testers import verify_index_list

6 from curator.helpers.waiters import wait_for_it

7 from curator.helpers.utils import chunk_index_list, report_failure, show_dry_run, to_csv

8

9 class Allocation:

10 """Allocation Action Class"""

11 def __init__(

12 self, ilo, key=None, value=None, allocation_type='require', wait_for_completion=False,

13 wait_interval=3, max_wait=-1

14 ):

15 """

16 :param ilo: An IndexList Object

17 :param key: An arbitrary metadata attribute key. Must match the key assigned to at least

18 :param value: An arbitrary metadata attribute value. Must correspond to values associated

19 :param allocation_type: Type of allocation to apply. Default is ``require``

20 :param wait_for_completion: Wait for completion before returning.

21 :param wait_interval: Seconds to wait between completion checks.

22 :param max_wait: Maximum number of seconds to ``wait_for_completion``

23

24 :type ilo: :py:class:`~.curator.indexlist.IndexList`

25 :type key: str

26 :type value: str

27 :type allocation_type: str

28 :type wait_for_completion: bool

29 :type wait_interval: int

30 :type max_wait: int

31

32 .. note::

33 See more about `shard allocation filtering </https://www.elastic.co/guide/en/elasticsearch/reference/8.6/shard-allocation-filtering.html>`_.

34 """

35 verify_index_list(ilo)

36 if not key:

37 raise MissingArgument('No value for "key" provided')

38 if allocation_type not in ['require', 'include', 'exclude']:

39 raise ValueError(

40 f'{allocation_type} is an invalid allocation_type. Must be one of "require", '

41 '"include", "exclude".'

42 )

43 #: The :py:class:`~.curator.indexlist.IndexList` object passed as ``ilo``

44 self.index_list = ilo

45 #: The :py:class:`~.elasticsearch.Elasticsearch` client object derived from

46 #: :py:attr:`index_list`

47 self.client = ilo.client

48 self.loggit = logging.getLogger('curator.actions.allocation')

49 bkey = f'index.routing.allocation.{allocation_type}.{key}'

50 #: Populated at instance creation time. Value is built from the passed params

51 #: ``allocation_type``, ``key``, and ``value``, e.g.

52 #: ``index.routing.allocation.allocation_type.key.value``

53 self.settings = {bkey : value}

54 #: Object attribute that gets the value of param ``wait_for_completion``

55 self.wfc = wait_for_completion

56 #: Object attribute that gets the value of param ``wait_interval``

57 self.wait_interval = wait_interval

58 #: Object attribute that gets the value of param ``max_wait``

59 self.max_wait = max_wait

60

61 def do_dry_run(self):

62 """Log what the output would be, but take no action."""

63 show_dry_run(self.index_list, 'allocation', settings=self.settings)

64

65 def do_action(self):

66 """

67 :py:meth:`~.elasticsearch.client.IndicesClient.put_settings` to indices in

68 :py:attr:`index_list` with :py:attr:`settings`.

69 """

70 self.loggit.debug(

71 'Cannot get change shard routing allocation of closed indices. '

72 'Omitting any closed indices.'

73 )

74 self.index_list.filter_closed()

75 self.index_list.empty_list_check()

76 self.loggit.info(

77 'Updating %s selected indices: %s', len(self.index_list.indices),

78 self.index_list.indices

79 )

80 self.loggit.info('Updating index setting %s', self.settings)

81 try:

82 index_lists = chunk_index_list(self.index_list.indices)

83 for lst in index_lists:

84 self.client.indices.put_settings(

85 index=to_csv(lst), settings=self.settings

86 )

87 if self.wfc:

88 self.loggit.debug(

89 'Waiting for shards to complete relocation for indices: %s', to_csv(lst))

90 wait_for_it(

91 self.client, 'allocation',

92 wait_interval=self.wait_interval, max_wait=self.max_wait

93 )

94 # pylint: disable=broad-except

95 except Exception as err:

96 report_failure(err)