def test_publish_functions_package_consumption(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',
                'sku_tier': 'dynamic'
            },
            function_app_resource_group_name=CONST_GROUP_NAME,
            function_app_name='cloud-custodian-test')

        package = FunctionPackage("TestPolicy")
        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, 'cloud-custodian-test')
        self.assertIsNotNone(app_settings.properties['WEBSITE_RUN_FROM_PACKAGE'])
Exemplo n.º 2
0
    def provision(self):
        """Provision any resources needed for the policy."""
        existing_service_plan = self.client.app_service_plans.get(
            self.group_name, self.parameters['servicePlanName']['value'])

        if not existing_service_plan:
            self.template_util.create_resource_group(
                self.group_name, {'location': self.parameters['location']['value']})

            self.template_util.deploy_resource_template(
                self.group_name, 'dedicated_functionapp.json', self.parameters).wait()

        else:
            existing_webapp = self.client.web_apps.get(self.group_name, self.webapp_name)
            if not existing_webapp:
                functionapp_util = FunctionAppUtilities()
                functionapp_util.deploy_webapp(self.webapp_name,
                                               self.group_name, existing_service_plan,
                                               self.parameters['storageName']['value'])
            else:
                self.log.info("Found existing App %s (%s) in group %s" %
                              (self.webapp_name, existing_webapp.location, self.group_name))

        self.log.info("Building function package for %s" % self.webapp_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.webapp_name):
            archive.publish(self.webapp_name)
        else:
            self.log.error("Aborted deployment, ensure Application Service is healthy.")
    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_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'])
Exemplo n.º 5
0
    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_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_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)
Exemplo n.º 8
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 = \
        '-'.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_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)))

    FunctionAppUtilities.publish_functions_package(params, package)
Exemplo n.º 9
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_name = session.get_function_target_subscription_name()
        function_suffix = StringUtils.naming_hash(rg_name + target_sub_name)

        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
Exemplo n.º 10
0
    def provision(self):
        super(AzureEventGridMode, self).provision()
        session = local_session(self.policy.session_factory)

        # queue name is restricted to lowercase letters, numbers, and single hyphens
        queue_name = re.sub(r'(-{2,})+', '-', self.function_params.function_app_name.lower())
        storage_account = self._create_storage_queue(queue_name, session)
        self._create_event_subscription(storage_account, queue_name, session)
        package = self.build_functions_package(queue_name=queue_name)
        FunctionAppUtilities.publish_functions_package(self.function_params, package)
Exemplo n.º 11
0
    def provision(self):
        super(AzureEventGridMode, self).provision()
        session = local_session(self.policy.session_factory)

        # queue name is restricted to lowercase letters, numbers, and single hyphens
        queue_name = re.sub(r'(-{2,})+', '-', self.function_params.function_app_name.lower())
        storage_account = self._create_storage_queue(queue_name, session)
        self._create_event_subscription(storage_account, queue_name, session)
        package = self.build_functions_package(queue_name)
        FunctionAppUtilities.publish_functions_package(self.function_params, package)
Exemplo n.º 12
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_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))
Exemplo n.º 15
0
    def test_function_app_consumption(self):
        # provision storage account
        sa_params = {
            'name': 'custodianaccount47182748',
            'location': self.rg_location,
            'resource_group_name': self.rg_name
        }
        storage_unit = StorageAccountUnit()
        storage_account_id = storage_unit.provision(sa_params).id
        conn_string = FunctionAppUtilities.get_storage_account_connection_string(
            storage_account_id)

        # provision function app
        func_params = {
            'name': 'cc-consumption-47182748',
            # Using different location due to http://go.microsoft.com/fwlink/?LinkId=825764
            'location': 'eastus2',
            'resource_group_name': self.rg_name,
            'app_service_plan_id': None,  # auto-provision a dynamic app plan
            'app_insights_key': None,
            'is_consumption_plan': True,
            'storage_account_connection_string': conn_string
        }
        func_unit = FunctionAppDeploymentUnit()
        func_app = self._validate(func_unit, func_params)

        # verify settings are properly configured
        self.assertEqual(func_app.kind, 'functionapp,linux')
        self.assertTrue(func_app.reserved)
