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

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 

7 

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() 

23 

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 # } 

71 

72 @property 

73 def plan(self): 

74 return self._plan 

75 

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] = [] 

81 

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] = [] 

89 

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) 

100 

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)) 

109 

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()) 

121 

122 def update(self, settings: t.Dict) -> None: 

123 self._plan.update(**settings) 

124 

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) 

158 

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