Coverage for awsutils / aws_resource_start_stop.py: 88%

87 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-21 13:47 +0900

1# -*- coding: utf-8 -*- 

2'''aws_resource_start_stop module. 

3 

4Copyright ycookjp 

5https://github.com/ycookjp/ 

6 

7''' 

8 

9import os 

10import yaml 

11 

12from .aws_resource_operator import AwsResourceOperatorFactory 

13 

14class AwsResourceStartStopConfig(): 

15 region_name = '' 

16 ''' 

17 Region name 

18 ''' 

19 resource_groups = [] 

20 ''' 

21 Array of EC2 instance id 

22 ''' 

23 access_key_id = None 

24 ''' 

25 IAM user's access key id 

26 ''' 

27 secret_access_key = None 

28 ''' 

29 IAM user's secret access key 

30 ''' 

31 

32def _load_config(script_path: str, configkey): 

33 ''' 

34  

35 Loads configuration file with YAMS format.  

36 Configuration file should be located at same directory of specified 

37 script path, and name should be base name of this script except for 

38 extension is '.yml'. 

39  

40 Args: 

41 script_path (str): script path 

42 configkey (str): configuration key name or list of configuration key 

43 names 

44  

45 Returns: 

46 AwsResourceStartStopConfig: Returns configuration object. 

47  

48 ''' 

49 config_path = os.path.splitext(script_path)[0] + '.yml' 

50 with open(config_path, 'r', encoding='utf-8') as file: 

51 yaml_conf = yaml.load(file, Loader=yaml.SafeLoader) 

52 

53 config = AwsResourceStartStopConfig() 

54 config.region_name = yaml_conf['region_name'] 

55 config.access_key_id = yaml_conf.get('access_key_id') 

56 config.secret_access_key = yaml_conf.get('secret_access_key') 

57 

58 if isinstance(configkey, list): 

59 config.resource_groups = [] 

60 config_dict = {} 

61 for key in configkey: 

62 for resource_group in yaml_conf[key]: 

63 type_name = resource_group.get('type') 

64 instance_ids = resource_group.get('ids') 

65 dict_instance_ids = config_dict.get(type_name) 

66 if dict_instance_ids == None: 

67 config_dict[type_name] = instance_ids 

68 else: 

69 for instance_id in instance_ids: 

70 if dict_instance_ids.count(instance_id) == 0: 70 ↛ 69line 70 didn't jump to line 69 because the condition on line 70 was always true

71 dict_instance_ids.append(instance_id) 

72 for key in list(config_dict): 

73 config.resource_groups.append({'type': key, 'ids': config_dict.get(key)}) 

74 elif isinstance(configkey, str): 74 ↛ 77line 74 didn't jump to line 77 because the condition on line 74 was always true

75 config.resource_groups = yaml_conf[configkey] 

76 

77 return config 

78 

79def _get_action_from_context(context): 

80 ''' 

81  

82 Lambda関数contextオブジェクトからLambda関数の名前を取得し、それを"_"で 

83 区切って分割して2番目の文字列を取得してEC2の開始、取得を区別する文字列 

84 (start/stop)を取得します。 

85  

86 Args: 

87 context: Lambda関数のcontextオブジェクト 

88  

89 Returns: 

90 str: EC2の開始、取得を区別する文字列(start/stop)を取得します。 

91 Lambda関数の名前によっては別の文字列が返されることがあります。 

92  

93 ''' 

94 funcname = context.function_name 

95 info = funcname.split('_', maxsplit=2) 

96 action_name = info[1] 

97 

98 return action_name 

99 

100def _get_configkey_from_context(context): 

101 ''' 

102  

103 Lambda関数contextオブジェクトからLambda関数の名前を取得し、それを"_"で 

104 区切って分割して3番目の文字列を取得して設定ファイルのキー名を取得します。 

105  

106 Args: 

107 context: Lambda関数のcontextオブジェクト 

108  

109 Returns: 

110 str: 設定ファイルのキー名を返します。 

111  

112 ''' 

113 funcname = context.function_name 

114 info = funcname.split('_', maxsplit=2) 

115 configkey = info[2] 

116 

117 return configkey 

118 

119def _get_action_from_event(event): 

120 action_name = event['action']; 

121 

122 return action_name 

123 

124def _get_configkey_from_event(event): 

125 configkey = event['configKey'] 

126 

127 return configkey 

128 

129def start_stop_aws_resources(event, context, use_event=True, script_path=__file__, 

130 access_key_id=None, secret_access_key=None): 

131 ''' 

132 

133 event または context から action ("start" または "stop") と configKey 

134 (インスタンスIDの配列を取得するための設定ファイルのキー、またはキーの配列) 

135 を取得して、インスタンスの開始/停止をします。 

136  

137 use_event 引数が True の場合は、event から action と configKey を取得 

138 します。use_event 引数が False の場合は、context から Lambda 関数の名前を 

139 取得し、そこから action と configKey を取得します。このときは、Lambda関数の 

140 名前は、「ec2_<action>_<configKey>」の形式である必要があります。 

141  

142 引数 access_key_id を指定しない(Noneを指定した)場合は、設定ファイルの 

143 「access_key_id」に設定された値をIAMユーザーのアクセスキーに使用します。 

144 同様に引数 secret_access_key を指定しない(Noneを指定した)場合は、設定ファイルの 

145 「secret_access_key」に指定された値をIAMユーザーのシークレットキーに庄します。 

146  

147 Args: 

148 event: Lambda関数のeventオブジェクトを指定します。 

149 context: Lambda関数のcontextオブジェクトを指定します。 

150 use_event (boolean, optional): event から情報を取得する場合は 

151 True、context から情報を取得する場合は False を指定する 

152 script_path (str, optional): スクリプトのパス 

153 access_key_id (str, optional): IAMユーザーのアクセスキー 

154 secret_access_key (str, optional): IAMユーザーのシークレットキー 

155 client (object, optional): low-lebel client 

156  

157 ''' 

158 

159 try: 

160 error = None 

161 

162 if use_event: 

163 action_name = _get_action_from_event(event) 

164 configkey = _get_configkey_from_event(event) 

165 else: 

166 action_name = _get_action_from_context(context) 

167 configkey = _get_configkey_from_context(context) 

168 

169 config = _load_config(script_path, configkey) 

170 

171 if access_key_id == None: 171 ↛ 173line 171 didn't jump to line 173 because the condition on line 171 was always true

172 access_key_id = config.access_key_id 

173 if secret_access_key == None: 173 ↛ 176line 173 didn't jump to line 176 because the condition on line 173 was always true

174 secret_access_key = config.secret_access_key 

175 

176 for resource_group in config.resource_groups: 

177 operator = AwsResourceOperatorFactory.create( 

178 resource_group['type'], config.region_name, 

179 access_key_id, secret_access_key) 

180 instance_ids = resource_group['ids'] 

181 if action_name == 'start': 181 ↛ 182line 181 didn't jump to line 182 because the condition on line 181 was never true

182 try: 

183 operator.start_resources(instance_ids) 

184 except Exception as e: 

185 if error == None: 

186 error = e 

187 elif action_name == 'stop': 187 ↛ 194line 187 didn't jump to line 194 because the condition on line 187 was always true

188 try: 

189 operator.stop_resources(instance_ids) 

190 except Exception as e: 

191 if error == None: 

192 error = e 

193 else: 

194 raise Exception('Lambda function name error') 

195 

196 if error != None: 

197 raise error 

198 except Exception: 

199 raise