Exemplo n.º 16
0
    def _get_parameters(self, template_util):
        parameters = template_util.get_default_parameters(
            'dedicated_functionapp.parameters.json')

        data = self.policy.data

        updated_parameters = {
            'dockerVersion':
            CONST_DOCKER_VERSION,
            'functionsExtVersion':
            CONST_FUNCTIONS_EXT_VERSION,
            'machineDecryptionKey':
            FunctionAppUtilities.generate_machine_decryption_key()
        }

        if 'mode' in data:
            if 'provision-options' in data['mode']:
                updated_parameters.update(data['mode']['provision-options'])
                if 'servicePlanName' in data['mode']['provision-options']:
                    updated_parameters['name'] = (
                        data['mode']['provision-options']['servicePlanName'] +
                        '-' + data['name']).replace(' ', '-').lower()

                    updated_parameters['storageName'] = (
                        data['mode']['provision-options']['servicePlanName']
                    ).replace('-', '').lower()

        parameters = template_util.update_parameters(parameters,
                                                     updated_parameters)

        return parameters
    def test_function_app_consumption(self):
        # provision storage account
        sa_params = {
            'name': 'custodianaccount47182748',
            'location': 'westus2',
            'resource_group_name': self.rg_name}
        storage_unit = StorageAccountUnit()
        storage_account_id = storage_unit.provision_if_not_exists(sa_params).id
        conn_string = FunctionAppUtilities.get_storage_account_connection_string(storage_account_id)

        # provision function app
        func_params = {
            'name': 'cc-consumption-47182748',
            'location': 'westus',
            'resource_group_name': self.rg_name,
            'app_service_plan_id': None,  # auto-provision a dynamic app plan
            'app_insights_key': None,
            'is_consumption_plan': True,
            'storage_account_connection_string': conn_string
        }
        func_unit = FunctionAppDeploymentUnit()
        func_app = self._validate(func_unit, func_params)

        # verify settings are properly configured
        self.assertEqual(func_app.kind, 'functionapp,linux')
        self.assertTrue(func_app.reserved)
 def test_get_storage_connection_string(self):
     storage_name = 'cloudcustodiantest'
     id = '/subscriptions/%s/resourceGroups/test_functionapp-reqs/providers/Microsoft.Storage' \
          '/storageAccounts/cloudcustodiantest' % local_session(Session).subscription_id
     conn_string = FunctionAppUtilities.get_storage_account_connection_string(
         id)
     self.assertIn('AccountName=%s;' % storage_name, conn_string)
class FunctionAppUtilsTest(BaseTest):
    def setUp(self):
        super(FunctionAppUtilsTest, self).setUp()
        self.functionapp_util = FunctionAppUtilities()

    @arm_template('functionapp-reqs.json')
    def test_get_storage_connection_string(self):
        storage_name = 'cloudcustodiantest'
        conn_string = self.functionapp_util.get_storage_connection_string(
            CONST_GROUP_NAME, storage_name)

        self.assertIn('AccountName=%s;' % storage_name, conn_string)

    @arm_template('functionapp-reqs.json')
    def test_get_application_insights_key_exists(self):
        app_insights_name = 'cloud-custodian-test'
        key = self.functionapp_util.get_application_insights_key(
            CONST_GROUP_NAME, app_insights_name)

        self.assertIsNotNone(key)

    @arm_template('functionapp-reqs.json')
    def test_get_application_insights_key_not_exists(self):
        app_insights_name = 'does-not-exist'
        key = self.functionapp_util.get_application_insights_key(
            CONST_GROUP_NAME, app_insights_name)

        self.assertFalse(key)

    @arm_template('functionapp-reqs.json')
    def test_deploy_webapp(self):
        s = Session()
        web_client = s.client('azure.mgmt.web.WebSiteManagementClient')

        service_plan = web_client.app_service_plans.get(
            CONST_GROUP_NAME, 'cloud-custodian-test')
        self.assertIsNotNone(service_plan)
        webapp_name = 'test-deploy-webapp'
        self.functionapp_util.deploy_webapp(webapp_name,
                                            CONST_GROUP_NAME,
                                            service_plan,
                                            'cloudcustodiantest')

        wep_app = web_client.web_apps.get(CONST_GROUP_NAME, webapp_name)
        self.assertIsNotNone(wep_app)
Exemplo n.º 20
0
    def provision(self):
        if sys.version_info[0] < 3:
            self.log.error(
                "Python 2.7 is not supported for deploying Azure Functions.")
            sys.exit(1)

        self.function_params = self.get_function_app_params()
        FunctionAppUtilities().deploy_dedicated_function_app(
            self.function_params)
