Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/c7n/resources/rdsparamgroup.py: 65%

127 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:51 +0000

1# Copyright The Cloud Custodian Authors. 

2# SPDX-License-Identifier: Apache-2.0 

3import logging 

4 

5from botocore.exceptions import ClientError 

6 

7from c7n.actions import ActionRegistry, BaseAction 

8from c7n.filters import FilterRegistry 

9from c7n.manager import resources 

10from c7n.query import QueryResourceManager, TypeInfo 

11from c7n.utils import (type_schema, local_session, chunks) 

12from c7n.tags import universal_augment 

13 

14log = logging.getLogger('custodian.rds-param-group') 

15 

16pg_filters = FilterRegistry('rds-param-group.filters') 

17pg_actions = ActionRegistry('rds-param-group.actions') 

18 

19 

20@resources.register('rds-param-group') 

21class RDSParamGroup(QueryResourceManager): 

22 """Resource manager for RDS parameter groups. 

23 """ 

24 

25 class resource_type(TypeInfo): 

26 

27 service = 'rds' 

28 arn_type = 'pg' 

29 enum_spec = ('describe_db_parameter_groups', 'DBParameterGroups', None) 

30 name = id = 'DBParameterGroupName' 

31 arn = 'DBParameterGroupArn' 

32 dimension = 'DBParameterGroupName' 

33 permissions_enum = ('rds:DescribeDBParameterGroups',) 

34 cfn_type = 'AWS::RDS::DBParameterGroup' 

35 universal_taggable = object() 

36 

37 augment = universal_augment 

38 

39 filter_registry = pg_filters 

40 action_registry = pg_actions 

41 

42 

43pg_cluster_filters = FilterRegistry('rds-cluster-param-group.filters') 

44pg_cluster_actions = ActionRegistry('rds-cluster-param-group.actions') 

45 

46 

47@resources.register('rds-cluster-param-group') 

48class RDSClusterParamGroup(QueryResourceManager): 

49 """ Resource manager for RDS cluster parameter groups. 

50 """ 

51 

52 class resource_type(TypeInfo): 

53 

54 service = 'rds' 

55 arn_type = 'cluster-pg' 

56 arn = 'DBClusterParameterGroupArn' 

57 enum_spec = ('describe_db_cluster_parameter_groups', 'DBClusterParameterGroups', None) 

58 name = id = 'DBClusterParameterGroupName' 

59 dimension = 'DBClusterParameterGroupName' 

60 permissions_enum = ('rds:DescribeDBClusterParameterGroups',) 

61 cfn_type = 'AWS::RDS::DBClusterParameterGroup' 

62 universal_taggable = object() 

63 

64 augment = universal_augment 

65 

66 filter_registry = pg_cluster_filters 

67 action_registry = pg_cluster_actions 

68 

69 

70class PGMixin: 

71 

72 def get_pg_name(self, pg): 

73 return pg['DBParameterGroupName'] 

74 

75 

76class PGClusterMixin: 

77 

78 def get_pg_name(self, pg): 

79 return pg['DBClusterParameterGroupName'] 

80 

81 

82class Copy(BaseAction): 

83 

84 schema = type_schema( 

85 'copy', 

86 **{ 

87 'required': ['name'], 

88 'name': {'type': 'string'}, 

89 'description': {'type': 'string'}, 

90 } 

91 ) 

92 

93 def process(self, param_groups): 

94 client = local_session(self.manager.session_factory).client('rds') 

95 

96 for param_group in param_groups: 

97 name = self.get_pg_name(param_group) 

98 copy_name = self.data.get('name') 

99 copy_desc = self.data.get('description', 'Copy of {}'.format(name)) 

100 self.do_copy(client, name, copy_name, copy_desc) 

101 self.log.info('Copied RDS parameter group %s to %s', name, copy_name) 

102 

103 

104@pg_actions.register('copy') 

105class PGCopy(PGMixin, Copy): 

