Coverage for /Users/buh/.pyenv/versions/3.12.2/envs/es-testbed/lib/python3.12/site-packages/es_testbed/classes/plan.py: 71%

78 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-27 20:59 -0600

1"""TestPlan Class Definition""" 

2 

3import typing as t 

4from dotmap import DotMap 

5from es_testbed.defaults import TESTPLAN 

6from es_testbed.helpers.utils import build_ilm_policy, getlogger, randomstr 

7 

8# pylint: disable=missing-docstring 

9 

10 

11class PlanBuilder: 

12 

13 def __init__( 

14 self, 

15 settings: t.Dict = None, 

16 default_entities: bool = True, 

17 autobuild: t.Optional[bool] = True, 

18 ): 

19 self.logger = getlogger('es_testbed.PlanBuilder') 

20 self.default_entities = default_entities 

21 if settings is None: 21 ↛ 22line 21 didn't jump to line 22, because the condition on line 21 was never true

22 settings = TESTPLAN 

23 self.settings = settings 

24 self._plan = DotMap(TESTPLAN) 

25 self._plan.cleanup = 'UNKNOWN' 

26 if autobuild: 26 ↛ exitline 26 didn't return from function '__init__', because the condition on line 26 was never false

27 self.setup() 

28 

29 # ## Example settings 

30 # settings={ 

31 # 'type': 'indices', # Default is indices? Or should it be data_streams? 

32 # 'prefix': 'es-testbed', # Provide this value as a default 

33 # 'rollover_alias': False, # Only respected if 'type' == 'indices'. 

34 # # Will rollover after creation and filling 1st 

35 # # If True, will be overridden to value of alias 

36 # # If False, will be overridden with None 

37 # 'uniq': 'my-unique-str', # If not provided, randomstr() 

38 # 'repository': # Only used for cold/frozen tier for snapshots 

39 # 'ilm': { # All of these ILM values are defaults 

40 # 'enabled': False, 

41 # 'tiers': ['hot', 'delete'], 

42 # 'forcemerge': False, 

43 # 'max_num_segments': 1, 

44 # } 

45 # 

46 # # If these keys aren't specified per entity, then all entities will get this 

47 # # treatment 

48 # # EXCEPT for the is_write_index for aliases and data_streams 

49 # 

50 # 'defaults': { 

51 # 'entity_count': 3, 

52 # 'docs': 10, 

53 # 'match': True, 

54 # 'searchable': tier... 

55 # } 

56 # 

57 # # Manually specifying entities makes sense for individual indices, but not so 

58 # # much for 

59 # # alias-backed indices or data_streams 

60 # 'entities': [ 

61 # { 

62 # 'docs': 10, 

63 # 'match': True, 

64 # 'searchable': 'frozen' 

65 # }, 

66 # { 

67 # 'docs': 10, 

68 # 'match': False, 

69 # 'searchable': 'cold', 

70 # }, 

71 # { 

72 # 'docs': 10, 

73 # 'match': True, 

74 # 'searchable': 'hot' 

75 # }, 

76 # ] 

77 # } 

78 

79 @property 

80 def plan(self) -> DotMap: 

81 return self._plan 

82 

83 def _create_lists(self) -> None: 

84 names = [ 

85 'indices', 

86 'data_stream', 

87 'snapshots', 

88 'ilm_policies', 

89 'index_templates', 

90 'component_templates', 

91 ] 

92 for name in names: 

93 self._plan[name] = [] 

94 

95 def add_entity( 

96 self, 

97 docs: t.Optional[int] = 10, 

98 match: t.Optional[bool] = True, 

99 searchable: t.Optional[str] = None, 

100 ) -> None: 

101 entity = {'docs': docs, 'match': match} 

102 if searchable: 

103 entity['searchable'] = searchable 

104 self._plan.entities.append(entity) 

105 

106 def make_default_entities(self) -> None: 

107 defs = TESTPLAN['defaults'] # Start with defaults 

108 if 'defaults' in self._plan: 108 ↛ 110line 108 didn't jump to line 110

109 defs = self._plan.defaults 

110 kwargs = { 

111 'docs': defs['docs'], 

112 'match': defs['match'], 

113 'searchable': defs['searchable'], 

114 } 

115 for _ in range(0, defs['entity_count']): 

116 self.add_entity(**kwargs) 

117 self.logger.debug( 

118 'Plan will create %s (backing) indices', len(self._plan.entities) 

119 ) 

120 

121 def setup(self) -> None: 

122 self._plan.uniq = randomstr(length=8, lowercase=True) 

123 self._create_lists() 

124 self.update(self.settings) # Override with settings. 

125 self.update_rollover_alias() 

126 self.update_ilm() 

127 if not self._plan.entities: 127 ↛ 130line 127 didn't jump to line 130, because the condition on line 127 was never false

128 if self.default_entities: 128 ↛ 130line 128 didn't jump to line 130, because the condition on line 128 was never false

129 self.make_default_entities() 

130 self.logger.debug('Test Plan: %s', self._plan.pprint()) 

131 

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

133 self._plan.update(**settings) 

134 

135 def update_ilm(self) -> None: 

136 setdefault = False 

137 if 'ilm' not in self._plan: 137 ↛ 138line 137 didn't jump to line 138, because the condition on line 137 was never true

138 self.logger.debug('key "ilm" is not in plan') 

139 setdefault = True 

140 if isinstance(self._plan.ilm, dict): 140 ↛ 143line 140 didn't jump to line 143, because the condition on line 140 was never false

141 _ = DotMap(self._plan.ilm) 

142 self._plan.ilm = _ 

143 if isinstance(self._plan.ilm, DotMap): 143 ↛ 150line 143 didn't jump to line 150, because the condition on line 143 was never false

144 if 'enabled' not in self._plan.ilm: 144 ↛ 146line 144 didn't jump to line 146, because the condition on line 144 was never true

145 # Override with defaults 

146 self.logger.debug( 

147 'plan.ilm does not have key "enabled". Overriding with defaults' 

148 ) 

149 setdefault = True 

150 elif isinstance(self._plan.ilm, bool): 

151 if self._plan.ilm: 

152 self.logger.warning( 

153 '"plan.ilm: True" is incorrect. Use plan.ilm.enabled: True' 

154 ) 

155 self.logger.debug('plan.ilm is boolean. Overriding with defaults') 

156 setdefault = True 

157 if setdefault: 157 ↛ 158line 157 didn't jump to line 158, because the condition on line 157 was never true

158 self.logger.debug('Setting defaults for ILM') 

159 self._plan.ilm = DotMap(TESTPLAN['ilm']) 

160 ilm = self._plan.ilm 

161 for entity in self._plan.entities: 161 ↛ 162line 161 didn't jump to line 162, because the loop on line 161 never started

162 if 'searchable' in entity and entity['searchable'] is not None: 

163 if not entity['searchable'] in ilm.tiers: 

164 ilm.tiers.append(entity['searchable']) 

165 kwargs = { 

166 'tiers': ilm.tiers, 

167 'forcemerge': ilm.forcemerge, 

168 'max_num_segments': ilm.max_num_segments, 

169 'repository': self._plan.repository, 

170 } 

171 self._plan.ilm.policy = build_ilm_policy(**kwargs) 

172 

173 def update_rollover_alias(self) -> None: 

174 if self._plan.rollover_alias: 

175 self._plan.rollover_alias = f'{self._plan.prefix}-idx-{self._plan.uniq}' 

176 else: 

177 self._plan.rollover_alias = None