class FunctionAppUtilsTest(BaseTest):
    def setUp(self):
        super(FunctionAppUtilsTest, self).setUp()
        self.functionapp_util = FunctionAppUtilities()

    @arm_template('functionapp-reqs.json')
    def test_get_storage_connection_string(self):
        storage_name = 'cloudcustodiantest'
        conn_string = self.functionapp_util.get_storage_connection_string(
            CONST_GROUP_NAME, storage_name)

        self.assertIn('AccountName=%s;' % storage_name, conn_string)

    @arm_template('functionapp-reqs.json')
    def test_get_application_insights_key_exists(self):
        app_insights_name = 'cloud-custodian-test'
        key = self.functionapp_util.get_application_insights_key(
            CONST_GROUP_NAME, app_insights_name)

        self.assertIsNotNone(key)

    @arm_template('functionapp-reqs.json')
    def test_get_application_insights_key_not_exists(self):
        app_insights_name = 'does-not-exist'
        key = self.functionapp_util.get_application_insights_key(
            CONST_GROUP_NAME, app_insights_name)

        self.assertFalse(key)

    @arm_template('functionapp-reqs.json')
    def test_deploy_webapp(self):
        s = Session()
        web_client = s.client('azure.mgmt.web.WebSiteManagementClient')

        service_plan = web_client.app_service_plans.get(
            CONST_GROUP_NAME, 'cloud-custodian-test')
        self.assertIsNotNone(service_plan)
        webapp_name = 'test-deploy-webapp'
        self.functionapp_util.deploy_webapp(webapp_name, CONST_GROUP_NAME,
                                            service_plan, 'cloudcustodiantest')

        wep_app = web_client.web_apps.get(CONST_GROUP_NAME, webapp_name)
        self.assertIsNotNone(wep_app)
Exemplo n.º 22
0
    def provision(self):
        """Provision any resources needed for the policy."""
        template_util = TemplateUtilities()

        parameters = self._get_parameters(template_util)
        group_name = parameters['servicePlanName']['value']
        webapp_name = parameters['name']['value']
        policy_name = self.policy.data['name'].replace(' ', '-').lower()

        existing_service_plan = self.client.app_service_plans.get(
            group_name, parameters['servicePlanName']['value'])

        if not existing_service_plan:
            template_util.create_resource_group(
                group_name, {'location': parameters['location']['value']})

            template_util.deploy_resource_template(
                group_name, 'dedicated_functionapp.json', parameters).wait()

        else:
            existing_webapp = self.client.web_apps.get(group_name, webapp_name)
            if not existing_webapp:
                functionapp_util = FunctionAppUtilities()
                functionapp_util.deploy_webapp(
                    webapp_name, group_name, existing_service_plan,
                    parameters['storageName']['value'])
            else:
                self.log.info(
                    "Found existing App %s (%s) in group %s" %
                    (webapp_name, existing_webapp.location, group_name))

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

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

        if archive.wait_for_status(webapp_name):
            archive.publish(webapp_name)
        else:
            self.log.error(
                "Aborted deployment, ensure Application Service is healthy.")
Exemplo n.º 23
0
    def provision(self):
        # Make sure we have auth data for function provisioning
        session = local_session(self.policy.session_factory)
        session.get_functions_auth_string("")

        self.target_subscription_ids = session.get_function_target_subscription_ids(
        )

        self.function_params = self.get_function_app_params()
        self.function_app = FunctionAppUtilities.deploy_function_app(
            self.function_params)
    def test_get_function_name_replacements(self):
        test_cases = [
            ('test-function-name', 'test-function-name-suffix'),
            ('test_function_name', 'test-function-name-suffix'),
            ('test-function-name123', 'test-function-name123-suffix'),
            ('test-function-name!@#$', 'test-function-name-----suffix')
        ]

        for test_case in test_cases:
            self.assertEqual(test_case[1], FunctionAppUtilities.get_function_name(
                policy_name=test_case[0], suffix='suffix'))
Exemplo n.º 25
0
    def test_get_function_name_replacements(self):
        test_cases = [
            ('test-function-name', 'test-function-name-suffix'),
            ('test_function_name', 'test-function-name-suffix'),
            ('test-function-name123', 'test-function-name123-suffix'),
            ('test-function-name!@#$', 'test-function-name-----suffix')
        ]

        for test_case in test_cases:
            self.assertEqual(test_case[1], FunctionAppUtilities.get_function_name(
                policy_name=test_case[0], suffix='suffix'))
