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)
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)
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)
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 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.")
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.")