95 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from ipaddress import ip_address, ip_network, IPv4Address, IPv4Network
 | 
						|
 | 
						|
from bundlewrap.exceptions import NoSuchGroup, NoSuchNode, BundleError
 | 
						|
from bundlewrap.utils.text import bold, red
 | 
						|
from bundlewrap.utils.ui import io
 | 
						|
 | 
						|
def resolve_identifier(repo, identifier):
 | 
						|
    """
 | 
						|
    Try to resolve an identifier (group or node). Return a set of ip
 | 
						|
    addresses valid for this identifier.
 | 
						|
    """
 | 
						|
    try:
 | 
						|
        nodes = {repo.get_node(identifier)}
 | 
						|
    except NoSuchNode:
 | 
						|
        try:
 | 
						|
            nodes = repo.nodes_in_group(identifier)
 | 
						|
        except NoSuchGroup:
 | 
						|
            try:
 | 
						|
                ip = ip_network(identifier)
 | 
						|
 | 
						|
                if isinstance(ip, IPv4Network):
 | 
						|
                    return {'ipv4': {ip}, 'ipv6': set()}
 | 
						|
                else:
 | 
						|
                    return {'ipv4': set(), 'ipv6': {ip}}
 | 
						|
            except Exception as e:
 | 
						|
                io.stderr('{x}  {t} Exception while resolving "{i}": {e}'.format(
 | 
						|
                    x=red('✘'),
 | 
						|
                    t=bold('libs.tools.resolve_identifier'),
 | 
						|
                    i=identifier,
 | 
						|
                    e=str(e),
 | 
						|
                ))
 | 
						|
                raise
 | 
						|
 | 
						|
    found_ips = set()
 | 
						|
    for node in nodes:
 | 
						|
        for interface, config in node.metadata.get('interfaces', {}).items():
 | 
						|
            for ip in config.get('ips', set()):
 | 
						|
                if '/' in ip:
 | 
						|
                    found_ips.add(ip_address(ip.split('/')[0]))
 | 
						|
                else:
 | 
						|
                    found_ips.add(ip_address(ip))
 | 
						|
 | 
						|
        if node.metadata.get('external_ipv4', None):
 | 
						|
            found_ips.add(ip_address(node.metadata.get('external_ipv4')))
 | 
						|
 | 
						|
    ip_dict = {
 | 
						|
        'ipv4': set(),
 | 
						|
        'ipv6': set(),
 | 
						|
    }
 | 
						|
 | 
						|
    for ip in found_ips:
 | 
						|
        if isinstance(ip, IPv4Address):
 | 
						|
            ip_dict['ipv4'].add(ip)
 | 
						|
        else:
 | 
						|
            ip_dict['ipv6'].add(ip)
 | 
						|
 | 
						|
    return ip_dict
 | 
						|
 | 
						|
 | 
						|
def remove_more_specific_subnets(input_subnets) -> list:
 | 
						|
    final_subnets = []
 | 
						|
 | 
						|
    for subnet in sorted(input_subnets):
 | 
						|
        source = ip_network(subnet)
 | 
						|
 | 
						|
        if not source in final_subnets:
 | 
						|
            subnet_found = False
 | 
						|
 | 
						|
            for dest_subnet in final_subnets:
 | 
						|
                if source.subnet_of(dest_subnet):
 | 
						|
                    subnet_found = True
 | 
						|
 | 
						|
            if not subnet_found:
 | 
						|
                final_subnets.append(source)
 | 
						|
 | 
						|
    out = []
 | 
						|
    for net in final_subnets:
 | 
						|
        out.append(str(net))
 | 
						|
 | 
						|
    return out
 | 
						|
 | 
						|
 | 
						|
def require_bundle(node, bundle, hint=''):
 | 
						|
    # It's considered bad style to use assert statements outside of tests.
 | 
						|
    # That's why this little helper function exists, so we have an easy
 | 
						|
    # way of defining bundle requirements in other bundles.
 | 
						|
    if not node.has_bundle(bundle):
 | 
						|
        raise BundleError(f'{node.name} requires bundle {bundle}, but wasn\'t found! {hint}')
 | 
						|
 | 
						|
 | 
						|
from shlex import quote
 | 
						|
 | 
						|
def run_as(user, command):
 | 
						|
    return f'sudo su - {user} -s /bin/bash -c {quote(command)}'
 | 
						|
 |