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

94 statements  

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

1"""Base TestBed Class""" 

2 

3import typing as t 

4from datetime import datetime, timezone 

5from dotmap import DotMap 

6from es_testbed.exceptions import ResultNotExpected 

7from es_testbed.defaults import NAMEMAPPER 

8from es_testbed.helpers.es_api import delete, get 

9from es_testbed.helpers.utils import getlogger 

10from .plan import PlanBuilder 

11from .entitymgrs import ( 

12 ComponentMgr, 

13 DataStreamMgr, 

14 IlmMgr, 

15 IndexMgr, 

16 SnapshotMgr, 

17 TemplateMgr, 

18) 

19 

20if t.TYPE_CHECKING: 20 ↛ 21line 20 didn't jump to line 21, because the condition on line 20 was never true

21 from elasticsearch8 import Elasticsearch 

22 

23# pylint: disable=broad-exception-caught,R0902 

24 

25 

26class TestBed: 

27 """TestBed Class""" 

28 

29 __test__ = False 

30 

31 def __init__( 

32 self, 

33 client: 'Elasticsearch' = None, 

34 plan: DotMap = None, 

35 autobuild: t.Optional[bool] = False, 

36 ): 

37 self.logger = getlogger('es_testbed.TestBed') 

38 self.client = client 

39 if plan is None: 39 ↛ 40line 39 didn't jump to line 40, because the condition on line 39 was never true

40 plan = PlanBuilder().plan # Use defaults 

41 self.plan = plan 

42 

43 # Set up for tracking 

44 self.ilmmgr = None 

45 self.componentmgr = None 

46 self.templatemgr = None 

47 self.snapshotmgr = None 

48 self.indexmgr = None 

49 self.data_streammgr = None 

50 

51 if autobuild: 51 ↛ 52line 51 didn't jump to line 52, because the condition on line 51 was never true

52 self.setup() 

53 

54 def _fodder_generator(self): 

55 """Method to delete everything matching our pattern(s)""" 

56 items = ['index', 'data_stream', 'snapshot', 'template', 'component', 'ilm'] 

57 for i in items: 

58 if i == 'snapshot' and self.plan.repository is None: 58 ↛ 59line 58 didn't jump to line 59, because the condition on line 58 was never true

59 self.logger.debug('No repository, no snapshots.') 

60 continue 

61 # self.logger.debug('Generating a list of type "%s"', i) 

62 pattern = f'*{self.plan.prefix}-{NAMEMAPPER[i]}-{self.plan.uniq}*' 

63 entities = get(self.client, i, pattern, repository=self.plan.repository) 

64 yield (i, entities) 

65 

66 def ilm_polling(self, interval: t.Union[str, None] = None): 

67 """Return persistent cluster settings to speed up ILM polling during testing""" 

68 return {'indices.lifecycle.poll_interval': interval} 

69 

70 def _while(self, kind: str, item: str) -> bool: 

71 count = 1 

72 success = False 

73 exc = None 

74 while count < 4 and not success: 74 ↛ 84line 74 didn't jump to line 84, because the condition on line 74 was never false

75 try: 

76 success = delete( 

77 self.client, kind, item, repository=self.plan.repository 

78 ) 

79 break 

80 except ResultNotExpected as err: 

81 self.logger.debug('Tried deleting "%s" %s time(s)', item, count) 

82 exc = err 

83 count += 1 

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

85 self.logger.warning( 

86 'Failed to delete "%s" after %s tries. Final error: %s', 

87 item, 

88 count - 1, 

89 exc, 

90 ) 

91 return success 

92 

93 def _erase(self, kind: str, lst: t.Sequence[str]) -> None: 

94 overall_success = True 

95 if not lst: 

96 self.logger.debug('%s: nothing to delete.', kind) 

97 return True 

98 if kind == 'ilm': # ILM policies can't be batch deleted 

99 ilm = [self._while(kind, x) for x in lst] 

100 overall_success = False not in ilm # No False values == True 

101 else: 

102 overall_success = self._while(kind, ','.join(lst)) 

103 return overall_success 

104 

105 def setup(self): 

106 """Setup the instance""" 

107 start = datetime.now(timezone.utc) 

108 self.logger.info('Setting: %s', self.ilm_polling(interval='1s')) 

109 self.client.cluster.put_settings(persistent=self.ilm_polling(interval='1s')) 

110 self.setup_entitymgrs() 

111 end = datetime.now(timezone.utc) 

112 self.logger.info( 

113 'Testbed setup elapsed time: %s', (end - start).total_seconds() 

114 ) 

115 

116 def teardown(self): 

117 """Tear down anything we created""" 

118 start = datetime.now(timezone.utc) 

119 successful = True 

120 for kind, list_of_kind in self._fodder_generator(): 

121 if not self._erase(kind, list_of_kind): 121 ↛ 122line 121 didn't jump to line 122, because the condition on line 121 was never true

122 successful = False 

123 self.logger.info( 

124 'Restoring ILM polling to default: %s', self.ilm_polling(interval=None) 

125 ) 

126 self.client.cluster.put_settings(persistent=self.ilm_polling(interval=None)) 

127 end = datetime.now(timezone.utc) 

128 self.logger.info( 

129 'Testbed teardown elapsed time: %s', (end - start).total_seconds() 

130 ) 

131 if successful: 131 ↛ 134line 131 didn't jump to line 134, because the condition on line 131 was never false

132 self.logger.info('Cleanup successful') 

133 else: 

134 self.logger.error('Cleanup was unsuccessful/incomplete') 

135 self.plan.cleanup = successful 

136 

137 def setup_entitymgrs(self): 

138 """ 

139 Setup each EntityMgr child class 

140 """ 

141 kw = {'client': self.client, 'plan': self.plan} 

142 self.ilmmgr = IlmMgr(**kw) 

143 self.componentmgr = ComponentMgr(**kw) 

144 self.templatemgr = TemplateMgr(**kw) 

145 self.snapshotmgr = SnapshotMgr(**kw) 

146 if self.plan.type == 'indices': 

147 self.indexmgr = IndexMgr(**kw, snapmgr=self.snapshotmgr) 

148 if self.plan.type == 'data_stream': 

149 self.data_streammgr = DataStreamMgr(**kw, snapmgr=self.snapshotmgr)