Beispiel #1
0
    def _process_resource(self, resource):
        model = models.AppServicePlan(location=resource['location'])

        if resource['kind'] == 'functionapp':
            self.log.info("Skipping %s, because this App Service Plan "
                          "is for Consumption Azure Functions." % resource['name'])
            return

        if resource['kind'] == 'linux':
            model.reserved = True

        size = Lookup.extract(self.data.get('size'), resource)

        # get existing tier
        model.sku = models.SkuDescription()
        model.sku.tier = resource['sku']['tier']
        model.sku.name = resource['sku']['name']

        if 'size' in self.data:
            model.sku.tier = ResizePlan.get_sku_name(size)
            model.sku.name = size

        if 'count' in self.data:
            model.sku.capacity = Lookup.extract(self.data.get('count'), resource)

        try:
            self.client.app_service_plans.update(resource['resourceGroup'], resource['name'], model)
        except models.DefaultErrorResponseException as e:
            self.log.error("Failed to resize %s.  Inner exception: %s" %
                           (resource['name'], e.inner_exception))
Beispiel #2
0
    def test_get_value_from_resource_value_not_exists_exception(self):
        resource = {'field_level_1': {'field_level_2': None}}
        source = {
            'type': Lookup.RESOURCE_SOURCE,
            'key': 'field_level_1.field_level_2'
        }

        with self.assertRaises(Exception):
            Lookup.get_value_from_resource(source, resource)
Beispiel #3
0
class Tag(AzureBaseAction):
    """Adds tags to Azure resources

    :example:

    This policy will tag all existing resource groups with a value such as Environment

    .. code-block:: yaml

      policies:
        - name: azure-tag-resourcegroups
          resource: azure.resourcegroup
          description: |
            Tag all existing resource groups with a value such as Environment
          actions:
           - type: tag
             tag: Environment
             value: Test
    """

    schema = utils.type_schema(
        'tag', **{
            'value': Lookup.lookup_type({'type': 'string'}),
            'tag': Lookup.lookup_type({'type': 'string'}),
            'tags': {
                'type': 'object'
            }
        })
    schema_alias = True
    log = logging.getLogger('custodian.azure.tagging.Tag')

    def __init__(self, data=None, manager=None, log_dir=None):
        super(Tag, self).__init__(data, manager, log_dir)

    def validate(self):
        if not self.data.get('tags') and not (self.data.get('tag')
                                              and self.data.get('value')):
            raise FilterValidationError(
                "Must specify either tags or a tag and value")

        if self.data.get('tags') and self.data.get('tag'):
            raise FilterValidationError(
                "Can't specify both tags and tag, choose one")

        return self

    def _process_resource(self, resource):
        new_tags = self._get_tags(resource)
        TagHelper.add_tags(self, resource, new_tags)

    def _get_tags(self, resource):
        return self.data.get('tags') or {
            Lookup.extract(self.data.get('tag'), resource):
            Lookup.extract(self.data.get('value'), resource)
        }
Beispiel #4
0
    def test_lookup_type(self):
        number_schema = {'type': 'number'}
        lookup_default_number = Lookup.lookup_type(number_schema)

        string_schema = {'type': 'string'}
        lookup_default_string = Lookup.lookup_type(string_schema)

        self.assertEqual(number_schema, lookup_default_number['oneOf'][1])
        self.assertEqual(
            number_schema, lookup_default_number['oneOf'][0]['oneOf'][0]
            ['properties']['default-value'])

        self.assertEqual(string_schema, lookup_default_string['oneOf'][1])
        self.assertEqual(
            string_schema, lookup_default_string['oneOf'][0]['oneOf'][0]
            ['properties']['default-value'])
class SetLabelsAction(BaseLabelAction):
    """Set labels to GCP resources

    :example:

    This policy will label all existing resource groups with a value such as environment

    .. code-block:: yaml

      policies:
        - name: gcp-add-multiple-labels
          resource: gcp.instance
          description: |
            Label all existing instances with multiple labels
          actions:
           - type: set-labels
             labels:
               environment: test
               env_type: customer

        - name: gcp-add-label-from-resource-attr
          resource: gcp.instance
          description: |
            Label all existing instances with label taken from resource attribute
          actions:
           - type: set-labels
             labels:
               environment:
                type: resource
                key: name
                default-value: name_not_found

        - name: gcp-remove-label
          resource: gcp.instance
          description: |
            Remove label from all instances
          actions:
           - type: set-labels
             remove: [env]

    """

    schema = type_schema(
        'set-labels',
        labels={'type': 'object', "additionalProperties": Lookup.lookup_type({'type': 'string'})},
        remove={'type': 'array', 'items': {'type': 'string'}})

    def validate(self):
        if not self.data.get('labels') and not self.data.get('remove'):
            raise FilterValidationError("Must specify one of labels or remove")

    def get_labels_to_add(self, resource):
        return {k: Lookup.extract(v, resource) for k, v in self.data.get('labels').items()}

    def get_labels_to_delete(self, resource):
        return self.data.get('remove')
