diff --git a/applications/configpush/apic_tool.py b/applications/configpush/apic_tool.py index 962a65c1..9c87ee2e 100644 --- a/applications/configpush/apic_tool.py +++ b/applications/configpush/apic_tool.py @@ -29,6 +29,9 @@ def main(): parser.add_argument('--displayonly', action='store_true', default=False, help=('Only display the JSON configuration. ' 'Do not actually push to the APIC.')) + parser.add_argument('--prompt', action='store_true', default=False, + help=('prompts a message to update the tenant with reference to the given config.' + 'y/n ? if yes does the action specified in the message')) parser.add_argument('--useipepgs', action='store_true', default=False, help=('Use IP based microsegmented EPGS to ' 'assign the endpoint to the EPG.')) @@ -55,7 +58,7 @@ def main(): print 'Could not load improperly formatted configuration file' return - if not args.displayonly and 'apic' not in config: + if 'apic' not in config: if args.url is None or args.login is None or args.password is None: print 'APIC credentials not given' return diff --git a/applications/configpush/apicservice.py b/applications/configpush/apicservice.py index 3120c29b..72ead68b 100644 --- a/applications/configpush/apicservice.py +++ b/applications/configpush/apicservice.py @@ -7,6 +7,7 @@ BridgeDomain, AttributeCriterion, Node, Context) import json +import re from jsonschema import validate, ValidationError, FormatChecker import logging from logging.handlers import RotatingFileHandler @@ -15,6 +16,7 @@ # Imports from standalone mode import argparse +from pprint import pprint class GenericService(object): @@ -26,6 +28,7 @@ def __init__(self): self._json_schema = None self.logger = None self._displayonly = False + self.prompt = False def set_json_schema(self, filename): """ @@ -49,6 +52,20 @@ def get_json_schema(self): """ return self._json_schema + @property + def prompt(self): + """ + Get the display only flag. This will cause the JSON to be displayed but not pushed to APIC. + """ + return self._prompt + + @prompt.setter + def prompt(self, x): + """ + Set the display only flag. This will cause the JSON to be displayed but not pushed to APIC. + """ + self._prompt = x + @property def displayonly(self): """ @@ -740,19 +757,48 @@ def set_app_name(self, name): def use_ip_epgs(self): self._use_ip_epgs = True - def push_config_to_apic(self): - """ - Push the configuration to the APIC - - :return: Requests Response instance indicating success or not - """ - THROTTLE_SIZE = 500000 / 8 - # Set the tenant name correctly - if self._tenant_name == '' and self.cdb.has_context_config(): - self.set_tenant_name(self.cdb.get_context_config().tenant_name) - elif self._tenant_name == '': - self.set_tenant_name('acitoolkit') + def prompt_and_mark_as_deleted(self, apic, object_delete=None): + ''' + if self.prompt is True, prompts for the decision and if yes the object is deleted. + if self.prompt is False, directly object is deleted + ''' + if self.prompt: + logging.debug(object_delete.get_json()) + print "----------------------------------" + pprint(object_delete.get_json()) + msg = 'do u want to delete %s : %s' % (object_delete.__class__.__name__, object_delete.name) + shall = raw_input("%s (y/n) " % msg).lower() == 'y' + if shall: + logging.debug("deleting object %s : %s" % (object_delete.__class__.__name__, object_delete.name)) + object_delete.mark_as_deleted() + else: + logging.debug("deleting object %s : %s" % (object_delete.__class__.__name__, object_delete.name)) + object_delete.mark_as_deleted() + + def prompt_and_remove_relation(self, apic, parentObject=None, childObject=None): + ''' + if self.prompt is True,prompts for the decision and if given yes removes the relation of child from the parent object. + if self.prompt is False, directly removes the relation of child from parent object + ''' + if self.prompt: + logging.debug(parentObject.get_json()) + print "----------------------------------" + pprint(parentObject.get_json()) + msg = 'do u want to remove relation of %s in %s : %s' % ( + childObject.name, parentObject.__class__.__name__, parentObject.name) + shall = raw_input("%s (y/n) " % msg).lower() == 'y' + if shall: + logging.debug("removing relation of %s with %s : %s" % + (childObject.name, parentObject.__class__.__name__, parentObject.name)) + parentObject._remove_relation(childObject) + childObject._remove_attachment(parentObject) + else: + logging.debug("removing relation of %s with %s : %s" % + (childObject.name, parentObject.__class__.__name__, parentObject.name)) + parentObject._remove_relation(childObject) + childObject._remove_attachment(parentObject) + def remove_duplicate_contracts(self): # Find all the unique contract providers logging.debug('Finding the unique contract providers') unique_providers = {} @@ -784,19 +830,73 @@ def push_config_to_apic(self): for duplicate_policy in duplicate_policies: self.cdb.remove_contract_policy(duplicate_policy) - if not self.displayonly: - # Log on to the APIC - apic_cfg = self.cdb.get_apic_config() - apic = Session(apic_cfg.url, apic_cfg.user_name, apic_cfg.password) - resp = apic.login() - if not resp.ok: - return resp + def delete_unwanted_attributeCriterion_in_epgs(self, apic): + ''' + deletes the attribute criterion(uSeg attributes) from EPGS which are not in the present config + ''' + tenant = Tenant(self._tenant_name) + tenant_names = [self._tenant_name] + existing_epgs = [] + if Tenant.exists(apic, tenant): + tenants = Tenant.get_deep( + apic, + names=tenant_names) + tenant = tenants[0] + appProfiles = tenant.get_children(AppProfile) + app = appProfiles[0] + existing_epgs = app.get_children(EPG) + else: + app = AppProfile(self._app_name, tenant) - tenant_names = [] - tenant_names.append(self._tenant_name) + if self._use_ip_epgs: + for existing_epg in existing_epgs: + if existing_epg.name != "base": + for epg_policy in self.cdb.get_epg_policies(): + if not existing_epg.descr == "" and existing_epg.descr.split(":")[1] == epg_policy.descr.split( + ":")[1] and existing_epg.descr.split(":")[0] == epg_policy.descr.split(":")[0]: - # delete all the unwanted epgs + if existing_epg._is_attribute_based: + existing_criterions = existing_epg.get_children(AttributeCriterion) + for existing_criterion in existing_criterions: + existing_ip_address = existing_criterion.get_ip_addresses() + node_policies = epg_policy.get_node_policies() + for existing_ip in existing_ip_address: + match = False + for node_policy in node_policies: + if node_policy.ip == existing_ip.split('/')[0]: + match = True + if not match: + logging.debug("delete ip existing_ip " + existing_ip) + if self.prompt: + logging.debug(existing_epg.get_json()) + pprint(existing_criterion.get_json()) + msg = 'do u want to delete the attribute criterion((uSeg attributes)) ip %s in EPG %s' % ( + existing_ip, existing_epg.name) + shall = raw_input("%s (y/n) " % msg).lower() == 'y' + if shall: + logging.debug( + "deleting attribute criterion(uSeg attributes) ip %s in %s" % + (existing_ip, existing_epg.name)) + existing_criterion.mark_as_deleted() + else: + logging.debug( + "deleting attribute criterion(uSeg attributes) ip %s in %s" % + (existing_ip, existing_epg.name)) + existing_criterion.mark_as_deleted() + if self.displayonly: + print json.dumps(tenant.get_json(), indent=4, sort_keys=True) + else: + logging.debug('Pushing EPGS by deleting unwanted uSeg attributes ') + if len(tenant.get_children()) > 0: + resp = tenant.push_to_apic(apic) + return resp + + def delete_unwanted_epgs(self, apic): + ''' + deletes the EPGS which are not in the present config['clusters'] + ''' tenant = Tenant(self._tenant_name) + tenant_names = [self._tenant_name] existing_epgs = [] if Tenant.exists(apic, tenant): tenants = Tenant.get_deep( @@ -805,6 +905,8 @@ def push_config_to_apic(self): limit_to=[ 'fvTenant', 'fvAp', + 'fvBD', + 'fvCtx', 'vzFilter', 'vzEntry', 'vzBrCP', @@ -815,46 +917,40 @@ def push_config_to_apic(self): app = appProfiles[0] existing_epgs = app.get_children(EPG) else: - app = AppProfile(self._app_name, tenant) for existing_epg in existing_epgs: matched = False if existing_epg.name != "base": for epg_policy in self.cdb.get_epg_policies(): - if existing_epg.descr.split(":")[1] == epg_policy.descr.split( + if not existing_epg.descr == "" and existing_epg.descr.split(":")[1] == epg_policy.descr.split( ":")[1] and existing_epg.descr.split(":")[0] == epg_policy.descr.split(":")[0]: if self._use_ip_epgs: if existing_epg._is_attribute_based: matched = True - existing_criterions = existing_epg.get_children(AttributeCriterion) - for existing_criterion in existing_criterions: - existing_criterion.mark_as_deleted() - elif existing_epg._is_attribute_based: + elif not existing_epg._is_attribute_based: matched = True - existing_criterions = existing_epg.get_children(AttributeCriterion) - for existing_criterion in existing_criterions: - existing_criterion.mark_as_deleted() if not matched: - existing_epg.mark_as_deleted() + self.prompt_and_mark_as_deleted(apic, existing_epg) + + if not self._use_ip_epgs: + for existing_epg in existing_epgs: + if existing_epg.name == "base": + self.prompt_and_mark_as_deleted(apic, existing_epg) + + if self.cdb.has_context_config(): + context_name = self.cdb.get_context_config().name else: - if not self._use_ip_epgs: - base_epg = EPG('base', app) - if self.cdb.has_context_config(): - context_name = self.cdb.get_context_config().name - else: - context_name = 'vrf1' - context = Context(context_name, tenant) - existing_contexts = tenant.get_children(Context) - for existing_context in existing_contexts: - if existing_context.name == context_name: - existing_context.mark_as_deleted() - existing_bds = tenant.get_children(BridgeDomain) - for existing_bd in existing_bds: - if existing_bd.name == 'bd': - existing_bd.mark_as_deleted() - base_epg.mark_as_deleted() + context_name = 'vrf1' + existing_contexts = tenant.get_children(Context) + for existing_context in existing_contexts: + if existing_context.name == context_name: + self.prompt_and_mark_as_deleted(apic, existing_context) + existing_bds = tenant.get_children(BridgeDomain) + for existing_bd in existing_bds: + if existing_bd.name == 'bd': + self.prompt_and_mark_as_deleted(apic, existing_bd) if self.displayonly: print json.dumps(tenant.get_json(), indent=4, sort_keys=True) @@ -862,49 +958,61 @@ def push_config_to_apic(self): logging.debug('Pushing EPGS by deleting unwanted epgs ') if len(tenant.get_children()) > 0: resp = tenant.push_to_apic(apic) - if not resp.ok: - return resp + return resp - # delete all the unwanted contracts - tenants = Tenant.get_deep( - apic, - names=tenant_names, - limit_to=[ - 'fvTenant', - 'fvAp', - 'vzFilter', - 'vzEntry', - 'vzBrCP', - 'vzSubj', - 'vzRsSubjFiltAtt']) - tenant = tenants[0] - existing_contracts = tenant.get_children(Contract) - for existing_contract in existing_contracts: - matched = False - for contract_policy in self.cdb.get_contract_policies(): - if existing_contract.descr.split("::")[1] == contract_policy.descr.split( - "::")[1] and existing_contract.descr.split("::")[0] == contract_policy.descr.split("::")[0]: - matched = True - if not matched: - existing_contract.mark_as_deleted() - exist_contract_providing_epgs = existing_contract.get_all_providing_epgs() - for exist_contract_providing_epg in exist_contract_providing_epgs: - exist_contract_providing_epg.mark_as_deleted() - exist_contract_consuming_epgs = existing_contract.get_all_consuming_epgs() - for exist_contract_consuming_epg in exist_contract_consuming_epgs: - exist_contract_consuming_epg.mark_as_deleted() + def delete_unwanted_contracts(self, apic): + ''' + deletes the Contracts which are not in the present config['policies'] + ''' + tenant_names = [self._tenant_name] + tenant = Tenant(self._tenant_name) + if Tenant.exists(apic, tenant): + tenants = Tenant.get_deep( + apic, + names=tenant_names, + limit_to=[ + 'fvTenant', + 'fvAp', + 'vzFilter', + 'vzEntry', + 'vzBrCP', + 'vzSubj', + 'vzRsSubjFiltAtt']) + tenant = tenants[0] + existing_contracts = tenant.get_children(Contract) + for existing_contract in existing_contracts: + matched = False + for contract_policy in self.cdb.get_contract_policies(): + contract_policy.descr = contract_policy.descr[0:127 - + (contract_policy.descr.count('"') + + contract_policy.descr.count("'") + + contract_policy.descr.count('/'))] + if existing_contract.descr.split("::")[1] == contract_policy.descr.split( + "::")[1] and existing_contract.descr.split("::")[0] == contract_policy.descr.split("::")[0]: + matched = True + if not matched: + self.prompt_and_mark_as_deleted(apic, existing_contract) + exist_contract_providing_epgs = existing_contract.get_all_providing_epgs() + for exist_contract_providing_epg in exist_contract_providing_epgs: + self.prompt_and_remove_relation(apic, exist_contract_providing_epg, existing_contract) + exist_contract_consuming_epgs = existing_contract.get_all_consuming_epgs() + for exist_contract_consuming_epg in exist_contract_consuming_epgs: + self.prompt_and_remove_relation(apic, exist_contract_consuming_epg, existing_contract) - if self.displayonly: - print json.dumps(tenant.get_json(), indent=4, sort_keys=True) - else: - logging.debug('Pushing contracts by deleting unwanted contracts') - if len(tenant.get_children()) > 0: - resp = tenant.push_to_apic(apic) - if not resp.ok: + if self.displayonly: + print json.dumps(tenant.get_json(), indent=4, sort_keys=True) + else: + logging.debug('Pushing contracts by deleting unwanted contracts') + if len(tenant.get_children()) > 0: + resp = tenant.push_to_apic(apic) return resp - filterEntry_list = [] - + def removing_unwanted_filter_relations(self, apic): + ''' + deletes the filter relations in contracts which are not in the present config['policies'] + ''' + # if num of contract_subjects is 0 then remove it finally + tenant_names = [self._tenant_name] logging.debug('Generating JSON....') # Push all of the Contracts logging.debug('Pushing contracts. # of Contract policies: %s', len(self.cdb.get_contract_policies())) @@ -923,12 +1031,11 @@ def push_config_to_apic(self): tenant = tenants[0] existing_contracts = tenant.get_children(Contract) else: - existing_contracts = tenant.get_children(Contract) + existing_contracts = [] # removing the unwanted contractsubject filters for each contract subject for contract_policy in self.cdb.get_contract_policies(): - name = contract_policy.src_name + '::' + contract_policy.dst_name for existing_contract in existing_contracts: - if existing_contract.descr.split("::")[1] == contract_policy.descr.split( + if existing_contract.descr != "" and existing_contract.descr.split("::")[1] == contract_policy.descr.split( "::")[1] and existing_contract.descr.split("::")[0] == contract_policy.descr.split("::")[0]: for child_contractSubject in existing_contract.get_children(ContractSubject): for child_filter in child_contractSubject.get_filters(): @@ -939,50 +1046,105 @@ def push_config_to_apic(self): matched = True continue if not matched: - # TBD need to check this. this is not working - child_contractSubject._remove_relation(child_filter) - child_filter._remove_attachment(child_contractSubject) - logging.debug('removing filter ' + child_filter.name) + self.prompt_and_remove_relation(apic, child_contractSubject, child_filter) if self.displayonly: print json.dumps(tenant.get_json(), indent=4, sort_keys=True) else: logging.debug('Pushing contracts by deleting unwanted filters') - if len(tenant.get_children()) > 0: - resp = tenant.push_to_apic(apic) - if not resp.ok: - return resp + resp = tenant.push_to_apic(apic) + return resp + + def push_remaining_contracts_along_with_filters(self, apic, THROTTLE_SIZE): + ''' + pushing the contracts in config['policies'] + if the tenant doesnot exist, then all the policies(contracts) are pushed to apic. + if the tenant exists, then only the policies(contracts) which are not existing are pushed to apic + ''' + self.filterEntry_list = [] + tenant_names = [self._tenant_name] + tenant = Tenant(self._tenant_name) + if Tenant.exists(apic, tenant): + tenants = Tenant.get_deep( + apic, + names=tenant_names, + limit_to=[ + 'fvTenant', + 'fvAp', + 'vzFilter', + 'vzEntry', + 'vzBrCP', + 'vzSubj', + 'vzRsSubjFiltAtt']) + tenant = tenants[0] + existing_contracts = tenant.get_children(Contract) + else: + existing_contracts = [] - # if num of contract_subjects is 0 then remove it finally for contract_policy in self.cdb.get_contract_policies(): - name = contract_policy.src_name + '::' + contract_policy.dst_name - contract = Contract(name, tenant) - contract.descr = contract_policy.descr[0:127 - - (contract_policy.descr.count('"') + - contract_policy.descr.count("'") + - contract_policy.descr.count('/'))] + matched = False + for existing_contract in existing_contracts: + if existing_contract.descr != "" and existing_contract.descr.split("::")[1] == contract_policy.descr.split( + "::")[1] and existing_contract.descr.split("::")[0] == contract_policy.descr.split("::")[0]: + matched = True + break + if matched: + contract = existing_contract + for child_contractSubject in contract.get_children(ContractSubject): + child_filters = child_contractSubject.get_filters() + else: + name = contract_policy.src_name + '::' + contract_policy.dst_name + child_filters = [] + contract = Contract(name, tenant) + contract.descr = contract_policy.descr[0:127 - + (contract_policy.descr.count('"') + + contract_policy.descr.count("'") + + contract_policy.descr.count('/'))] + if self.prompt: + pprint(contract.get_json()) + msg = "do u want to add a new contract %s" % name + shall = raw_input("%s (y/n) " % msg).lower() == 'y' + if not shall: + contract.mark_as_deleted() + else: + logging.debug("adding a new contract " + name) + for whitelist_policy in contract_policy.get_whitelist_policies(): entry_name = whitelist_policy.proto + '.' + whitelist_policy.port_min + '.' + whitelist_policy.port_max - if whitelist_policy.proto == '6' or whitelist_policy.proto == '17': - entry = FilterEntry(entry_name, - applyToFrag='no', - arpOpc='unspecified', - dFromPort=whitelist_policy.port_min, - dToPort=whitelist_policy.port_max, - etherT='ip', - prot=whitelist_policy.proto, - sFromPort='unspecified', - sToPort='unspecified', - tcpRules='unspecified', - parent=contract) - else: - entry = FilterEntry(entry_name, - applyToFrag='no', - arpOpc='unspecified', - etherT='ip', - prot=whitelist_policy.proto, - parent=contract) - filterEntry_list.append(entry_name) + self.filterEntry_list.append(entry_name) + filter_not_exists = True + for child_filter in child_filters: + if child_filter.name == entry_name + '_Filter': + filter_not_exists = False + + if filter_not_exists: + if self.prompt: + print "----------------------------------" + pprint(contract.get_json()) + msg = "do u want to add a new filter relation %s in contract %s " % (entry_name, contract.name) + shall = raw_input("%s (y/n) " % msg).lower() == 'y' + if not shall: + break + logging.debug("adding a new filter for contract " + entry_name) + if whitelist_policy.proto == '6' or whitelist_policy.proto == '17': + entry = FilterEntry(entry_name, + applyToFrag='no', + arpOpc='unspecified', + dFromPort=whitelist_policy.port_min, + dToPort=whitelist_policy.port_max, + etherT='ip', + prot=whitelist_policy.proto, + sFromPort='unspecified', + sToPort='unspecified', + tcpRules='unspecified', + parent=contract) + else: + entry = FilterEntry(entry_name, + applyToFrag='no', + arpOpc='unspecified', + etherT='ip', + prot=whitelist_policy.proto, + parent=contract) if not self.displayonly: if len(str(tenant.get_json())) > THROTTLE_SIZE: logging.debug('Throttling contracts. Pushing config...') @@ -991,15 +1153,224 @@ def push_config_to_apic(self): return resp tenant = Tenant(self._tenant_name) + if self.displayonly: + print json.dumps(tenant.get_json(), indent=4, sort_keys=True) + else: + logging.debug('Pushing remaining contracts') + resp = tenant.push_to_apic(apic) + return resp + + def removing_unwanted_filters(self, apic): + ''' + deleting the filters which are not in any of the whitelist_policies of the present config['policies'] + ''' + tenants = Tenant.get_deep(apic, names=[self._tenant_name], limit_to=['fvTenant', 'vzFilter', 'vzEntry']) + if len(tenants) > 0: + tenant = tenants[0] + existing_Filters = [] + existing_Filters = tenant.get_children(Filter) + for existing_filter in existing_Filters: + matched = False + for filterEntry in self.filterEntry_list: + if filterEntry + '_Filter' == existing_filter.name: + matched = True + break + if not matched: + self.prompt_and_mark_as_deleted(apic, existing_filter) if self.displayonly: print json.dumps(tenant.get_json(), indent=4, sort_keys=True) else: - logging.debug('Pushing remaining contracts') resp = tenant.push_to_apic(apic) - if not resp.ok: - return resp + return resp + + def consume_and_provide_contracts_for_epgs(self, tenant, app, bd=None, base_epg=None): + existing_epgs = app.get_children(EPG) + for epg_policy in self.cdb.get_epg_policies(): + matched = False + for existing_epg in existing_epgs: + if existing_epg.name != "base": + if existing_epg.descr.split(":")[1] == epg_policy.descr.split( + ":")[1] and existing_epg.descr.split(":")[0] == epg_policy.descr.split(":")[0]: + matched = True + break + + consumed_contracts = [] + provided_contracts = [] + if matched is True: + consumed_contracts = existing_epg.get_all_consumed() + provided_contracts = existing_epg.get_all_provided() + epg = existing_epg + else: + epg = EPG(epg_policy.name, app) + epg.descr = epg_policy.descr[0:127] + if self.prompt: + print "----------------------------------" + pprint(epg.get_json()) + msg = "do u want to add a new EPG %s" % epg_policy.name + shall = raw_input("%s (y/n) " % msg).lower() == 'y' + if not shall: + epg.mark_as_deleted() + else: + logging.debug("adding a new epg " + epg_policy.name) + + if self._use_ip_epgs: + no_default_endpoint = True + for node_policy in epg_policy.get_node_policies(): + if node_policy.ip == '0.0.0.0' and node_policy.prefix_len == 0: + no_default_endpoint = False + epg.add_bd(bd) + + # Add all of the IP addresses + if no_default_endpoint: + if not epg.is_attributed_based: + epg.is_attributed_based = True + epg.set_base_epg(base_epg) + criterion = AttributeCriterion('criterion', epg) + else: + existing_criterions = epg.get_children(AttributeCriterion) + if len(existing_criterions) > 0: + criterion = existing_criterions[0] + else: + criterion = AttributeCriterion('criterion', epg) + + ipaddrs = [] + for node_policy in epg_policy.get_node_policies(): + ipaddr = ipaddress.ip_address(unicode(node_policy.ip)) + if not ipaddr.is_multicast: # Skip multicast addresses. They cannot be IP based EPGs + ipaddrs.append(ipaddr) + nets = ipaddress.collapse_addresses(ipaddrs) + + for net in nets: + existing_ip_address = criterion.get_ip_addresses() + if not str(net) in existing_ip_address: + if self.prompt: + print "----------------------------------" + pprint(epg.get_json()) + msg = "do u want to add attribute Criterion with ip address %s to EPG %s " % ( + str(net), epg.name) + shall = raw_input("%s (y/n) " % msg).lower() == 'y' + if shall: + logging.debug( + "adding attribute Criterion with ip address %s to EPG %s " % + (str(net), epg_policy.name)) + criterion.add_ip_address(str(net)) + else: + logging.debug( + "adding attribute Criterion with ip address %s to EPG %s " % + (str(net), epg_policy.name)) + criterion.add_ip_address(str(net)) + epg.descr = epg_policy.descr[0:127] - # Push all of the EPGs + for contract_policy in self.cdb.get_contract_policies(): + contract = None + if epg_policy.id in contract_policy.src_ids: + name = contract_policy.src_name + '::' + contract_policy.dst_name + pattern = re.escape(re.match(r"(.*)-(.*)", contract_policy.src_name).group(1)) + pattern += r"-\d+::" + pattern += re.escape(re.match(r"(.*)-(.*)", contract_policy.dst_name).group(1)) + pattern += r"-\d+" + existing = False + for existing_consumed_contract in consumed_contracts: + if re.search(pattern, existing_consumed_contract.name, re.IGNORECASE): + existing = True + contract = existing_consumed_contract + if not existing: + if self.prompt: + msg = "do u want to add a new consuming contract %s for EPG %s" % (name, epg) + shall = raw_input("%s (y/n) " % msg).lower() == 'y' + if shall: + contract = Contract(name, tenant) + epg.consume(contract) + logging.debug("adding a consuming contract %s for EPG %s " % (name, epg_policy.name)) + else: + logging.debug("adding a consuming contract %s for EPG %s " % (name, epg_policy.name)) + contract = Contract(name, tenant) + epg.consume(contract) + if epg_policy.id in contract_policy.dst_ids: + name = contract_policy.src_name + '::' + contract_policy.dst_name + pattern = re.escape(re.match(r"(.*)-(.*)", contract_policy.src_name).group(1)) + pattern += r"-\d+::" + pattern += re.escape(re.match(r"(.*)-(.*)", contract_policy.dst_name).group(1)) + pattern += r"-\d+" + if contract is None: + existing = False + for existing_provided_contract in provided_contracts: + if re.search(pattern, existing_provided_contract.name, re.IGNORECASE): + existing = True + contract = existing_provided_contract + if not existing: + if self.prompt: + msg = "do u want to add a new consuming contract %s for EPG %s" % (name, epg) + shall = raw_input("%s (y/n) " % msg).lower() == 'y' + if shall: + contract = Contract(name, tenant) + logging.debug( + "adding a providing contract %s for EPG %s " % + (name, epg_policy.name)) + else: + logging.debug("adding a providing contract %s for EPG %s " % (name, epg_policy.name)) + contract = Contract(name, tenant) + epg.provide(contract) + + def push_config_to_apic(self): + """ + Push the configuration to the APIC + + :return: Requests Response instance indicating success or not + """ + THROTTLE_SIZE = 500000 / 8 + # Set the tenant name correctly + if self._tenant_name == '' and self.cdb.has_context_config(): + self.set_tenant_name(self.cdb.get_context_config().tenant_name) + elif self._tenant_name == '': + self.set_tenant_name('acitoolkit') + + logging.debug('Removing duplicate contracts') + self.remove_duplicate_contracts() + + # Log on to the APIC + apic_cfg = self.cdb.get_apic_config() + apic = Session(apic_cfg.url, apic_cfg.user_name, apic_cfg.password) + resp = apic.login() + if not resp.ok: + return resp + + tenant = Tenant(self._tenant_name) + if not Tenant.exists(apic, tenant): + # when adding tenant for the first time, all the config is added so prompt is made false + print ("tenant doesnot exist. so adding all the config without showing the prompt ") + self.prompt = False + + # delete all the unused or not existing EPGs in the present config + logging.debug('Deleting unused or not existing EPGs in the present config') + resp = self.delete_unwanted_epgs(apic) + if not resp.ok: + return resp + + logging.debug('Deleting unused or not exitsing attribute criterion in the present config in existing EPGs') + resp = self.delete_unwanted_attributeCriterion_in_epgs(apic) + if not resp.ok: + return resp + + # delete all the unused or not existing contracts in the present config + logging.debug('Deleting unused or not existing contracts in the present config') + resp = self.delete_unwanted_contracts(apic) + if not resp.ok: + return resp + + logging.debug('Deleting unused or not existing filter relations from contractSubjects in the present config') + resp = self.removing_unwanted_filter_relations(apic) + if not resp.ok: + return resp + + # pushing remaining contracts + logging.debug('Pushing remaining contracts along with filters relations') + resp = self.push_remaining_contracts_along_with_filters(apic, THROTTLE_SIZE) + if not resp.ok: + return resp + + # Push remaining EPGs + tenant_names = [self._tenant_name] logging.debug('Pushing EPGs') if not self.displayonly: tenants = Tenant.get_deep(apic, names=tenant_names) @@ -1028,142 +1399,41 @@ def push_config_to_apic(self): if node.role == 'leaf': base_epg.add_static_leaf_binding(node.node, 'vlan', '1', encap_mode='untagged') - # Create the Attribute based EPGs - logging.debug('Creating Attribute Based EPGs') - existing_epgs = app.get_children(EPG) - for epg_policy in self.cdb.get_epg_policies(): - if not self.displayonly: - # Check if we need to throttle very large configs - if len(str(tenant.get_json())) > THROTTLE_SIZE: - resp = tenant.push_to_apic(apic) - if not resp.ok: - return resp - tenant = Tenant(self._tenant_name) - app = AppProfile(self._app_name, tenant) - context = Context(context_name, tenant) - bd = BridgeDomain('bd', tenant) - bd.add_context(context) - if self._use_ip_epgs: - base_epg = EPG('base', app) - base_epg.add_bd(bd) - - matched = False - for existing_epg in existing_epgs: - if existing_epg.name != "base": - if existing_epg.descr.split(":")[1] == epg_policy.descr.split( - ":")[1] and existing_epg.descr.split(":")[0] == epg_policy.descr.split(":")[0]: - matched = True - break - - consumed_contracts = [] - provided_contracts = [] - if matched is True: - consumed_contracts = existing_epg.get_all_consumed() - provided_contracts = existing_epg.get_all_provided() - epg = existing_epg - else: - epg = EPG(epg_policy.name, app) + if not self.displayonly: + # Check if we need to throttle very large configs + if len(str(tenant.get_json())) > THROTTLE_SIZE: + resp = tenant.push_to_apic(apic) + if not resp.ok: + return resp + tenant = Tenant(self._tenant_name) + app = AppProfile(self._app_name, tenant) + context = Context(context_name, tenant) + bd = BridgeDomain('bd', tenant) + bd.add_context(context) + if self._use_ip_epgs: + base_epg = EPG('base', app) + base_epg.add_bd(bd) - # Check if the policy has the default 0.0.0.0 IP address - no_default_endpoint = True - for node_policy in epg_policy.get_node_policies(): - if node_policy.ip == '0.0.0.0' and node_policy.prefix_len == 0: - no_default_endpoint = False - epg.add_bd(bd) + self.consume_and_provide_contracts_for_epgs(tenant, app, bd, base_epg) - # Add all of the IP addresses - if no_default_endpoint: - epg.is_attributed_based = True - epg.set_base_epg(base_epg) - criterion = AttributeCriterion('criterion', epg) - ipaddrs = [] - # TBD check if the existing nodes are there in the present config,if not delete them - for node_policy in epg_policy.get_node_policies(): - ipaddr = ipaddress.ip_address(unicode(node_policy.ip)) - if not ipaddr.is_multicast: # Skip multicast addresses. They cannot be IP based EPGs - ipaddrs.append(ipaddr) - nets = ipaddress.collapse_addresses(ipaddrs) - for net in nets: - criterion.add_ip_address(str(net)) - epg.descr = epg_policy.descr[0:127] - # Consume and provide all of the necessary contracts - for contract_policy in self.cdb.get_contract_policies(): - contract = None - if epg_policy.id in contract_policy.src_ids: - name = contract_policy.src_name + '::' + contract_policy.dst_name - existing = False - for existing_consumed_contract in consumed_contracts: - if name == existing_consumed_contract.name: - existing = True - contract = existing_consumed_contract - if not existing: - contract = Contract(name, tenant) - epg.consume(contract) - if epg_policy.id in contract_policy.dst_ids: - name = contract_policy.src_name + '::' + contract_policy.dst_name - if contract is None: - existing = False - for existing_provided_contract in provided_contracts: - if name == existing_provided_contract.name: - existing = True - contract = existing_provided_contract - if not existing: - contract = Contract(name, tenant) - epg.provide(contract) else: logging.debug('Creating EPGs') tenants = Tenant.get_deep(apic, names=tenant_names) - tenant = tenants[0] + if len(tenants) > 0: + tenant = tenants[0] + bds = tenant.get_children(BridgeDomain) + if len(bds) > 0: + bd = bds[0] + bd.mark_as_deleted() + else: + tenant = Tenant(self._tenant_name) appProfiles = tenant.get_children(AppProfile) if len(appProfiles) > 0: app = appProfiles[0] else: app = AppProfile(self._app_name, tenant) - existing_epgs = app.get_children(EPG) - - for epg_policy in self.cdb.get_epg_policies(): - - matched = False - for existing_epg in existing_epgs: - if existing_epg.name != "base": - if existing_epg.descr.split(":")[1] == epg_policy.descr.split( - ":")[1] and existing_epg.descr.split(":")[0] == epg_policy.descr.split(":")[0]: - matched = True - break - - consumed_contracts = [] - provided_contracts = [] - if matched is True: - consumed_contracts = existing_epg.get_all_consumed() - provided_contracts = existing_epg.get_all_provided() - epg = EPG(epg_policy.name, app) - epg.descr = epg_policy.descr[0:127] - - # Consume and provide all of the necessary contracts - for contract_policy in self.cdb.get_contract_policies(): - contract = None - if epg_policy.id in contract_policy.src_ids: - name = contract_policy.src_name + '::' + contract_policy.dst_name - existing = False - for existing_consumed_contract in consumed_contracts: - if name == existing_consumed_contract.name: - existing = True - contract = existing_consumed_contract - if not existing: - contract = Contract(name, tenant) - epg.consume(contract) - if epg_policy.id in contract_policy.dst_ids: - name = contract_policy.src_name + '::' + contract_policy.dst_name - if contract is None: - existing = False - for existing_provided_contract in provided_contracts: - if name == existing_provided_contract.name: - existing = True - contract = existing_provided_contract - if not existing: - contract = Contract(name, tenant) - epg.provide(contract) + self.consume_and_provide_contracts_for_epgs(tenant, app) if self.displayonly: print json.dumps(tenant.get_json(), indent=4, sort_keys=True) @@ -1173,19 +1443,8 @@ def push_config_to_apic(self): return resp # remove the unwanted filters - existing_filters = tenant.get_children(Filter) - for existing_filetrEntry in existing_filters: - matched = False - for filterEntry in filterEntry_list: - if filterEntry + '_Filter' == existing_filetrEntry.name: - matched = True - if not matched: - existing_filetrEntry.mark_as_deleted() - if self.displayonly: - print json.dumps(tenant.get_json(), indent=4, sort_keys=True) - else: - resp = tenant.push_to_apic(apic) - return resp + logging.debug('Deleting the unused or not existing Filters in the present config') + return self.removing_unwanted_filters(apic) def mangle_names(self): unique_id = 0 @@ -1296,6 +1555,7 @@ def execute_tool(args): tool = ApicService() tool.displayonly = args.displayonly + tool.prompt = args.prompt if args.tenant: tool.set_tenant_name(args.tenant) if args.app: diff --git a/applications/configpush/apicservice_test.py b/applications/configpush/apicservice_test.py index 4f0a4c20..bb178b75 100644 --- a/applications/configpush/apicservice_test.py +++ b/applications/configpush/apicservice_test.py @@ -10,6 +10,8 @@ import time from deepdiff import DeepDiff import gzip +from pprint import pprint +import ast try: from apicservice_test_credentials import (LOGIN, PASSWORD, IPADDR) @@ -34,7 +36,7 @@ def __init__(self): self.session = '' self.tool = '' - def load_configFile(self, config_file, is_file=True, displayonly=False, tenant_name='configpush-test', + def load_configFile(self, config_file, is_file=True, prompt=False, displayonly=False, tenant_name='configpush-test', app_name='appProfile-test', useipEpgs=False): """ load_configFile @@ -66,6 +68,7 @@ def load_configFile(self, config_file, is_file=True, displayonly=False, tenant_n self.tool = ApicService() self.tool.displayonly = displayonly + self.tool.prompt = prompt self.tool.set_tenant_name(tenant_name) self.tool.set_app_name(app_name) if useipEpgs: @@ -290,7 +293,7 @@ def test_initial_configpush(self): self.assertEquals(len(existing_epgs), 2, "epgs count did not match for the pushed config and existing config") for existing_epg in existing_epgs: - self.assertEqual(existing_epg.is_attribute_based, False, + self.assertEqual(existing_epg.is_attributed_based, False, "attribute based is true for EPG " + existing_epg.name) if existing_epg.name == 'Configpushtest_-_1_-0': self.assertEqual(len(existing_epg.get_all_consumed()), 1, @@ -1026,6 +1029,183 @@ def test_useipEpg_node_update_configpush_for_policy(self): self.assertEquals(len(existing_contexts), 1, "existing_contexts count did not match for the pushed config and existing config") + def test_without_useipEpg_again_push_initial_configpush(self): + """ + after useipepgs pushing back the initial config and check the tenant config doesnot change + push a sample config with 2 clusters, 1 policy. + check the tenant config after it is pushed to apic by tenant.get_deep() + verify the num of children expected and existing in apic for this tenant + """ + + config_file = """ + { + "clusters": [ + { + "name": "Configpushtest*-(1)", + "id": "56c55b8761707062b2d11b00", + "descr": "sample description", + "route_tag": { + "subnet_mask": "173.38.111.0/24", + "name": "rtp1-dcm01n-gp-db-dr2:iv2133" + }, + "labels": [ + + ], + "nodes": [ + { + "ip": "173.38.111.127", + "name": "lnxdb-dr-vm-421" + }, + { + "ip": "173.38.111.131", + "name": "lnxdb-dr-vm-422" + } + ] + }, + { + "name": "Configpushtest*-(2)", + "id": "56c3d31561707035c0c12b00", + "descr": "sample description", + "approved": true, + "route_tag": { + "subnet_mask": "0.0.0.0/0", + "name": "INTERNET-EXTNET" + }, + "labels": [ + + ], + "nodes": [ + { + "ip": "173.38.111.126", + "name": "lnxdb-dr-vm-423" + }, + { + "ip": "173.38.111.128", + "name": "lnxdb-dr-vm-424" + } + ] + } + ], + "policies": [ + { + "src": "56c55b8761707062b2d11b00", + "dst": "56c3d31561707035c0c12b00", + "src_name": "Configpushtest-policy*-(1)", + "dst_name": "Configpushtest-policy*-(2)", + "descr": "sample description", + "whitelist": [ + { + "port": [ + 0, + 0 + ], + "proto": 1, + "action": "ALLOW" + }, + { + "port": [ + 0, + 0 + ], + "proto": 6, + "action": "ALLOW" + } + ] + } + ] +} + """ + load_config = LoadConfig() + load_config.load_configFile(config_file, is_file=False) + time.sleep(5) + tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) + for tenant in tenants: + if tenant.name == 'configpush-test': + existing_filters = tenant.get_children(Filter) + self.assertEquals(len(existing_filters), 2, + "filter count did not match for the pushed config and existing config") + + app_profiles = tenant.get_children(AppProfile) + app = app_profiles[0] + existing_epgs = app.get_children(EPG) + self.assertEquals(len(existing_epgs), 2, + "epgs count did not match for the pushed config and existing config") + for existing_epg in existing_epgs: + self.assertEqual(existing_epg.is_attributed_based, False, + "attribute based is true for EPG " + existing_epg.name) + if existing_epg.name == 'Configpushtest_-_1_-0': + self.assertEqual(len(existing_epg.get_all_consumed()), 1, + "consumed EPG did not match for EPG " + existing_epg.name) + self.assertEqual(len(existing_epg.get_all_provided()), 0, + "provided EPG did not match for EPG " + existing_epg.name) + elif existing_epg.name == 'Configpushtest_-_2_-1': + self.assertEqual(len(existing_epg.get_all_consumed()), 0, + "consumed EPG did not match for EPG " + existing_epg.name) + self.assertEqual(len(existing_epg.get_all_provided()), 1, + "provided EPG did not match for EPG " + existing_epg.name) + for existing_epg in existing_epgs: + self.assertTrue(existing_epg.name != 'Base', + "Base EPG exists without useipEpgs" + existing_epg.name) + + existing_contracts = tenant.get_children(Contract) + self.assertEquals(len(existing_contracts), 1, + "contracts count did not match for the pushed config and existing config") + for existing_contract in existing_contracts: + for child_contractSubject in existing_contract.get_children(ContractSubject): + self.assertEqual(len(child_contractSubject.get_filters()), 2, + "num of filters in contract subject did not match " + child_contractSubject.name) + + existing_bds = tenant.get_children(BridgeDomain) + self.assertEquals(len(existing_bds), 0, + "bridgeDomains count did not match for the pushed config and existing config") + + existing_contexts = tenant.get_children(Context) + self.assertEquals(len(existing_contexts), 0, + "existing_contexts count did not match for the pushed config and existing config") + + def test_without_any_EPG_and_Contracts(self): + """ + push a sample config with 0 clusters, 0 policy. + check the tenant config after it is pushed to apic by tenant.get_deep() + verify the num of children expected and existing in apic for this tenant + """ + + config_file = """ + { + "clusters": [ + ], + "policies": [ + ] +} + """ + load_config = LoadConfig() + load_config.load_configFile(config_file, is_file=False) + time.sleep(5) + tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) + for tenant in tenants: + if tenant.name == 'configpush-test': + existing_filters = tenant.get_children(Filter) + self.assertEquals(len(existing_filters), 0, + "filter count did not match for the pushed config and existing config") + + app_profiles = tenant.get_children(AppProfile) + app = app_profiles[0] + existing_epgs = app.get_children(EPG) + self.assertEquals(len(existing_epgs), 0, + "epgs count did not match for the pushed config and existing config") + + existing_contracts = tenant.get_children(Contract) + self.assertEquals(len(existing_contracts), 0, + "contracts count did not match for the pushed config and existing config") + + existing_bds = tenant.get_children(BridgeDomain) + self.assertEquals(len(existing_bds), 0, + "bridgeDomains count did not match for the pushed config and existing config") + + existing_contexts = tenant.get_children(Context) + self.assertEquals(len(existing_contexts), 0, + "existing_contexts count did not match for the pushed config and existing config") + class TestCheckForAllTheJsonConfigs(unittest.TestCase): """ @@ -1047,10 +1227,10 @@ def test_configpush_test1_policies(self): tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) for tenant in tenants: if tenant.name == 'configpush_test1_policies': - tenant_existing = json.dumps(tenant.get_json()) + tenant_existing = ast.literal_eval(json.dumps(tenant.get_json())) with gzip.open('configpush_test1_policies_tenant_golden.json.gz', 'rb') as data_file: - tenant_expected = data_file.read() - self.assertEqual(DeepDiff(tenant_existing, tenant_expected), {}) + tenant_expected = ast.literal_eval(data_file.read()) + self.assertEqual(DeepDiff(tenant_existing, tenant_expected, ignore_order=True), {}) def test_configpush_test1_policies_with_useipEpgs(self): """ @@ -1065,10 +1245,10 @@ def test_configpush_test1_policies_with_useipEpgs(self): tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) for tenant in tenants: if tenant.name == 'configpush_test1_policies': - tenant_existing = json.dumps(tenant.get_json()) + tenant_existing = ast.literal_eval(json.dumps(tenant.get_json())) with gzip.open('configpush_test1_policies_with_useipEpgs_tenant_golden.json.gz', 'rb') as data_file: - tenant_expected = data_file.read() - self.assertEqual(DeepDiff(tenant_existing, tenant_expected), {}) + tenant_expected = ast.literal_eval(data_file.read()) + self.assertEqual(DeepDiff(tenant_existing, tenant_expected, ignore_order=True), {}) def test_configpush_test2_policies(self): """ @@ -1083,10 +1263,10 @@ def test_configpush_test2_policies(self): tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) for tenant in tenants: if tenant.name == 'configpush_test2_policies': - tenant_existing = json.dumps(tenant.get_json()) + tenant_existing = ast.literal_eval(json.dumps(tenant.get_json())) with gzip.open('configpush_test2_policies_tenant_golden.json.gz', 'rb') as data_file: - tenant_expected = data_file.read() - self.assertEqual(DeepDiff(tenant_existing, tenant_expected), {}) + tenant_expected = ast.literal_eval(data_file.read()) + self.assertEqual(DeepDiff(tenant_existing, tenant_expected, ignore_order=True), {}) def test_configpush_test2_policies_with_useipEpgs(self): """ @@ -1101,10 +1281,10 @@ def test_configpush_test2_policies_with_useipEpgs(self): tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) for tenant in tenants: if tenant.name == 'configpush_test2_policies': - tenant_existing = json.dumps(tenant.get_json()) + tenant_existing = ast.literal_eval(json.dumps(tenant.get_json())) with gzip.open('configpush_test2_policies_with_useipEpgs_tenant_golden.json.gz', 'rb') as data_file: - tenant_expected = data_file.read() - self.assertEqual(DeepDiff(tenant_existing, tenant_expected), {}) + tenant_expected = ast.literal_eval(data_file.read()) + self.assertEqual(DeepDiff(tenant_existing, tenant_expected, ignore_order=True), {}) def test_configpush_test3_policies(self): """ @@ -1119,10 +1299,10 @@ def test_configpush_test3_policies(self): tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) for tenant in tenants: if tenant.name == 'configpush_test3_policies': - tenant_existing = json.dumps(tenant.get_json()) + tenant_existing = ast.literal_eval(json.dumps(tenant.get_json())) with gzip.open('configpush_test3_policies_tenant_golden.json.gz', 'rb') as data_file: - tenant_expected = data_file.read() - self.assertEqual(DeepDiff(tenant_existing, tenant_expected), {}) + tenant_expected = ast.literal_eval(data_file.read()) + self.assertEqual(DeepDiff(tenant_existing, tenant_expected, ignore_order=True), {}) def test_configpush_test3_policies_with_useipEpgs(self): """ @@ -1137,15 +1317,15 @@ def test_configpush_test3_policies_with_useipEpgs(self): tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) for tenant in tenants: if tenant.name == 'configpush_test3_policies': - tenant_existing = json.dumps(tenant.get_json()) + tenant_existing = ast.literal_eval(json.dumps(tenant.get_json())) with gzip.open('configpush_test3_policies_with_useipEpgs_tenant_golden.json.gz', 'rb') as data_file: - tenant_expected = data_file.read() - self.assertEqual(DeepDiff(tenant_existing, tenant_expected), {}) + tenant_expected = ast.literal_eval(data_file.read()) + self.assertEqual(DeepDiff(tenant_existing, tenant_expected, ignore_order=True), {}) def test_configpush_test4_policies(self): """ configpush_test4_policies.json - providing configpush_test1_policies.json to apicservice and + providing configpush_test4_policies.json to apicservice and comparing with the expected json """ config_file = 'configpush_test4_policies.json.gz' @@ -1155,15 +1335,15 @@ def test_configpush_test4_policies(self): tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) for tenant in tenants: if tenant.name == 'configpush_test4_policies': - tenant_existing = json.dumps(tenant.get_json()) + tenant_existing = ast.literal_eval(json.dumps(tenant.get_json())) with gzip.open('configpush_test4_policies_tenant_golden.json.gz', 'rb') as data_file: - tenant_expected = data_file.read() - self.assertEqual(DeepDiff(tenant_existing, tenant_expected), {}) + tenant_expected = ast.literal_eval(data_file.read()) + self.assertEqual(DeepDiff(tenant_existing, tenant_expected, ignore_order=True), {}) def test_configpush_test4_policies_with_useipEpgs(self): """ configpush_test4_policies.json - providing configpush_test1_policies.json to apicservice and + providing configpush_test4_policies.json to apicservice and comparing with the expected json """ config_file = 'configpush_test4_policies.json.gz' @@ -1173,11 +1353,10 @@ def test_configpush_test4_policies_with_useipEpgs(self): tenants = Tenant.get_deep(load_config.session, names=[load_config.tool.tenant_name]) for tenant in tenants: if tenant.name == 'configpush_test4_policies': - tenant_existing = json.dumps(tenant.get_json()) + tenant_existing = ast.literal_eval(json.dumps(tenant.get_json())) with gzip.open('configpush_test4_policies_with_useipEpgs_tenant_golden.json.gz', 'rb') as data_file: - tenant_expected = data_file.read() - self.assertEqual(DeepDiff(tenant_existing, tenant_expected), {}) - + tenant_expected = ast.literal_eval(data_file.read()) + self.assertEqual(DeepDiff(tenant_existing, tenant_expected, ignore_order=True), {}) if __name__ == '__main__': configpush = unittest.TestSuite() diff --git a/applications/configpush/configpush_test1_policies_tenant_golden.json.gz b/applications/configpush/configpush_test1_policies_tenant_golden.json.gz index 34649792..633b5d00 100644 Binary files a/applications/configpush/configpush_test1_policies_tenant_golden.json.gz and b/applications/configpush/configpush_test1_policies_tenant_golden.json.gz differ diff --git a/applications/configpush/configpush_test1_policies_with_useipEpgs_tenant_golden.json.gz b/applications/configpush/configpush_test1_policies_with_useipEpgs_tenant_golden.json.gz index a54775d7..563e91d2 100644 Binary files a/applications/configpush/configpush_test1_policies_with_useipEpgs_tenant_golden.json.gz and b/applications/configpush/configpush_test1_policies_with_useipEpgs_tenant_golden.json.gz differ diff --git a/applications/configpush/configpush_test2_policies_tenant_golden.json.gz b/applications/configpush/configpush_test2_policies_tenant_golden.json.gz index addf413f..35264789 100644 Binary files a/applications/configpush/configpush_test2_policies_tenant_golden.json.gz and b/applications/configpush/configpush_test2_policies_tenant_golden.json.gz differ diff --git a/applications/configpush/configpush_test2_policies_with_useipEpgs_tenant_golden.json.gz b/applications/configpush/configpush_test2_policies_with_useipEpgs_tenant_golden.json.gz index e51b6c36..6fdea6f5 100644 Binary files a/applications/configpush/configpush_test2_policies_with_useipEpgs_tenant_golden.json.gz and b/applications/configpush/configpush_test2_policies_with_useipEpgs_tenant_golden.json.gz differ diff --git a/applications/configpush/configpush_test3_policies_tenant_golden.json.gz b/applications/configpush/configpush_test3_policies_tenant_golden.json.gz index 672038ca..8f1741ad 100644 Binary files a/applications/configpush/configpush_test3_policies_tenant_golden.json.gz and b/applications/configpush/configpush_test3_policies_tenant_golden.json.gz differ diff --git a/applications/configpush/configpush_test3_policies_with_useipEpgs_tenant_golden.json.gz b/applications/configpush/configpush_test3_policies_with_useipEpgs_tenant_golden.json.gz index 2c90aab5..eb2f71dc 100644 Binary files a/applications/configpush/configpush_test3_policies_with_useipEpgs_tenant_golden.json.gz and b/applications/configpush/configpush_test3_policies_with_useipEpgs_tenant_golden.json.gz differ diff --git a/applications/configpush/configpush_test4_policies_tenant_golden.json.gz b/applications/configpush/configpush_test4_policies_tenant_golden.json.gz index 259a9c80..52bbbbf5 100644 Binary files a/applications/configpush/configpush_test4_policies_tenant_golden.json.gz and b/applications/configpush/configpush_test4_policies_tenant_golden.json.gz differ diff --git a/applications/configpush/configpush_test4_policies_with_useipEpgs_tenant_golden.json.gz b/applications/configpush/configpush_test4_policies_with_useipEpgs_tenant_golden.json.gz index 4fcea363..892c55ad 100644 Binary files a/applications/configpush/configpush_test4_policies_with_useipEpgs_tenant_golden.json.gz and b/applications/configpush/configpush_test4_policies_with_useipEpgs_tenant_golden.json.gz differ