Coverage for /Users/buh/.pyenv/versions/3.12.2/envs/es-testbed/lib/python3.12/site-packages/es_testbed/classes/plan.py: 84%
83 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-24 22:41 -0600
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-24 22:41 -0600
1"""TestPlan Class Definition"""
2import typing as t
3from dotmap import DotMap
4from es_testbed.defaults import TESTPLAN
5from es_testbed.helpers.utils import build_ilm_policy, getlogger, randomstr
6# pylint: disable=missing-docstring
8class PlanBuilder:
9 def __init__(
10 self,
11 settings: t.Dict = None,
12 default_entities: bool = True,
13 autobuild: t.Optional[bool] = True,
14 ):
15 self.logger = getlogger('es_testbed.PlanBuilder')
16 self.default_entities = default_entities
17 if settings is None: 17 ↛ 18line 17 didn't jump to line 18, because the condition on line 17 was never true
18 settings = TESTPLAN
19 self.settings = settings
20 self._plan = DotMap(TESTPLAN)
21 if autobuild: 21 ↛ exitline 21 didn't return from function '__init__', because the condition on line 21 was never false
22 self.setup()
24 ### Example settings
25 # settings={
26 # 'type': 'indices', # Default is indices? Or should it be data_streams?
27 # 'prefix': 'es-testbed', # Provide this value as a default
28 # 'rollover_alias': False, # Only respected if 'type' == 'indices'.
29 # # Will rollover after creation and filling 1st index
30 # # If True, will be overridden to value of alias name
31 # # If False, will be overridden with None
32 # 'uniq': 'my-unique-str', # If not provided, randomstr(length=8, lowercase=True)
33 # 'repository': # Only used for cold/frozen tier for snapshots
34 # 'ilm': { # All of these ILM values are defaults
35 # 'enabled': False,
36 # 'tiers': ['hot', 'delete'],
37 # 'forcemerge': False,
38 # 'max_num_segments': 1,
39 # }
40 #
41 ## If these keys aren't specified per entity, then all entities will get this treatment
42 ## EXCEPT for the is_write_index for aliases and data_streams
43 #
44 # 'defaults': {
45 # 'entity_count': 3,
46 # 'docs': 10,
47 # 'match': True,
48 # 'searchable': tier...
49 # }
50 #
51 ## Manually specifying entities makes sense for individual indices, but not so much for
52 ## alias-backed indices or data_streams
53 # 'entities': [
54 # {
55 # 'docs': 10,
56 # 'match': True,
57 # 'searchable': 'frozen'
58 # },
59 # {
60 # 'docs': 10,
61 # 'match': False,
62 # 'searchable': 'cold',
63 # },
64 # {
65 # 'docs': 10,
66 # 'match': True,
67 # 'searchable': 'hot'
68 # },
69 # ]
70 # }
72 @property
73 def plan(self):
74 return self._plan
76 def _create_failsafes(self):
77 self._plan.failsafes = DotMap()
78 items = ['index', 'data_stream', 'snapshot', 'ilm', 'template', 'component', 'entity_type']
79 for i in items:
80 self._plan.failsafes[i] = []
82 def _create_lists(self):
83 names = [
84 'indices', 'data_stream', 'snapshots', 'ilm_policies', 'index_templates',
85 'component_templates', 'entity_mgrs'
86 ]
87 for name in names:
88 self._plan[name] = []
90 def add_entity(
91 self,
92 docs: t.Optional[int] = 10,
93 match: t.Optional[bool] = True,
94 searchable: t.Optional[str] = None
95 ) -> None:
96 entity = {'docs': docs, 'match': match}
97 if searchable:
98 entity['searchable'] = searchable
99 self._plan.entities.append(entity)
101 def make_default_entities(self) -> None:
102 defs = TESTPLAN['defaults'] # Start with defaults
103 if 'defaults' in self._plan: 103 ↛ 105line 103 didn't jump to line 105, because the condition on line 103 was never false
104 defs = self._plan.defaults
105 kwargs = {'docs': defs['docs'], 'match': defs['match'], 'searchable': defs['searchable']}
106 for _ in range(0, defs['entity_count']):
107 self.add_entity(**kwargs)
108 self.logger.debug('Plan will create %s (backing) indices', len(self._plan.entities))
110 def setup(self) -> None:
111 self._plan.uniq = randomstr(length=8, lowercase=True)
112 self._create_lists()
113 self._create_failsafes()
114 self.update(self.settings) # Override with settings.
115 self.update_rollover_alias()
116 self.update_ilm()
117 if not self._plan.entities: 117 ↛ 120line 117 didn't jump to line 120, because the condition on line 117 was never false
118 if self.default_entities: 118 ↛ 120line 118 didn't jump to line 120, because the condition on line 118 was never false
119 self.make_default_entities()
120 self.logger.debug('Test Plan: %s', self._plan.pprint())
122 def update(self, settings: t.Dict) -> None:
123 self._plan.update(**settings)
125 def update_ilm(self) -> None:
126 setdefault = False
127 if 'ilm' not in self._plan: 127 ↛ 128line 127 didn't jump to line 128, because the condition on line 127 was never true
128 self.logger.debug('key "ilm" is not in plan')
129 setdefault = True
130 if isinstance(self._plan.ilm, dict):
131 _ = DotMap(self._plan.ilm)
132 self._plan.ilm = _
133 if isinstance(self._plan.ilm, DotMap):
134 if 'enabled' not in self._plan.ilm:
135 # Override with defaults
136 self.logger.debug('plan.ilm does not have key "enabled". Overriding with defaults')
137 setdefault = True
138 elif isinstance(self._plan.ilm, bool): 138 ↛ 143line 138 didn't jump to line 143, because the condition on line 138 was never false
139 if self._plan.ilm: 139 ↛ 140line 139 didn't jump to line 140, because the condition on line 139 was never true
140 self.logger.warning('"plan.ilm: True" is incorrect. Use plan.ilm.enabled: True')
141 self.logger.debug('plan.ilm is boolean. Overriding with defaults')
142 setdefault = True
143 if setdefault:
144 self.logger.debug('Setting defaults for ILM')
145 self._plan.ilm = DotMap(TESTPLAN['ilm'])
146 ilm = self._plan.ilm
147 for entity in self._plan.entities: 147 ↛ 148line 147 didn't jump to line 148, because the loop on line 147 never started
148 if 'searchable' in entity and entity['searchable'] is not None:
149 if not entity['searchable'] in ilm.tiers:
150 ilm.tiers.append(entity['searchable'])
151 kwargs = {
152 'tiers': ilm.tiers,
153 'forcemerge': ilm.forcemerge,
154 'max_num_segments': ilm.max_num_segments,
155 'repository': self._plan.repository,
156 }
157 self._plan.ilm.policy = build_ilm_policy(**kwargs)
159 def update_rollover_alias(self) -> None:
160 if self._plan.rollover_alias:
161 self._plan.rollover_alias = f'{self._plan.prefix}-idx-{self._plan.uniq}'
162 else:
163 self._plan.rollover_alias = None