Exemplo n.º 26
0
    def provision(self):
        # Make sure we have auth data for function provisioning
        session = local_session(self.policy.session_factory)
        session.get_functions_auth_string()

        if sys.version_info[0] < 3:
            self.log.error("Python 2.7 is not supported for deploying Azure Functions.")
            sys.exit(1)

        self.function_params = self.get_function_app_params()
        self.function_app = FunctionAppUtilities.deploy_function_app(self.function_params)
    def test_function_app_dedicated(self):
        # provision storage account
        sa_params = {
            'name': 'custodianaccount47182748',
            'location': 'westus2',
            'resource_group_name': self.rg_name
        }
        storage_unit = StorageAccountUnit()
        storage_account_id = storage_unit.provision_if_not_exists(sa_params).id
        conn_string = FunctionAppUtilities.get_storage_account_connection_string(
            storage_account_id)

        # provision app plan
        app_plan_params = {
            'name': 'cloud-custodian-test',
            'location': 'westus2',
            'resource_group_name': self.rg_name,
            'sku_tier': 'Basic',
            'sku_name': 'B1'
        }
        app_plan_unit = AppServicePlanUnit()
        app_plan = app_plan_unit.provision_if_not_exists(app_plan_params)

        # provision function app
        func_app_name = 'cc-dedicated-47182748'
        func_params = {
            'name': func_app_name,
            'location': 'westus',
            'resource_group_name': self.rg_name,
            'app_service_plan_id': app_plan.id,
            'app_insights_key': None,
            'is_consumption_plan': False,
            'storage_account_connection_string': conn_string
        }
        func_unit = FunctionAppDeploymentUnit()
        func_app = self._validate(func_unit, func_params)

        # verify settings are properly configured
        self.assertEquals(func_app.kind, 'functionapp,linux,container')
        self.assertTrue(func_app.reserved)

        wc = self.session.client('azure.mgmt.web.WebSiteManagementClient')

        site_config = wc.web_apps.get_configuration(self.rg_name,
                                                    func_app_name)
        self.assertTrue(site_config.always_on)
        self.assertEquals(site_config.linux_fx_version,
                          FUNCTION_DOCKER_VERSION)

        app_settings = wc.web_apps.list_application_settings(
            self.rg_name, func_app_name)
        self.assertIsNotNone(
            app_settings.properties['MACHINEKEY_DecryptionKey'])
Exemplo n.º 28
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)

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

    FunctionAppUtilities.publish_functions_package(params, package)
Exemplo n.º 29
0
    def provision(self):
        # Make sure we have auth data for function provisioning
        session = local_session(self.policy.session_factory)
        if jmespath.search('mode."provision-options".identity.type',
                           self.policy.data) in (AUTH_TYPE_EMBED, None):
            session.get_functions_auth_string("")

        self.target_subscription_ids = session.get_function_target_subscription_ids(
        )

        self.function_params = self.get_function_app_params()
        self.function_app = FunctionAppUtilities.deploy_function_app(
            self.function_params)
Exemplo n.º 30
0
    def provision(self):
        """Provision any resources needed for the policy."""
        template_util = TemplateUtilities()

        parameters = self._get_parameters(template_util)
        group_name = parameters['servicePlanName']['value']
        webapp_name = parameters['name']['value']
        policy_name = self.policy.data['name'].replace(' ', '-').lower()

        existing_service_plan = self.client.app_service_plans.get(
            group_name, parameters['servicePlanName']['value'])

        if not existing_service_plan:
            template_util.create_resource_group(
                group_name, {'location': parameters['location']['value']})

            template_util.deploy_resource_template(
                group_name, 'dedicated_functionapp.json', parameters).wait()

        else:
            existing_webapp = self.client.web_apps.get(group_name, webapp_name)
            if not existing_webapp:
                functionapp_util = FunctionAppUtilities()
                functionapp_util.deploy_webapp(webapp_name, group_name, existing_service_plan,
                                               parameters['storageName']['value'])
            else:
                self.log.info("Found existing App %s (%s) in group %s" %
                              (webapp_name, existing_webapp.location, group_name))

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

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

        if archive.wait_for_status(webapp_name):
            archive.publish(webapp_name)
        else:
            self.log.error("Aborted deployment, ensure Application Service is healthy.")
