Source code for c7n.resources.rdsparamgroup

# Copyright 2017 Capital One Services, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function, unicode_literals

import logging

from botocore.exceptions import ClientError

from c7n.actions import ActionRegistry, BaseAction
from c7n.filters import FilterRegistry
from c7n.manager import resources
from c7n.query import QueryResourceManager
from c7n.utils import (type_schema, local_session, chunks)

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

pg_filters = FilterRegistry('rds-param-group.filters')
pg_actions = ActionRegistry('rds-param-group.actions')


[docs]@resources.register('rds-param-group') class RDSParamGroup(QueryResourceManager): """Resource manager for RDS parameter groups. """
[docs] class resource_type(object): service = 'rds' type = 'pg' enum_spec = ('describe_db_parameter_groups', 'DBParameterGroups', None) name = id = 'DBParameterGroupName' filter_name = None filter_type = None dimension = 'DBParameterGroupName' date = None
filter_registry = pg_filters action_registry = pg_actions
pg_cluster_filters = FilterRegistry('rds-cluster-param-group.filters') pg_cluster_actions = ActionRegistry('rds-cluster-param-group.actions')
[docs]@resources.register('rds-cluster-param-group') class RDSClusterParamGroup(QueryResourceManager): """ Resource manager for RDS cluster parameter groups. """
[docs] class resource_type(object): service = 'rds' type = 'cluster-pg' enum_spec = ('describe_db_cluster_parameter_groups', 'DBClusterParameterGroups', None) name = id = 'DBClusterParameterGroupName' filter_name = None filter_type = None dimension = 'DBClusterParameterGroupName' date = None
filter_registry = pg_cluster_filters action_registry = pg_cluster_actions
[docs]class PGMixin(object):
[docs] def get_pg_name(self, pg): return pg['DBParameterGroupName']
[docs]class PGClusterMixin(object):
[docs] def get_pg_name(self, pg): return pg['DBClusterParameterGroupName']
[docs]class Copy(BaseAction): schema = type_schema( 'copy', **{ 'required': ['name'], 'name': {'type': 'string'}, 'description': {'type': 'string'}, } )
[docs] def process(self, param_groups): client = local_session(self.manager.session_factory).client('rds') for param_group in param_groups: name = self.get_pg_name(param_group) copy_name = self.data.get('name') copy_desc = self.data.get('description', 'Copy of {}'.format(name)) self.do_copy(client, name, copy_name, copy_desc) self.log.info('Copied RDS parameter group %s to %s', name, copy_name)
[docs]@pg_actions.register('copy') class PGCopy(PGMixin, Copy): """ Action to copy an RDS parameter group. :example: .. code-block:: yaml policies: - name: rds-param-group-copy resource: rds-param-group filters: - DBParameterGroupName: original_pg_name actions: - type: copy name: copy_name """ permissions = ('rds:CopyDBParameterGroup',)
[docs] def do_copy(self, client, name, copy_name, desc): client.copy_db_parameter_group( SourceDBParameterGroupIdentifier=name, TargetDBParameterGroupIdentifier=copy_name, TargetDBParameterGroupDescription=desc )
[docs]@pg_cluster_actions.register('copy') class PGClusterCopy(PGClusterMixin, Copy): """ Action to copy an RDS cluster parameter group. :example: .. code-block:: yaml policies: - name: rds-cluster-param-group-copy resource: rds-cluster-param-group filters: - DBClusterParameterGroupName: original_cluster_pg_name actions: - type: copy name: copy_name """ permissions = ('rds:CopyDBClusterParameterGroup',)
[docs] def do_copy(self, client, name, copy_name, desc): client.copy_db_cluster_parameter_group( SourceDBClusterParameterGroupIdentifier=name, TargetDBClusterParameterGroupIdentifier=copy_name, TargetDBClusterParameterGroupDescription=desc )
[docs]class Delete(BaseAction): schema = type_schema('delete')
[docs] def process(self, param_groups): client = local_session(self.manager.session_factory).client('rds') for param_group in param_groups: name = self.get_pg_name(param_group) try: self.do_delete(client, name) except ClientError as e: if e.response['Error']['Code'] == 'DBParameterGroupNotFoundFault': self.log.warning('RDS parameter group %s already deleted', name) continue raise self.log.info('Deleted RDS parameter group: %s', name)
[docs]@pg_actions.register('delete') class PGDelete(PGMixin, Delete): """Action to delete an RDS parameter group :example: .. code-block:: yaml policies: - name: rds-param-group-delete resource: rds-param-group filters: - DBParameterGroupName: pg_name actions: - type: delete """ permissions = ('rds:DeleteDBParameterGroup',)
[docs] def do_delete(self, client, name): client.delete_db_parameter_group(DBParameterGroupName=name)
[docs]@pg_cluster_actions.register('delete') class PGClusterDelete(PGClusterMixin, Delete): """Action to delete an RDS cluster parameter group :example: .. code-block:: yaml policies: - name: rds-cluster-param-group-delete resource: rds-cluster-param-group filters: - DBClusterParameterGroupName: cluster_pg_name actions: - type: delete """ permissions = ('rds:DeleteDBClusterParameterGroup',)
[docs] def do_delete(self, client, name): client.delete_db_cluster_parameter_group(DBClusterParameterGroupName=name)
[docs]class Modify(BaseAction): schema = type_schema( 'modify', **{ 'required': ['params'], 'params': { 'type': 'array', 'items': { 'type': 'object', 'required': ['name', 'value'], 'name': {'type': 'string'}, 'value': {'type': 'string'}, 'apply-method': {'type': 'string', 'enum': ['immediate', 'pending-reboot']} }, }, } )
[docs] def process(self, param_groups): client = local_session(self.manager.session_factory).client('rds') params = [] for param in self.data.get('params', []): params.append({ 'ParameterName': param['name'], 'ParameterValue': param['value'], 'ApplyMethod': param.get('apply-method', 'immediate'), }) for param_group in param_groups: name = self.get_pg_name(param_group) # Fetch the existing parameters for this DB, so we only try to change the ones that are # different. cur_params = self.get_current_params(client, name) changed_params = [] for param in params: param_name = param['ParameterName'] if (param_name not in cur_params or cur_params[param_name]['ParameterValue'] != param['ParameterValue']): changed_params.append(param) # Can only do 20 elements at a time per docs, so if we have more than that we will # break it into multiple requests: # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.modify_db_parameter_group for param_set in chunks(changed_params, 5): self.do_modify(client, name, param_set) self.log.info('Modified RDS parameter group %s (%i parameters changed, %i unchanged)', name, len(changed_params), len(params) - len(changed_params))
[docs]@pg_actions.register('modify') class PGModify(PGMixin, Modify): """Action to modify an RDS parameter group :example: .. code-block:: yaml policies: - name: rds-param-group-modify resource: rds-param-group filters: - DBParameterGroupName: pg_name actions: - type: modify params: - name: autocommit value: "1" - name: max_connections value: "100" """ permissions = ('rds:DescribeDBParameters', 'rds:ModifyDBParameterGroup')
[docs] def get_current_params(self, client, name): params = client.describe_db_parameters(DBParameterGroupName=name) return {x['ParameterName']: { 'ParameterValue': x.get('ParameterValue'), 'ApplyMethod': x['ApplyMethod']} for x in params.get('Parameters', [])}
[docs] def do_modify(self, client, name, params): client.modify_db_parameter_group(DBParameterGroupName=name, Parameters=params)
[docs]@pg_cluster_actions.register('modify') class PGClusterModify(PGClusterMixin, Modify): """Action to modify an RDS cluster parameter group :example: .. code-block:: yaml policies: - name: rds-cluster-param-group-modify resource: rds-cluster-param-group filters: - DBClusterParameterGroupName: cluster_pg_name actions: - type: modify params: - name: lower_case_table_names value: "1" - name: master_verify_checksum value: "1" """ permissions = ('rds:DescribeDBClusterParameters', 'rds:ModifyDBClusterParameterGroup')
[docs] def get_current_params(self, client, name): params = client.describe_db_cluster_parameters(DBClusterParameterGroupName=name) return {x['ParameterName']: { 'ParameterValue': x.get('ParameterValue'), 'ApplyMethod': x['ApplyMethod']} for x in params.get('Parameters', [])}
[docs] def do_modify(self, client, name, params): client.modify_db_cluster_parameter_group( DBClusterParameterGroupName=name, Parameters=params )