Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ports.py 2.7KB

1 year ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import re
  2. PORT_SPEC = re.compile(
  3. "^" # Match full string
  4. "(" # External part
  5. r"(\[?(?P<host>[a-fA-F\d.:]+)\]?:)?" # Address
  6. r"(?P<ext>[\d]*)(-(?P<ext_end>[\d]+))?:" # External range
  7. ")?"
  8. r"(?P<int>[\d]+)(-(?P<int_end>[\d]+))?" # Internal range
  9. "(?P<proto>/(udp|tcp|sctp))?" # Protocol
  10. "$" # Match full string
  11. )
  12. def add_port_mapping(port_bindings, internal_port, external):
  13. if internal_port in port_bindings:
  14. port_bindings[internal_port].append(external)
  15. else:
  16. port_bindings[internal_port] = [external]
  17. def add_port(port_bindings, internal_port_range, external_range):
  18. if external_range is None:
  19. for internal_port in internal_port_range:
  20. add_port_mapping(port_bindings, internal_port, None)
  21. else:
  22. ports = zip(internal_port_range, external_range)
  23. for internal_port, external_port in ports:
  24. add_port_mapping(port_bindings, internal_port, external_port)
  25. def build_port_bindings(ports):
  26. port_bindings = {}
  27. for port in ports:
  28. internal_port_range, external_range = split_port(port)
  29. add_port(port_bindings, internal_port_range, external_range)
  30. return port_bindings
  31. def _raise_invalid_port(port):
  32. raise ValueError('Invalid port "%s", should be '
  33. '[[remote_ip:]remote_port[-remote_port]:]'
  34. 'port[/protocol]' % port)
  35. def port_range(start, end, proto, randomly_available_port=False):
  36. if not start:
  37. return start
  38. if not end:
  39. return [start + proto]
  40. if randomly_available_port:
  41. return [f'{start}-{end}' + proto]
  42. return [str(port) + proto for port in range(int(start), int(end) + 1)]
  43. def split_port(port):
  44. if hasattr(port, 'legacy_repr'):
  45. # This is the worst hack, but it prevents a bug in Compose 1.14.0
  46. # https://github.com/docker/docker-py/issues/1668
  47. # TODO: remove once fixed in Compose stable
  48. port = port.legacy_repr()
  49. port = str(port)
  50. match = PORT_SPEC.match(port)
  51. if match is None:
  52. _raise_invalid_port(port)
  53. parts = match.groupdict()
  54. host = parts['host']
  55. proto = parts['proto'] or ''
  56. internal = port_range(parts['int'], parts['int_end'], proto)
  57. external = port_range(
  58. parts['ext'], parts['ext_end'], '', len(internal) == 1)
  59. if host is None:
  60. if external is not None and len(internal) != len(external):
  61. raise ValueError('Port ranges don\'t match in length')
  62. return internal, external
  63. else:
  64. if not external:
  65. external = [None] * len(internal)
  66. elif len(internal) != len(external):
  67. raise ValueError('Port ranges don\'t match in length')
  68. return internal, [(host, ext_port) for ext_port in external]