Source code for c7n_azure.resources.sqldatabase

# Copyright 2018 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 c7n_azure.provider import resources

import abc
import enum
import logging

import six
from c7n_azure.filters import scalar_ops
from c7n_azure.provider import resources
from c7n_azure.resources.arm import ChildArmResourceManager
from c7n_azure.utils import RetentionPeriod, ResourceIdParser, ThreadHelper
from msrestazure.azure_exceptions import CloudError

from c7n.filters import Filter
from c7n.utils import type_schema

log = logging.getLogger('custodian.azure.sqldatabase')


[docs]@resources.register('sqldatabase') class SqlDatabase(ChildArmResourceManager):
[docs] class resource_type(ChildArmResourceManager.resource_type): service = 'azure.mgmt.sql' client = 'SqlManagementClient' enum_spec = ('databases', 'list_by_server', None) parent_manager_name = 'sqlserver'
[docs] @classmethod def extra_args(cls, parent_resource): return {'resource_group_name': parent_resource['resourceGroup'], 'server_name': parent_resource['name']}
[docs]@six.add_metaclass(abc.ABCMeta) class BackupRetentionPolicyFilter(Filter): schema = type_schema( 'backup-retention-policy', **{ 'op': {'enum': list(scalar_ops.keys())} } ) def __init__(self, operations_property, retention_limit, data, manager=None): super(BackupRetentionPolicyFilter, self).__init__(data, manager) self.operations_property = operations_property self.retention_limit = retention_limit
[docs] @abc.abstractmethod def get_retention_from_backup_policy(self, retention_policy): raise NotImplementedError()
[docs] def process(self, resources, event=None): resources, exceptions = ThreadHelper.execute_in_parallel( resources=resources, event=event, execution_method=self._process_resource_set, executor_factory=self.executor_factory, log=log ) if exceptions: raise exceptions[0] return resources
def _process_resource_set(self, resources, event): client = self.manager.get_client() get_operation = getattr(client, self.operations_property).get matched_resources = [] for resource in resources: match = self._process_resource(resource, get_operation) if match: matched_resources.append(resource) return matched_resources def _process_resource(self, resource, get_operation): retention_policy = self._get_backup_retention_policy(resource, get_operation) resource['c7n:{}'.format(self.operations_property)] = retention_policy.as_dict() if retention_policy is None: return self._perform_op(0, self.retention_limit) retention = self.get_retention_from_backup_policy(retention_policy) return retention is not None and self._perform_op(retention, self.retention_limit) def _get_backup_retention_policy(self, resource, get_operation): server_id = resource[self.manager.resource_type.parent_key] resource_group_name = resource.get('resourceGroup') if resource_group_name is None: resource_group_name = ResourceIdParser.get_resource_group(server_id) database_name = resource['name'] server_name = ResourceIdParser.get_resource_name(server_id) try: response = get_operation(resource_group_name, server_name, database_name) except CloudError as e: if e.status_code == 404: response = None else: log.error("Unable to get backup retention policy. " "(resourceGroup: {}, sqlserver: {}, sqldatabase: {})".format( resource_group_name, server_name, database_name)) raise e return response def _perform_op(self, a, b): op = scalar_ops.get(self.data.get('op', 'eq')) return op(a, b)
[docs]@SqlDatabase.filter_registry.register('short-term-backup-retention-policy') class ShortTermBackupRetentionPolicyFilter(BackupRetentionPolicyFilter): """ Filter SQL Databases on the length of their short term backup retention policies. If the database has no backup retention policies, the database is treated as if it has a backup retention of zero days. :example: Find all SQL Databases with a short term retention policy shorter than 2 weeks. .. code-block:: yaml policies: - name: short-term-backup-retention-policy resource: azure.sqldatabase filters: - type: short-term-backup-retention-policy op: lt retention-period-days: 14 """ schema = type_schema( 'short-term-backup-retention-policy', required=['retention-period-days'], rinherit=BackupRetentionPolicyFilter.schema, **{ 'retention-period-days': {'type': 'number'} } ) def __init__(self, data, manager=None): retention_limit = data.get('retention-period-days') super(ShortTermBackupRetentionPolicyFilter, self).__init__( 'backup_short_term_retention_policies', retention_limit, data, manager)
[docs] def get_retention_from_backup_policy(self, retention_policy): return retention_policy.retention_days
[docs]@SqlDatabase.filter_registry.register('long-term-backup-retention-policy') class LongTermBackupRetentionPolicyFilter(BackupRetentionPolicyFilter): """ Filter SQL Databases on the length of their long term backup retention policies. There are 3 backup types for a sql database: weekly, monthly, and yearly. And, each of these backups has a retention period that can specified in units of days, weeks, months, or years. :example: Find all SQL Databases with weekly backup retentions longer than 1 month. .. code-block:: yaml policies: - name: long-term-backup-retention-policy resource: azure.sqldatabase filters: - type: long-term-backup-retention-policy backup-type: weekly op: gt retention-period: 1 retention-period-units: months """
[docs] @enum.unique class BackupType(enum.Enum): weekly = ('weekly_retention',) monthly = ('monthly_retention',) yearly = ('yearly_retention',) def __init__(self, retention_property): self.retention_property = retention_property
[docs] def get_retention_from_backup_policy(self, backup_policy): return getattr(backup_policy, self.retention_property)
def __str__(self): return self.name
schema = type_schema( 'long-term-backup-retention-policy', required=['backup-type', 'retention-period', 'retention-period-units'], rinherit=BackupRetentionPolicyFilter.schema, **{ 'backup-type': {'enum': list([t.name for t in BackupType])}, 'retention-period': {'type': 'number'}, 'retention-period-units': { 'enum': list([u.name for u in RetentionPeriod.Units]) } } ) def __init__(self, data, manager=None): retention_period = data.get('retention-period') self.retention_period_units = RetentionPeriod.Units[ data.get('retention-period-units')] super(LongTermBackupRetentionPolicyFilter, self).__init__( 'backup_long_term_retention_policies', retention_period, data, manager) self.backup_type = LongTermBackupRetentionPolicyFilter.BackupType[self.data.get( 'backup-type')]
[docs] def get_retention_from_backup_policy(self, retention_policy): actual_retention_iso8601 = self.backup_type.get_retention_from_backup_policy( retention_policy) try: actual_duration, actual_duration_units = RetentionPeriod.parse_iso8601_retention_period( actual_retention_iso8601) except ValueError: return None if actual_duration_units.iso8601_symbol != self.retention_period_units.iso8601_symbol: return None return actual_duration