Exemplo n.º 31
0
 def test_validate_function_name_length_requirements(self):
     with self.assertRaises(ValueError):
         FunctionAppUtilities.validate_function_name(function_name=None)
     with self.assertRaises(ValueError):
         FunctionAppUtilities.validate_function_name(function_name='')
     with self.assertRaises(ValueError):
         FunctionAppUtilities.validate_function_name(
             function_name='abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn')
 def test_validate_function_name_length_requirements(self):
     with self.assertRaises(ValueError):
         FunctionAppUtilities.validate_function_name(function_name=None)
     with self.assertRaises(ValueError):
         FunctionAppUtilities.validate_function_name(function_name='')
     with self.assertRaises(ValueError):
         FunctionAppUtilities.validate_function_name(
             function_name='abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn')
class FunctionAppUtilsTest(BaseTest):
    def setUp(self):
        super(FunctionAppUtilsTest, self).setUp()
        self.functionapp_util = FunctionAppUtilities()

    @arm_template('functionapp-reqs.json')
    def test_get_storage_connection_string(self):
        storage_name = 'cloudcustodiantest'
        id = '/subscriptions/%s/resourceGroups/test_functionapp-reqs/providers/Microsoft.Storage' \
             '/storageAccounts/cloudcustodiantest' % local_session(Session).subscription_id
        conn_string = FunctionAppUtilities.get_storage_account_connection_string(
            id)
        self.assertIn('AccountName=%s;' % storage_name, conn_string)

    @arm_template('functionapp-reqs.json')
    def test_get_application_insights_key_exists(self):
        insights = AppInsightsUnit().get({
            'name':
            'cloud-custodian-test',
            'resource_group_name':
            CONST_GROUP_NAME
        })

        self.assertIsNotNone(insights)
        self.assertIsNotNone(insights.instrumentation_key)

    @arm_template('functionapp-reqs.json')
    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'
            },
            function_app_resource_group_name=CONST_GROUP_NAME,
            function_app_name='custodian-test-app')

        app = self.functionapp_util.deploy_dedicated_function_app(parameters)
        self.assertIsNotNone(app)
    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': 'cloudcustodiantest'
            },
            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='cloud-custodian-test')

        FunctionAppUtilities.publish_functions_package(parameters, FunctionPackage("TestPolicy"))
        mock_function_package_publish.assert_called_once()
Exemplo n.º 35
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.")
    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': 'cloudcustodiantest'
            },
            service_plan={
                'id': '',
                'resource_group_name': CONST_GROUP_NAME,
                'name': 'cloud-custodian-test',
                'sku_tier': 'something wrong'
            },
            function_app_resource_group_name=CONST_GROUP_NAME,
            function_app_name='cloud-custodian-test')

        FunctionAppUtilities.deploy_function_app(parameters)
        self.assertEqual(parameters.service_plan['sku_tier'], 'Basic')
    def test_function_app_dedicated(self):
        # provision storage account
        sa_params = {
            'name': 'custodianaccount47182748',
            'location': 'westus2',
            'resource_group_name': self.rg_name}
        storage_unit = StorageAccountUnit()
        storage_account_id = storage_unit.provision_if_not_exists(sa_params).id
        conn_string = FunctionAppUtilities.get_storage_account_connection_string(storage_account_id)

        # provision app plan
        app_plan_params = {
            'name': 'cloud-custodian-test',
            'location': 'westus2',
            'resource_group_name': self.rg_name,
            'sku_tier': 'Basic',
            'sku_name': 'B1'}
        app_plan_unit = AppServicePlanUnit()
        app_plan = app_plan_unit.provision_if_not_exists(app_plan_params)

        # provision function app
        func_app_name = 'cc-dedicated-47182748'
        func_params = {
            'name': func_app_name,
            'location': 'westus',
            'resource_group_name': self.rg_name,
            'app_service_plan_id': app_plan.id,
            'app_insights_key': None,
            'is_consumption_plan': False,
            'storage_account_connection_string': conn_string
        }
        func_unit = FunctionAppDeploymentUnit()
        func_app = self._validate(func_unit, func_params)

        # verify settings are properly configured
        self.assertEqual(func_app.kind, 'functionapp,linux,container')
        self.assertTrue(func_app.reserved)

        wc = self.session.client('azure.mgmt.web.WebSiteManagementClient')

        site_config = wc.web_apps.get_configuration(self.rg_name, func_app_name)
        self.assertTrue(site_config.always_on)
        self.assertEqual(site_config.linux_fx_version, FUNCTION_DOCKER_VERSION)

        app_settings = wc.web_apps.list_application_settings(self.rg_name, func_app_name)
        self.assertIsNotNone(app_settings.properties['MACHINEKEY_DecryptionKey'])
