def test_publish_functions_package_dedicated(
            self, mock_function_package_publish):
        parameters = FunctionAppUtilities.FunctionAppInfrastructureParameters(
            app_insights={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test'
            },
            storage_account={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': self.storage_name
            },
            service_plan={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test',
                'sku_tier': 'Basic'
            },
            function_app_resource_group_name=CONST_GROUP_NAME,
            function_app_name=self.dedicated_function_name)

        FunctionAppUtilities.publish_functions_package(
            parameters, FunctionPackage("TestPolicy"))
        mock_function_package_publish.assert_called_once()
    def test_publish_functions_package_dedicated(self, _1):
        parameters = FunctionAppUtilities.FunctionAppInfrastructureParameters(
            app_insights={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test'
            },
            storage_account={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': self.storage_name
            },
            service_plan={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test',
                'sku_tier': 'Basic'
            },
            function_app={
                'resource_group_name': CONST_GROUP_NAME,
                'name': self.dedicated_function_name})

        package = FunctionPackage("TestPolicy")
        package.pkg = AzurePythonPackageArchive()
        package.close()

        FunctionAppUtilities.publish_functions_package(parameters, package)
    def test_publish_functions_package_consumption(self, _1):
        function_app_name = 'cloud-custodian-test-consumption%s' % self.subscription_id[
            -12:]
        parameters = FunctionAppUtilities.FunctionAppInfrastructureParameters(
            app_insights={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test'
            },
            storage_account={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': self.storage_name
            },
            service_plan={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test',
                'sku_tier': 'dynamic'
            },
            function_app_resource_group_name=CONST_GROUP_NAME,
            function_app_name=function_app_name)

        package = FunctionPackage("TestPolicy")
        package.pkg = AzurePythonPackageArchive()
        package.close()

        FunctionAppUtilities.publish_functions_package(parameters, package)

        # verify app setting updated
        wc = self.session.client('azure.mgmt.web.WebSiteManagementClient')
        app_settings = wc.web_apps.list_application_settings(
            CONST_GROUP_NAME, function_app_name)
        self.assertIsNotNone(
            app_settings.properties['WEBSITE_RUN_FROM_PACKAGE'])
    def test_deploy_function_app_pre_existing_app_fetch_actual_sku_tier(self):
        parameters = FunctionAppUtilities.FunctionAppInfrastructureParameters(
            app_insights={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test'
            },
            storage_account={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': self.storage_name
            },
            service_plan={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test',
                'sku_tier': 'something wrong'
            },
            function_app={
                'name': self.dedicated_function_name,
                'resource_group_name': CONST_GROUP_NAME
            })

        FunctionAppUtilities.deploy_function_app(parameters)
        self.assertEqual(parameters.service_plan['sku_tier'], 'Basic')
    def test_deploy_function_app(self):
        parameters = FunctionAppUtilities.FunctionAppInfrastructureParameters(
            app_insights={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test'
            },
            storage_account={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': self.storage_name
            },
            service_plan={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test',
                'location': 'westus2'
            },
            function_app={
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'custodian-test-app'
            })

        app = FunctionAppUtilities.deploy_function_app(parameters)
        self.assertIsNotNone(app)
Beispiel #6
0
def provision(config):
    log = logging.getLogger('c7n_mailer.azure.deploy')

    function_name = config.get('function_name', 'mailer')
    function_properties = config.get('function_properties', {})

    # service plan is parse first, because its location might be shared with storage & insights
    service_plan = AzureFunctionMode.extract_properties(
        function_properties,
        'servicePlan',
        {
            'name': 'cloud-custodian',
            'location': 'eastus',
            'resource_group_name': 'cloud-custodian',
            'sku_tier': 'Dynamic',  # consumption plan
            'sku_name': 'Y1'
        })

    location = service_plan.get('location', 'eastus')
    rg_name = service_plan['resource_group_name']

    sub_id = local_session(Session).get_subscription_id()
    suffix = StringUtils.naming_hash(rg_name + sub_id)

    storage_account = AzureFunctionMode.extract_properties(
        function_properties, 'storageAccount', {
            'name': 'mailerstorage' + suffix,
            'location': location,
            'resource_group_name': rg_name
        })

    app_insights = AzureFunctionMode.extract_properties(
        function_properties, 'appInsights', {
            'name': service_plan['name'],
            'location': location,
            'resource_group_name': rg_name
        })

    function_app_name = FunctionAppUtilities.get_function_name(
        '-'.join([service_plan['name'], function_name]), suffix)
    FunctionAppUtilities.validate_function_name(function_app_name)

    params = FunctionAppUtilities.FunctionAppInfrastructureParameters(
        app_insights=app_insights,
        service_plan=service_plan,
        storage_account=storage_account,
        function_app_resource_group_name=service_plan['resource_group_name'],
        function_app_name=function_app_name)

    FunctionAppUtilities.deploy_function_app(params)

    log.info("Building function package for %s" % function_app_name)
    package = build_function_package(config, function_name, sub_id)

    log.info("Function package built, size is %dMB" % (package.pkg.size /
                                                       (1024 * 1024)))

    FunctionAppUtilities.publish_functions_package(params, package)