Beispiel #6
0
    def test_get_value_from_resource_value_not_exists(self):
        resource = {'field_level_1': {'field_level_2': None}}
        source = {
            'type': Lookup.RESOURCE_SOURCE,
            'key': 'field_level_1.field_level_2',
            'default-value': 'value_2'
        }

        value = Lookup.get_value_from_resource(source, resource)
        self.assertEqual(value, 'value_2')
Beispiel #7
0
    def test_extract_lookup(self):
        data = {'field_level_1': {'field_level_2': 'value_1'}}
        source = {
            'type': Lookup.RESOURCE_SOURCE,
            'key': 'field_level_1.field_level_2',
            'default-value': 'value_2'
        }

        value = Lookup.extract(source, data)
        self.assertEqual(value, 'value_1')
Beispiel #8
0
 def get_labels_to_add(self, resource):
     return {
         k: Lookup.extract(v, resource)
         for k, v in self.data.get('labels').items()
     }
Beispiel #9
0
 def test_extract_no_lookup(self):
     source = 'mock_string_value'
     value = Lookup.extract(source)
     self.assertEqual(source, value)
Beispiel #10
0
 def _get_tags(self, resource):
     return self.data.get('tags') or {
         Lookup.extract(self.data.get('tag'), resource):
         Lookup.extract(self.data.get('value'), resource)
     }
Beispiel #11
0
class ResizePlan(AzureBaseAction):
    """Resize App Service Plans

    :example:

    Resize App Service Plan to B1 plan with 2 instance.

    .. code-block:: yaml

        policies:
        - name: azure-resize-plan
          resource: azure.appserviceplan
          actions:
           - type: resize-plan
             size: B1
             count: 2


    :example:

    Resize app service plans with on/off hours and resource tagging

    .. code-block:: yaml

        policies:
          - name: on-hours
            resource: azure.appserviceplan
            filters:
              - type: onhour
                default_tz: pt
                onhour: 8
                tag: onoffhour_schedule
            actions:
              - type: resize-plan
                size:
                    type: resource
                    key: tags.on_hour_sku
                    default-value: P1

          - name: off-hours
            resource: azure.appserviceplan
            filters:
              - type: offhour
                default_tz: pt
                offhour: 19
                tag: onoffhour_schedule
            actions:
              - type: tag
                tag: on_hour_sku
                value:
                    type: resource
                    key: sku.name
              - type: resize-plan
                size:
                    size: S1

    """

    schema = {
        'type': 'object',
        'anyOf': [
            {'required': ['size']},
            {'required': ['count']}
        ],
        'properties': {
            'type': {'enum': ['resize-plan']},
            'size': Lookup.lookup_type({'type': 'string',
                                        'enum': ['F1', 'B1', 'B2', 'B3', 'D1',
                                                 'S1', 'S2', 'S3', 'P1', 'P2',
                                                 'P3', 'P1V2', 'P2V2', 'P3v2',
                                                 'PC2', 'PC3', 'PC4']
                                        }),
            'count': Lookup.lookup_type({'type': 'integer'})
        },
        'additionalProperties': False
    }
    schema_alias = True

    def _prepare_processing(self):
        self.client = self.manager.get_client()  # type azure.mgmt.web.WebSiteManagementClient

    def _process_resource(self, resource):
        model = models.AppServicePlan(location=resource['location'])

        if resource['kind'] == 'functionapp':
            self.log.info("Skipping %s, because this App Service Plan "
                          "is for Consumption Azure Functions." % resource['name'])
            return

        if resource['kind'] == 'linux':
            model.reserved = True

        size = Lookup.extract(self.data.get('size'), resource)

        # get existing tier
        model.sku = models.SkuDescription()
        model.sku.tier = resource['sku']['tier']
        model.sku.name = resource['sku']['name']

        if 'size' in self.data:
            model.sku.tier = ResizePlan.get_sku_name(size)
            model.sku.name = size

        if 'count' in self.data:
            model.sku.capacity = Lookup.extract(self.data.get('count'), resource)

        try:
            self.client.app_service_plans.update(resource['resourceGroup'], resource['name'], model)
        except models.DefaultErrorResponseException as e:
            self.log.error("Failed to resize %s.  Inner exception: %s" %
                           (resource['name'], e.inner_exception))

    @staticmethod
    def get_sku_name(tier):
        tier = tier.upper()
        if tier == 'F1':
            return 'FREE'
        elif tier == 'D1':
            return 'SHARED'
        elif tier in ['B1', 'B2', 'B3']:
            return 'BASIC'
        elif tier in ['S1', 'S2', 'S3']:
            return 'STANDARD'
        elif tier in ['P1', 'P2', 'P3']:
            return 'PREMIUM'
        elif tier in ['P1V2', 'P2V2', 'P3V2']:
            return 'PREMIUMV2'
        elif tier in ['PC2', 'PC3', 'PC4']:
            return 'PremiumContainer'
        return None