106 """ Action to copy an RDS parameter group. 

107 

108 :example: 

109 

110 .. code-block:: yaml 

111 

112 policies: 

113 - name: rds-param-group-copy 

114 resource: rds-param-group 

115 filters: 

116 - DBParameterGroupName: original_pg_name 

117 actions: 

118 - type: copy 

119 name: copy_name 

120 """ 

121 

122 permissions = ('rds:CopyDBParameterGroup',) 

123 

124 def do_copy(self, client, name, copy_name, desc): 

125 client.copy_db_parameter_group( 

126 SourceDBParameterGroupIdentifier=name, 

127 TargetDBParameterGroupIdentifier=copy_name, 

128 TargetDBParameterGroupDescription=desc 

129 ) 

130 

131 

132@pg_cluster_actions.register('copy') 

133class PGClusterCopy(PGClusterMixin, Copy): 

134 """ Action to copy an RDS cluster parameter group. 

135 

136 :example: 

137 

138 .. code-block:: yaml 

139 

140 policies: 

141 - name: rds-cluster-param-group-copy 

142 resource: rds-cluster-param-group 

143 filters: 

144 - DBClusterParameterGroupName: original_cluster_pg_name 

145 actions: 

146 - type: copy 

147 name: copy_name 

148 """ 

149 

150 permissions = ('rds:CopyDBClusterParameterGroup',) 

151 

152 def do_copy(self, client, name, copy_name, desc): 

153 client.copy_db_cluster_parameter_group( 

154 SourceDBClusterParameterGroupIdentifier=name, 

155 TargetDBClusterParameterGroupIdentifier=copy_name, 

156 TargetDBClusterParameterGroupDescription=desc 

157 ) 

158 

159 

160class Delete(BaseAction): 

161 

162 schema = type_schema('delete') 

163 

164 def process(self, param_groups): 

165 client = local_session(self.manager.session_factory).client('rds') 

166 

167 for param_group in param_groups: 

168 name = self.get_pg_name(param_group) 

169 try: 

170 self.do_delete(client, name) 

171 except ClientError as e: 

172 if e.response['Error']['Code'] == 'DBParameterGroupNotFoundFault': 

173 self.log.warning('RDS parameter group %s already deleted', name) 

174 continue 

175 raise 

176 self.log.info('Deleted RDS parameter group: %s', name) 

177 

178 

179@pg_actions.register('delete') 

180class PGDelete(PGMixin, Delete): 

181 """Action to delete an RDS parameter group 

182 

183 :example: 

184 

185 .. code-block:: yaml 

186 

187 policies: 

188 - name: rds-param-group-delete 

189 resource: rds-param-group 

190 filters: 

191 - DBParameterGroupName: pg_name 

192 actions: 

193 - type: delete 

194 """ 

195 

196 permissions = ('rds:DeleteDBParameterGroup',) 

197 

198 def do_delete(self, client, name): 

199 client.delete_db_parameter_group(DBParameterGroupName=name) 

200 

201 

202@pg_cluster_actions.register('delete') 

203class PGClusterDelete(PGClusterMixin, Delete): 

204 """Action to delete an RDS cluster parameter group 

205 

206 :example: 

207 

208 .. code-block:: yaml 

209 

210 policies: 

211 - name: rds-cluster-param-group-delete 

212 resource: rds-cluster-param-group 

213 filters: 

214 - DBClusterParameterGroupName: cluster_pg_name 

215 actions: 

216 - type: delete 

217 """ 

218 

219 permissions = ('rds:DeleteDBClusterParameterGroup',) 

220 

221 def do_delete(self, client, name): 

222 client.delete_db_cluster_parameter_group(DBClusterParameterGroupName=name) 

223 

224 

225class Modify(BaseAction): 

226 

227 schema = type_schema( 

228 'modify', 

229 **{ 

230 'required': ['params'], 

231 'params': { 

232 'type': 'array', 

233 'items': { 

234 'type': 'object', 

235 'required': ['name', 'value'], 

236 'name': {'type': 'string'}, 

237 'value': {'type': 'string'}, 

238 'apply-method': {'type': 'string', 'enum': ['immediate', 'pending-reboot']} 

239 }, 

240 }, 

241 } 

242 ) 