Beispiel #7
0
    def get_function_app_params(self):
        session = local_session(self.policy.session_factory)

        provision_options = self.policy.data['mode'].get('provision-options', {})

        # Service plan is parsed first, location might be shared with storage & insights
        service_plan = AzureFunctionMode.extract_properties(
            provision_options,
            'servicePlan',
            {
                'name': 'cloud-custodian',
                'location': 'eastus',
                'resource_group_name': 'cloud-custodian',
                'sku_tier': 'Dynamic',  # consumption plan
                'sku_name': 'Y1'
            })

        # Metadata used for automatic naming
        location = service_plan.get('location', 'eastus')
        rg_name = service_plan['resource_group_name']
        sub_id = session.get_subscription_id()
        target_sub_id = session.get_function_target_subscription_id()
        function_suffix = StringUtils.naming_hash(rg_name + target_sub_id)
        storage_suffix = StringUtils.naming_hash(rg_name + sub_id)

        storage_account = AzureFunctionMode.extract_properties(
            provision_options,
            'storageAccount',
            {
                'name': self.default_storage_name + storage_suffix,
                'location': location,
                'resource_group_name': rg_name
            })

        app_insights = AzureFunctionMode.extract_properties(
            provision_options,
            'appInsights',
            {
                'name': service_plan['name'],
                'location': location,
                'resource_group_name': rg_name
            })

        function_app_name = FunctionAppUtilities.get_function_name(self.policy_name,
            function_suffix)
        FunctionAppUtilities.validate_function_name(function_app_name)

        params = FunctionAppUtilities.FunctionAppInfrastructureParameters(
            app_insights=app_insights,
            service_plan=service_plan,
            storage_account=storage_account,
            function_app_resource_group_name=service_plan['resource_group_name'],
            function_app_name=function_app_name)

        return params
    def test_is_consumption_plan(self):
        params = FunctionAppUtilities.FunctionAppInfrastructureParameters(
            app_insights=None,
            storage_account=None,
            service_plan={'sku_tier': 'dynamic'},
            function_app_resource_group_name=CONST_GROUP_NAME,
            function_app_name='cloud-custodian-test')

        self.assertTrue(FunctionAppUtilities.is_consumption_plan(params))

        params.service_plan['sku_tier'] = 'other'
        self.assertFalse(FunctionAppUtilities.is_consumption_plan(params))
    def test_deploy_function_app(self):

        parameters = FunctionAppUtilities.FunctionAppInfrastructureParameters(
            app_insights={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test'
            },
            storage_account={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloudcustodiantest'
            },
            service_plan={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test'
            },
            functionapp_name='custodian-test-app')

        app = self.functionapp_util.deploy_dedicated_function_app(parameters)
        self.assertIsNotNone(app)
Beispiel #10
0
    def provision(self):

        # If storage account name is not provided, we'll try to make it unique using
        # resource group name & subscription id values.
        # Can't be a part of constructor because local_session is not working with
        # custodian validate.
        if self.storage_account['name'] == self.default_storage_name:
            rg_name = self.storage_account['resource_group_name']
            sub_id = local_session(
                self.policy.session_factory).get_subscription_id()
            suffix = hashlib.sha256(bytes(rg_name + sub_id,
                                          'utf-8')).hexdigest().lower()[:8]
            self.storage_account['name'] = self.default_storage_name + suffix

        params = FunctionAppUtilities.FunctionAppInfrastructureParameters(
            app_insights=self.app_insights,
            service_plan=self.service_plan,
            storage_account=self.storage_account,
            functionapp_name=self.functionapp_name)

        FunctionAppUtilities().deploy_dedicated_function_app(params)

        self.log.info("Building function package for %s" %
                      self.functionapp_name)

        archive = FunctionPackage(self.policy_name)
        archive.build(self.policy.data)
        archive.close()

        self.log.info("Function package built, size is %dMB" %
                      (archive.pkg.size / (1024 * 1024)))

        if archive.wait_for_status(self.functionapp_name):
            archive.publish(self.functionapp_name)
        else:
            self.log.error(
                "Aborted deployment, ensure Application Service is healthy.")
