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

72 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-08-30 20:56 -0600

1"""TestPlan Class Definition""" 

2 

3import typing as t 

4import logging 

5from dotmap import DotMap 

6from es_testbed.defaults import TESTPLAN 

7from es_testbed.helpers.utils import build_ilm_policy, prettystr, randomstr 

8 

9logger = logging.getLogger(__name__) 

10 

11 

12class PlanBuilder: 

13 """Plan builder class""" 

14 

15 def __init__( 

16 self, 

17 settings: t.Dict = None, 

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

19 ): 

20 if settings is None: 

21 raise ValueError('Must provide a settings dictionary') 

22 self.settings = settings 

23 logger.debug('SETTINGS: %s', settings) 

24 self._plan = DotMap(TESTPLAN) 

25 logger.debug('INITIAL PLAN: %s', prettystr(self._plan)) 

26 self._plan.cleanup = 'UNSET' # Future use? 

27 if autobuild: 

28 self.setup() 

29 

30 # ## Example settings 

31 # { 

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

33 # 'prefix': 'es-testbed', # The default prefix for everything we create 

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

35 # # Will rollover after creation and filling 1st 

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

37 # # If False, will be overridden with None 

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

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

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

41 # 'enabled': False, 

42 # 'phases': ['hot', 'delete'], 

43 # 'readonly': PHASE # Define readonly action during named PHASE 

44 # 'forcemerge': False, 

45 # 'max_num_segments': 1, 

46 # 'policy': {} # Define full ILM policy in advance. 

47 # } 

48 # 

49 

50 # 

51 # # The index_buildlist 

52 # # The array of indices to build. Needs at least a single element. Importing 

53 # # is expected, but it can be modified or replaced after importing. 

54 # 'index_buildlist': [ 

55 # { 

56 # 'preset': 'NAME', # docgen_preset name, included or otherwise 

57 # 'options': { # kwargs for the generator function 

58 # 'docs': 10, 

59 # 'start_at': 0, 

60 # 'match': True, 

61 # } 

62 # 'target_tier': 'frozen' # Target tier for 1st (oldest) index created 

63 # }, 

64 # { 

65 # 'preset': 'NAME', # docgen_preset name, included or otherwise 

66 # 'options': { # kwargs for the generator function 

67 # 'docs': 10, 

68 # 'start_at': 10, 

69 # 'match': True, 

70 # } 

71 # 'target_tier': 'cold' # Target tier for 2nd index created 

72 # }, 

73 # { 

74 # 'preset': 'NAME', # docgen_preset name, included or otherwise 

75 # 'options': { # kwargs for the generator function 

76 # 'docs': 10, 

77 # 'start_at': 20, 

78 # 'match': True, 

79 # } 

80 # 'target_tier': 'hot' # Target tier for last (newest) index created 

81 # }, 

82 # ] 

83 # } 

84 

85 @property 

86 def plan(self) -> DotMap: 

87 """Return the Plan""" 

88 return self._plan 

89 

90 def _create_lists(self) -> None: 

91 names = [ 

92 'indices', 

93 'data_stream', 

94 'snapshots', 

95 'ilm_policies', 

96 'index_templates', 

97 'component_templates', 

98 ] 

99 for name in names: 

100 self._plan[name] = [] 

101 

102 def setup(self) -> None: 

103 """Do initial setup of the Plan DotMap""" 

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

105 self._create_lists() 

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

107 self.update_rollover_alias() 

108 logger.debug('Rollover alias updated') 

109 self.update_ilm() 

110 logger.debug('FINAL PLAN: %s', prettystr(self._plan.toDict())) 

111 

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

113 """Update the Plan DotMap""" 

114 self._plan.update(**settings) 

115 

116 def update_ilm(self) -> None: 

117 """Update the ILM portion of the Plan DotMap""" 

118 setdefault = False 

119 if 'ilm' not in self._plan: 

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

121 setdefault = True 

122 if isinstance(self._plan.ilm, dict): 

123 _ = DotMap(self._plan.ilm) 

124 self._plan.ilm = _ 

125 if isinstance(self._plan.ilm, DotMap): 

126 if 'enabled' not in self._plan.ilm: 

127 # Override with defaults 

128 logger.debug( 

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

130 ) 

131 setdefault = True 

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

133 if self._plan.ilm: 

134 logger.warning( 

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

136 ) 

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

138 setdefault = True 

139 if setdefault: 

140 logger.debug('Setting defaults for ILM') 

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

142 if self._plan.ilm.enabled: 

143 ilm = self._plan.ilm 

144 if not isinstance(self._plan.ilm.phases, list): 

145 logger.error('Phases is not a list!') 

146 self._plan.ilm.phases = TESTPLAN['ilm']['phases'] 

147 for entity in self._plan.index_buildlist: 

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

149 if not entity['searchable'] in ilm.phases: 

150 ilm.phases.append(entity['searchable']) 

151 logger.debug('ILM = %s', ilm) 

152 logger.debug('self._plan.ilm = %s', self._plan.ilm) 

153 kwargs = { 

154 'phases': ilm.phases, 

155 'forcemerge': ilm.forcemerge, 

156 'max_num_segments': ilm.max_num_segments, 

157 'readonly': ilm.readonly, 

158 'repository': self._plan.repository, 

159 } 

160 logger.debug('KWARGS = %s', kwargs) 

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

162 

163 def update_rollover_alias(self) -> None: 

164 """Update the Rollover Alias value""" 

165 if self._plan.rollover_alias: 

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

167 else: 

168 self._plan.rollover_alias = None