243 

244 def process(self, param_groups): 

245 client = local_session(self.manager.session_factory).client('rds') 

246 

247 params = [] 

248 for param in self.data.get('params', []): 

249 params.append({ 

250 'ParameterName': param['name'], 

251 'ParameterValue': param['value'], 

252 'ApplyMethod': param.get('apply-method', 'immediate'), 

253 }) 

254 

255 for param_group in param_groups: 

256 name = self.get_pg_name(param_group) 

257 

258 # Fetch the existing parameters for this DB, so we only try to change the ones that are 

259 # different. 

260 cur_params = self.get_current_params(client, name) 

261 changed_params = [] 

262 for param in params: 

263 param_name = param['ParameterName'] 

264 if (param_name not in cur_params or 

265 cur_params[param_name]['ParameterValue'] != param['ParameterValue']): 

266 changed_params.append(param) 

267 

268 # Can only do 20 elements at a time per docs, so if we have more than that we will 

269 # break it into multiple requests: 

270 # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.modify_db_parameter_group 

271 for param_set in chunks(changed_params, 5): 

272 self.do_modify(client, name, param_set) 

273 

274 self.log.info('Modified RDS parameter group %s (%i parameters changed, %i unchanged)', 

275 name, len(changed_params), len(params) - len(changed_params)) 

276 

277 

278@pg_actions.register('modify') 

279class PGModify(PGMixin, Modify): 

280 """Action to modify an RDS parameter group 

281 

282 :example: 

283 

284 .. code-block:: yaml 

285 

286 policies: 

287 - name: rds-param-group-modify 

288 resource: rds-param-group 

289 filters: 

290 - DBParameterGroupName: pg_name 

291 actions: 

292 - type: modify 

293 params: 

294 - name: autocommit 

295 value: "1" 

296 - name: max_connections 

297 value: "100" 

298 """ 

299 

300 permissions = ('rds:DescribeDBParameters', 'rds:ModifyDBParameterGroup') 

301 

302 def get_current_params(self, client, name): 

303 params = client.describe_db_parameters(DBParameterGroupName=name) 

304 return {x['ParameterName']: { 

305 'ParameterValue': x.get('ParameterValue'), 

306 'ApplyMethod': x['ApplyMethod']} 

307 for x in params.get('Parameters', [])} 

308 

309 def do_modify(self, client, name, params): 

310 client.modify_db_parameter_group(DBParameterGroupName=name, Parameters=params) 

311 

312 

313@pg_cluster_actions.register('modify') 

314class PGClusterModify(PGClusterMixin, Modify): 

315 """Action to modify an RDS cluster parameter group 

316 

317 :example: 

318 

319 .. code-block:: yaml 

320 

321 policies: 

322 - name: rds-cluster-param-group-modify 

323 resource: rds-cluster-param-group 

324 filters: 

325 - DBClusterParameterGroupName: cluster_pg_name 

326 actions: 

327 - type: modify 

328 params: 

329 - name: lower_case_table_names 

330 value: "1" 

331 - name: master_verify_checksum 

332 value: "1" 

333 """ 

334 

335 permissions = ('rds:DescribeDBClusterParameters', 'rds:ModifyDBClusterParameterGroup') 

336 

337 def get_current_params(self, client, name): 

338 params = client.describe_db_cluster_parameters(DBClusterParameterGroupName=name) 

339 return {x['ParameterName']: { 

340 'ParameterValue': x.get('ParameterValue'), 

341 'ApplyMethod': x['ApplyMethod']} 

342 for x in params.get('Parameters', [])} 

343 

344 def do_modify(self, client, name, params): 

345 client.modify_db_cluster_parameter_group( 

346 DBClusterParameterGroupName=name, 

347 Parameters=params 

348 )