Coverage for src/es_testbed/classes/testplan.py: 66%

68 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-04-23 13:32 -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 

9 

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.update_settings(settings) 

27 self.logger.debug('settings = %s', self.asdict) 

28 self.update_ilm() 

29 if not self.entities: 29 ↛ exitline 29 didn't return from function '__init__', because the condition on line 29 was never false

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

31 self.make_default_entities() 

32 

33 ### Example settings 

34 # settings={ 

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

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

37 # 'rollover_alias': True, # Only respected if 'type' == 'indices'. 

38 # # Will rollover after creation and filling 

39 # 'uniq': 'my-unique-str', # If not provided, randomstr(length=8, lowercase=True) 

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

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

42 # 'forcemerge': False, 

43 # 'max_num_segments': 1, 

44 # 'repository': None, 

45 # } 

46 # 

47 # # If these keys aren't specified per entity, then all entities will get this 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 much for 

58 # # alias-backed indices or data_streams 

59 # 'entities': [ 

60 # { 

61 # 'docs': 10, 

62 # 'match': True, 

63 # 'searchable': 'frozen' 

64 # }, 

65 # { 

66 # 'docs': 10, 

67 # 'match': False, 

68 # 'searchable': 'cold', 

69 # }, 

70 # { 

71 # 'docs': 10, 

72 # 'match': True, 

73 # 'searchable': 'frozen' 

74 # }, 

75 # ] 

76 # } 

77 def add_entity( 

78 self, 

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

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

81 searchable: t.Optional[str] = None 

82 ) -> None: 

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

84 if searchable: 84 ↛ 85line 84 didn't jump to line 85, because the condition on line 84 was never true

85 entity['searchable'] = searchable 

86 self.entities.append(entity) 

87 

88 def make_default_entities(self) -> None: 

89 if self.settings and isinstance(self.settings, dict): 89 ↛ 92line 89 didn't jump to line 92, because the condition on line 89 was never false

90 if 'defaults' in self.settings: 90 ↛ 92line 90 didn't jump to line 92, because the condition on line 90 was never false

91 defs = self.settings['defaults'] 

92 kwargs = {'docs': defs['docs'], 'match': defs['match'], 'searchable': defs['searchable']} 

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

94 self.add_entity(**kwargs) 

95 self.logger.debug('Created %s entities', len(self.entities)) 

96 

97 def update_ilm(self) -> None: 

98 if self.use_ilm(): 

99 self.ilm = IlmBuilder() # Set defaults 

100 for k,v in self.settings['ilm'].items(): 100 ↛ 101line 100 didn't jump to line 101, because the loop on line 100 never started

101 self.logger.debug('IlmBuilder.%s = %s', k, v) 

102 setattr(self.ilm, k, v) 

103 # If cold or frozen tiers weren't included in settings['ilm']['tiers'] 

104 # we manually correct here 

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

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

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

108 self.ilm.tiers.append(entity['searchable']) 

109 self.logger.debug('ILM settings = %s', 

110 self.ilm.asdict if isinstance(self.ilm, IlmBuilder) else self.ilm) 

111 

112 

113 def use_ilm(self) -> bool: 

114 use_ilm = False 

115 self.logger.debug('INIT: use_ilm = %s', use_ilm) 

116 if 'ilm' in self.settings: 116 ↛ 126line 116 didn't jump to line 126, because the condition on line 116 was never false

117 if isinstance(self.settings['ilm'], dict): # It's a dictionary, not a bool 

118 self.logger.debug('settings["ilm"] is a dictionary') 

119 use_ilm = True 

120 elif isinstance(self.settings['ilm'], bool): 120 ↛ 123line 120 didn't jump to line 123, because the condition on line 120 was never false

121 self.logger.debug('settings["ilm"] is a bool') 

122 use_ilm = self.settings['ilm'] # Accept whatever the boolean value is 

123 elif self.settings['ilm'] is None: # Empty dict is truthy, but is not None 

124 self.logger.debug('settings["ilm"] is None') 

125 use_ilm = False 

126 if self.entities: 126 ↛ 128line 126 didn't jump to line 128, because the condition on line 126 was never true

127 # Detect if cold or frozen tiers were included in settings['ilm']['tiers'] 

128 for entity in self.entities: 

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

130 self.logger.debug('Test entities contain searchable snapshots') 

131 if not use_ilm: 

132 raise TestPlanMisconfig( 

133 'Searchable entities were found, but ILM is disabled') 

134 self.logger.debug('FINAL: use_ilm = %s', use_ilm) 

135 return use_ilm