Beispiel #11
0
def provision(config):
    log = logging.getLogger('c7n_mailer.azure.deploy')

    function_name = config.get('function_name', 'mailer')
    function_properties = config.get('function_properties', {})

    # service plan is parse first, because its location might be shared with storage & insights
    service_plan = AzureFunctionMode.extract_properties(
        function_properties, 'servicePlan', {
            'name': 'cloud-custodian',
            'location': 'westus2',
            'resource_group_name': 'cloud-custodian',
            'sku_name': 'B1',
            'sku_tier': 'Basic'
        })

    location = service_plan.get('location', 'westus2')
    rg_name = service_plan['resource_group_name']

    sub_id = local_session(Session).get_subscription_id()
    suffix = StringUtils.naming_hash(rg_name + sub_id)

    storage_account = AzureFunctionMode.extract_properties(
        function_properties, 'storageAccount', {
            'name': 'mailerstorage' + suffix,
            'location': location,
            'resource_group_name': rg_name
        })

    app_insights = AzureFunctionMode.extract_properties(
        function_properties, 'appInsights', {
            'name': service_plan['name'],
            'location': location,
            'resource_group_name': rg_name
        })

    function_app_name = \
        '-'.join([service_plan['name'], function_name, suffix]) \
        .replace(' ', '-').lower()

    params = FunctionAppUtilities.FunctionAppInfrastructureParameters(
        app_insights=app_insights,
        service_plan=service_plan,
        storage_account=storage_account,
        function_app_resource_group_name=service_plan['resource_group_name'],
        function_app_name=function_app_name)

    FunctionAppUtilities().deploy_dedicated_function_app(params)

    log.info("Building function package for %s" % function_app_name)
    package = build_function_package(config, function_name)

    log.info("Function package built, size is %dMB" % (package.pkg.size /
                                                       (1024 * 1024)))

    client = local_session(Session).client(
        'azure.mgmt.web.WebSiteManagementClient')
    publish_creds = client.web_apps.list_publishing_credentials(
        service_plan['resource_group_name'], function_app_name).result()

    if package.wait_for_status(publish_creds):
        package.publish(publish_creds)
    else:
        log.error("Aborted deployment, ensure Application Service is healthy.")
Beispiel #12
0
def provision(config):
    log = logging.getLogger('c7n_mailer.azure.deploy')

    function_name = config.get('function_name', 'mailer')
    schedule = config.get('function_schedule', '0 */10 * * * *')
    function_properties = config.get('function_properties', {})

    # service plan is parse first, because its location might be shared with storage & insights
    service_plan = AzureFunctionMode.extract_properties(
        function_properties, 'servicePlan', {
            'name': 'cloud-custodian',
            'location': 'westus2',
            'resource_group_name': 'cloud-custodian',
            'sku_name': 'B1',
            'sku_tier': 'Basic'
        })

    location = service_plan.get('location', 'westus2')
    rg_name = service_plan['resource_group_name']

    sub_id = local_session(Session).get_subscription_id()
    suffix = StringUtils.naming_hash(rg_name + sub_id)

    storage_account = AzureFunctionMode.extract_properties(
        function_properties, 'storageAccount', {
            'name': 'mailerstorage' + suffix,
            'location': location,
            'resource_group_name': rg_name
        })

    app_insights = AzureFunctionMode.extract_properties(
        function_properties, 'appInsights', {
            'name': service_plan['name'],
            'location': location,
            'resource_group_name': rg_name
        })

    function_app_name = \
        '-'.join([service_plan['name'], function_name, suffix]) \
        .replace(' ', '-').lower()

    params = FunctionAppUtilities.FunctionAppInfrastructureParameters(
        app_insights=app_insights,
        service_plan=service_plan,
        storage_account=storage_account,
        function_app_resource_group_name=service_plan['resource_group_name'],
        function_app_name=function_app_name)

    function_app = FunctionAppUtilities().deploy_dedicated_function_app(params)

    log.info("Building function package for %s" % function_app_name)

    # Build package
    packager = FunctionPackage(
        function_name, os.path.join(os.path.dirname(__file__), 'function.py'))

    packager.build(None,
                   entry_point=os.path.join(os.path.dirname(__file__),
                                            'handle.py'),
                   extra_modules={'c7n_mailer', 'ruamel'})

    packager.pkg.add_contents(function_name + '/config.json',
                              contents=json.dumps(config))

    packager.pkg.add_contents(function_name + '/function.json',
                              contents=packager.get_function_config({
                                  'mode': {
                                      'type': 'azure-periodic',
                                      'schedule': schedule
                                  }
                              }))
    # Add mail templates
    template_dir = os.path.abspath(
        os.path.join(os.path.dirname(__file__), '../..', 'msg-templates'))

    for t in os.listdir(template_dir):
        with open(os.path.join(template_dir, t)) as fh:
            packager.pkg.add_contents('msg-templates/%s' % t, fh.read())

    packager.close()

    if packager.wait_for_status(function_app):
        packager.publish(function_app)
    else:
        log.error("Aborted deployment, ensure Application Service is healthy.")