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'])
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'])
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)
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)
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
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)
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)
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))
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)
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)
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)
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.")
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'))
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'])
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)
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)
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.")
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()
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)
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 provision(self): super(AzurePeriodicMode, self).provision() package = self.build_functions_package() FunctionAppUtilities.publish_functions_package(self.function_params, package)
def provision(self): self.function_params = self.get_function_app_params() FunctionAppUtilities().deploy_dedicated_function_app(self.function_params)
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)