class FunctionAppUtilsTest(BaseTest):
    def setUp(self):
        super(FunctionAppUtilsTest, self).setUp()
        self.functionapp_util = FunctionAppUtilities()

    @arm_template('functionapp-reqs.json')
    def test_get_storage_connection_string(self):
        storage_name = 'cloudcustodiantest'
        id = '/subscriptions/%s/resourceGroups/test_functionapp-reqs/providers/Microsoft.Storage' \
             '/storageAccounts/cloudcustodiantest' % local_session(Session).subscription_id
        conn_string = FunctionAppUtilities.get_storage_account_connection_string(id)
        self.assertIn('AccountName=%s;' % storage_name, conn_string)

    @arm_template('functionapp-reqs.json')
    def test_get_application_insights_key_exists(self):
        insights = AppInsightsUnit().get({'name': 'cloud-custodian-test',
                                          'resource_group_name': CONST_GROUP_NAME})

        self.assertIsNotNone(insights)
        self.assertIsNotNone(insights.instrumentation_key)

    @arm_template('functionapp-reqs.json')
    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'
            },
            function_app_resource_group_name=CONST_GROUP_NAME,
            function_app_name='custodian-test-app')

        app = self.functionapp_util.deploy_dedicated_function_app(parameters)
        self.assertIsNotNone(app)
Exemplo n.º 39
0
def _get_parameters(template_util, func_config):
    parameters = template_util.get_default_parameters(
        'dedicated_functionapp.parameters.json')

    func_config['name'] = (func_config['servicePlanName'] + '-' +
                           func_config['name']).replace(' ', '-').lower()

    func_config['storageName'] = (func_config['servicePlanName']).replace(
        '-', '')
    func_config['dockerVersion'] = CONST_DOCKER_VERSION
    func_config['functionsExtVersion'] = CONST_FUNCTIONS_EXT_VERSION
    func_config[
        'machineDecryptionKey'] = FunctionAppUtilities.generate_machine_decryption_key(
        )

    parameters = template_util.update_parameters(parameters, func_config)

    return parameters
    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)
    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'
            },
            function_app_resource_group_name=CONST_GROUP_NAME,
            function_app_name='custodian-test-app')

        app = FunctionAppUtilities.deploy_function_app(parameters)
        self.assertIsNotNone(app)
 def test_get_storage_connection_string(self):
     id = '/subscriptions/%s/resourceGroups/test_functionapp-reqs/providers/Microsoft.Storage' \
          '/storageAccounts/%s' % (self.subscription_id, self.storage_name)
     conn_string = FunctionAppUtilities.get_storage_account_connection_string(
         id)
     self.assertIn('AccountName=%s;' % self.storage_name, conn_string)
 def setUp(self):
     super(FunctionAppUtilsTest, self).setUp()
     self.functionapp_util = FunctionAppUtilities()
 def setUp(self):
     super(FunctionAppUtilsTest, self).setUp()
     self.functionapp_util = FunctionAppUtilities()
Exemplo n.º 45
0
 def provision(self):
     super(AzurePeriodicMode, self).provision()
     package = self.build_functions_package()
     FunctionAppUtilities.publish_functions_package(self.function_params, package)
Exemplo n.º 46
0
 def provision(self):
     self.function_params = self.get_function_app_params()
     FunctionAppUtilities().deploy_dedicated_function_app(self.function_params)
Exemplo n.º 47
0
 def provision(self):
     super(AzurePeriodicMode, self).provision()
     package = self.build_functions_package(
         target_subscription_ids=self.target_subscription_ids)
     FunctionAppUtilities.publish_functions_package(self.function_params,
                                                    package)
 def test_get_storage_connection_string(self):
     storage_name = 'cloudcustodiantest'
     id = '/subscriptions/%s/resourceGroups/test_functionapp-reqs/providers/Microsoft.Storage' \
          '/storageAccounts/cloudcustodiantest' % local_session(Session).subscription_id
     conn_string = FunctionAppUtilities.get_storage_account_connection_string(id)
     self.assertIn('AccountName=%s;' % storage_name, conn_string)