Coverage for /Users/buh/.pyenv/versions/3.12.2/envs/es-testbed/lib/python3.12/site-packages/es_testbed/classes/testplan.py: 71%
69 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 21:55 -0600
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 21:55 -0600
1"""TestPlan Class Definition"""
2import typing as t
3from es_testbed.exceptions import TestPlanMisconfig
4from es_testbed.defaults import TESTPLAN
5from es_testbed.helpers.utils import randomstr, getlogger
6from .args import Args
7from .ilm import IlmBuilder
8# pylint: disable=missing-docstring
10class TestPlan(Args):
11 __test__ = False
12 def __init__(
13 self,
14 settings: t.Dict[str, t.Any] = None,
15 defaults: t.Dict[str, t.Any] = None,
16 default_entities: bool = True,
17 ):
18 if defaults is None: 18 ↛ 20line 18 didn't jump to line 20, because the condition on line 18 was never false
19 defaults = TESTPLAN
20 super().__init__(settings=settings, defaults=defaults)
21 self.logger = getlogger('es_testbed.TestPlan')
22 self.entities = []
23 self.ilm = False
24 self.prefix = None
25 self.uniq = randomstr(length=8, lowercase=True)
26 self.repository = None
27 self.update_settings(settings)
28 self.logger.debug('settings = %s', self.asdict)
29 self.update_ilm()
30 if not self.entities: 30 ↛ exitline 30 didn't return from function '__init__', because the condition on line 30 was never false
31 if default_entities: 31 ↛ exitline 31 didn't return from function '__init__', because the condition on line 31 was never false
32 self.make_default_entities()
34 ### Example settings
35 # settings={
36 # 'type': 'indices', # Default is indices? Or should it be data_streams?
37 # 'prefix': 'es-testbed', # Provide this value as a default
38 # 'rollover_alias': True, # Only respected if 'type' == 'indices'.
39 # # Will rollover after creation and filling
40 # 'uniq': 'my-unique-str', # If not provided, randomstr(length=8, lowercase=True)
41 # 'repository': Only used for snapshots when ILM is not used.
42 # 'ilm': { # All of these ILM values are defaults
43 # 'tiers': ['hot', 'delete'],
44 # 'forcemerge': False,
45 # 'max_num_segments': 1,
46 # 'repository': None,
47 # }
48 #
49 # # If these keys aren't specified per entity, then all entities will get this treatment
50 # # EXCEPT for the is_write_index for aliases and data_streams
51 #
52 # 'defaults': {
53 # 'entity_count': 3,
54 # 'docs': 10,
55 # 'match': True,
56 # 'searchable': tier...
57 # }
59 # # Manually specifying entities makes sense for individual indices, but not so much for
60 # # alias-backed indices or data_streams
61 # 'entities': [
62 # {
63 # 'docs': 10,
64 # 'match': True,
65 # 'searchable': 'frozen'
66 # },
67 # {
68 # 'docs': 10,
69 # 'match': False,
70 # 'searchable': 'cold',
71 # },
72 # {
73 # 'docs': 10,
74 # 'match': True,
75 # 'searchable': 'frozen'
76 # },
77 # ]
78 # }
79 def add_entity(
80 self,
81 docs: t.Optional[int] = 10,
82 match: t.Optional[bool] = True,
83 searchable: t.Optional[str] = None
84 ) -> None:
85 entity = {'docs': docs, 'match': match}
86 if searchable:
87 entity['searchable'] = searchable
88 self.entities.append(entity)
90 def make_default_entities(self) -> None:
91 if self.settings and isinstance(self.settings, dict): 91 ↛ 94line 91 didn't jump to line 94, because the condition on line 91 was never false
92 if 'defaults' in self.settings: 92 ↛ 94line 92 didn't jump to line 94, because the condition on line 92 was never false
93 defs = self.settings['defaults']
94 kwargs = {'docs': defs['docs'], 'match': defs['match'], 'searchable': defs['searchable']}
95 for _ in range(0, defs['entity_count']):
96 self.add_entity(**kwargs)
97 self.logger.debug('Created %s entities', len(self.entities))
99 def update_ilm(self) -> None:
100 if self.use_ilm():
101 self.ilm = IlmBuilder() # Set defaults
102 for k,v in self.settings['ilm'].items():
103 self.logger.debug('IlmBuilder.%s = %s', k, v)
104 setattr(self.ilm, k, v)
105 # If cold or frozen tiers weren't included in settings['ilm']['tiers']
106 # we manually correct here
107 for entity in self.entities: 107 ↛ 108line 107 didn't jump to line 108, because the loop on line 107 never started
108 if 'searchable' in entity and entity['searchable'] is not None:
109 if not entity['searchable'] in self.ilm.tiers:
110 self.ilm.tiers.append(entity['searchable'])
111 self.logger.debug('ILM settings = %s',
112 self.ilm.asdict if isinstance(self.ilm, IlmBuilder) else self.ilm)
115 def use_ilm(self) -> bool:
116 use_ilm = False
117 self.logger.debug('INIT: use_ilm = %s', use_ilm)
118 if 'ilm' in self.settings: 118 ↛ 128line 118 didn't jump to line 128, because the condition on line 118 was never false
119 if isinstance(self.settings['ilm'], dict): # It's a dictionary, not a bool
120 self.logger.debug('settings["ilm"] is a dictionary')
121 use_ilm = True
122 elif isinstance(self.settings['ilm'], bool): 122 ↛ 125line 122 didn't jump to line 125, because the condition on line 122 was never false
123 self.logger.debug('settings["ilm"] is a bool')
124 use_ilm = self.settings['ilm'] # Accept whatever the boolean value is
125 elif self.settings['ilm'] is None: # Empty dict is truthy, but is not None
126 self.logger.debug('settings["ilm"] is None')
127 use_ilm = False
128 if self.entities: 128 ↛ 130line 128 didn't jump to line 130, because the condition on line 128 was never true
129 # Detect if cold or frozen tiers were included in settings['ilm']['tiers']
130 for entity in self.entities:
131 if 'searchable' in entity and entity['searchable'] is not None:
132 self.logger.debug('Test entities contain searchable snapshots')
133 if not use_ilm:
134 raise TestPlanMisconfig(
135 'Searchable entities were found, but ILM is disabled')
136 self.logger.debug('FINAL: use_ilm = %s', use_ilm)
137 return use_ilm