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

1"""Open index action class"""

2 import logging

3 from curator.exceptions import ConfigurationError

4 from curator.helpers.date_ops import parse_date_pattern

5 from curator.helpers.testers import rollable_alias, verify_client_object

6 from curator.helpers.utils import report_failure

7

8 class Rollover:

9 """Rollover Action Class"""

10 def __init__(

11 self, client, name=None, conditions=None, new_index=None, extra_settings=None,

12 wait_for_active_shards=1

13 ):

14 """

15 :param client: A client connection object

16 :param name: The name of the single-index-mapped alias to test for rollover conditions.

17 :param new_index: A new index name

18 :param conditions: Conditions to test

19 :param extra_settings: Must be either ``None``, or a dictionary of settings to apply to the new index on rollover. This is used in place of ``settings`` in the Rollover API, mostly because it's already existent in other places here in Curator

20 :param wait_for_active_shards: The number of shards expected to be active before returning.

21

22 :type client: :py:class:`~.elasticsearch.Elasticsearch`

23 :type name: str

24 :type new_index: str

25 :type conditions: dict

26 :type extra_settings: dict or None

27 :type wait_for_active_shards: int

28 """

29 self.loggit = logging.getLogger('curator.actions.rollover')

30 if not isinstance(conditions, dict):

31 raise ConfigurationError('"conditions" must be a dictionary')

32 else:

33 self.loggit.debug('"conditions" is %s', conditions)

34 if not isinstance(extra_settings, dict) and extra_settings is not None:

35 raise ConfigurationError(

36 '"extra_settings" must be a dictionary or None')

37 verify_client_object(client)

38 #: Object attribute that gets the value of param ``client``.

39 self.client = client

40 #: Object attribute that gets the value of param ``conditions``.

41 self.conditions = conditions

42 #: Object attribute that gets the value of param ``extra_settings``.

43 self.settings = extra_settings

44 #: The :py:func:`~.curator.helpers.date_ops.parse_date_pattern` rendered version of what

45 #: was passed as ``new_index``, or else ``None``

46 self.new_index = parse_date_pattern(new_index) if new_index else new_index

47 #: Object attribute that gets the value of param ``wait_for_active_shards``.

48 self.wait_for_active_shards = wait_for_active_shards

49

50 #: Object attribute that gets the value of param ``name``.

51 self.name = None

52 # Verify that `conditions` and `settings` are good?

53 # Verify that `name` is an alias, and is only mapped to one index.

54 if rollable_alias(client, name):

55 self.name = name

56 else:

57 raise ValueError(

58 f'Unable to perform index rollover with alias '

59 f'"{name}". See previous logs for more details.'

60 )

61

62 def log_result(self, result):

63 """Log the results based on whether the index rolled over or not"""

64 dryrun_string = ''

65 if result['dry_run']:

66 dryrun_string = 'DRY-RUN: '

67 self.loggit.debug('%sResult: %s', dryrun_string, result)

68 rollover_string = (

69 f"{dryrun_string}Old index {result['old_index']} "

70 f"rolled over to new index {result['new_index']}"

71 )

72 # Success is determined by at one condition being True

73 success = False

74 for k in list(result['conditions'].keys()):

75 if result['conditions'][k]:

76 success = True

77 if result['dry_run'] and success: # log "successful" dry-run

78 self.loggit.info(rollover_string)

79 elif result['rolled_over']:

80 self.loggit.info(rollover_string)

81 else:

82 msg = (

83 f"{dryrun_string}Rollover conditions not met. "

84 f"Index {result['old_index']} not rolled over."

85 )

86 self.loggit.info(msg)

87

88 def doit(self, dry_run=False):

89 """

90 This exists solely to prevent having to have duplicate code in both :py:meth:`do_dry_run`

91 and :py:meth:`do_action` because :py:meth:`~.elasticsearch.client.IndicesClient.rollover`

92 has its own ``dry_run`` flag.

93 """

94 return self.client.indices.rollover(

95 alias=self.name,

96 new_index=self.new_index,

97 conditions=self.conditions,

98 settings=self.settings,

99 dry_run=dry_run,

100 wait_for_active_shards=self.wait_for_active_shards,

101 )

102

103 def do_dry_run(self):

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

105 self.loggit.info('DRY-RUN MODE. No changes will be made.')

106 self.log_result(self.doit(dry_run=True))

107

108 def do_action(self):

109 """

110 :py:meth:`~.elasticsearch.client.IndicesClient.rollover` the index referenced by alias

111 :py:attr:`name`

112 """

113 self.loggit.info('Performing index rollover')

114 try:

115 self.log_result(self.doit())

116 # pylint: disable=broad-except

117 except Exception as err:

118 report_failure(err)