mirror of
https://github.com/ansible-collections/community.docker.git
synced 2026-03-15 19:58:28 +00:00
Fix expose ranges handling.
This commit is contained in:
parent
b3723a30c3
commit
5e951c03fa
@ -1,3 +0,0 @@
|
||||
bugfixes:
|
||||
- "docker_container - fix ``pull`` idempotency with Docker 29.0.0 (https://github.com/ansible-collections/community.docker/pull/1192)."
|
||||
- "docker_container - fix idempotency for IPv6 addresses with Docker 29.0.0 (https://github.com/ansible-collections/community.docker/pull/1192)."
|
||||
7
changelogs/fragments/1192-docker_container.yml
Normal file
7
changelogs/fragments/1192-docker_container.yml
Normal file
@ -0,0 +1,7 @@
|
||||
bugfixes:
|
||||
- "docker_container - fix ``pull`` idempotency with Docker 29.0.0 (https://github.com/ansible-collections/community.docker/pull/1192)."
|
||||
- "docker_container - fix idempotency for IPv6 addresses with Docker 29.0.0 (https://github.com/ansible-collections/community.docker/pull/1192)."
|
||||
- "docker_container - fix handling of exposed port ranges. So far, the module used an undocumented feature of Docker that was removed from Docker 29.0.0,
|
||||
that allowed to pass the range to the deamon and let handle it. Now the module explodes ranges into a list of all contained ports, same as the
|
||||
Docker CLI does. For backwards compatibility with Docker < 29.0.0, it also explodes ranges returned by the API for existing containers so that
|
||||
comparison should only indicate a difference if the ranges actually change (https://github.com/ansible-collections/community.docker/pull/1192)."
|
||||
@ -1016,7 +1016,7 @@ def _preprocess_ports(
|
||||
else:
|
||||
port_binds = len(container_ports) * [(ipaddr,)]
|
||||
else:
|
||||
return module.fail_json(
|
||||
module.fail_json(
|
||||
msg=f'Invalid port description "{port}" - expected 1 to 3 colon-separated parts, but got {p_len}. '
|
||||
"Maybe you forgot to use square brackets ([...]) around an IPv6 address?"
|
||||
)
|
||||
@ -1037,38 +1037,43 @@ def _preprocess_ports(
|
||||
binds[idx] = bind
|
||||
values["published_ports"] = binds
|
||||
|
||||
exposed = []
|
||||
exposed: set[tuple[int, str]] = set()
|
||||
if "exposed_ports" in values:
|
||||
for port in values["exposed_ports"]:
|
||||
port = to_text(port, errors="surrogate_or_strict").strip()
|
||||
protocol = "tcp"
|
||||
matcher = re.search(r"(/.+$)", port)
|
||||
if matcher:
|
||||
protocol = matcher.group(1).replace("/", "")
|
||||
port = re.sub(r"/.+$", "", port)
|
||||
exposed.append((port, protocol))
|
||||
parts = port.split("/", maxsplit=1)
|
||||
if len(parts) == 2:
|
||||
port, protocol = parts
|
||||
parts = port.split("-", maxsplit=1)
|
||||
if len(parts) < 2:
|
||||
try:
|
||||
exposed.add((int(port), protocol))
|
||||
except ValueError as e:
|
||||
module.fail_json(msg=f"Cannot parse port {port!r}: {e}")
|
||||
else:
|
||||
try:
|
||||
start_port = int(parts[0])
|
||||
end_port = int(parts[1])
|
||||
if start_port > end_port:
|
||||
raise ValueError(
|
||||
"start port must be smaller or equal to end port."
|
||||
)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg=f"Cannot parse port range {port!r}: {e}")
|
||||
for port in range(start_port, end_port + 1):
|
||||
exposed.add((port, protocol))
|
||||
if "published_ports" in values:
|
||||
# Any published port should also be exposed
|
||||
for publish_port in values["published_ports"]:
|
||||
match = False
|
||||
if isinstance(publish_port, str) and "/" in publish_port:
|
||||
port, protocol = publish_port.split("/")
|
||||
port = int(port)
|
||||
else:
|
||||
protocol = "tcp"
|
||||
port = int(publish_port)
|
||||
for exposed_port in exposed:
|
||||
if exposed_port[1] != protocol:
|
||||
continue
|
||||
if isinstance(exposed_port[0], str) and "-" in exposed_port[0]:
|
||||
start_port, end_port = exposed_port[0].split("-")
|
||||
if int(start_port) <= port <= int(end_port):
|
||||
match = True
|
||||
elif exposed_port[0] == port:
|
||||
match = True
|
||||
if not match:
|
||||
exposed.append((port, protocol))
|
||||
values["ports"] = exposed
|
||||
exposed.add((port, protocol))
|
||||
values["ports"] = sorted(exposed)
|
||||
return values
|
||||
|
||||
|
||||
|
||||
@ -1970,10 +1970,20 @@ def _get_values_ports(
|
||||
config = container["Config"]
|
||||
|
||||
# "ExposedPorts": null returns None type & causes AttributeError - PR #5517
|
||||
expected_exposed: list[str] = []
|
||||
if config.get("ExposedPorts") is not None:
|
||||
expected_exposed = [_normalize_port(p) for p in config.get("ExposedPorts", {})]
|
||||
else:
|
||||
expected_exposed = []
|
||||
for port_and_protocol in config.get("ExposedPorts", {}):
|
||||
port, protocol = _normalize_port(port_and_protocol).rsplit("/")
|
||||
try:
|
||||
start, end = port.split("-", 1)
|
||||
start_port = int(start)
|
||||
end_port = int(end)
|
||||
for port_no in range(start_port, end_port + 1):
|
||||
expected_exposed.append(f"{port_no}/{protocol}")
|
||||
continue
|
||||
except ValueError:
|
||||
# Either it is not a range, or a broken one - in both cases, simply add the original form
|
||||
expected_exposed.append(f"{port}/{protocol}")
|
||||
|
||||
return {
|
||||
"published_ports": host_config.get("PortBindings"),
|
||||
@ -2027,17 +2037,14 @@ def _get_expected_values_ports(
|
||||
]
|
||||
expected_values["published_ports"] = expected_bound_ports
|
||||
|
||||
image_ports = []
|
||||
image_ports: set[str] = set()
|
||||
if image:
|
||||
image_exposed_ports = image["Config"].get("ExposedPorts") or {}
|
||||
image_ports = [_normalize_port(p) for p in image_exposed_ports]
|
||||
param_ports = []
|
||||
image_ports = {_normalize_port(p) for p in image_exposed_ports}
|
||||
param_ports: set[str] = set()
|
||||
if "ports" in values:
|
||||
param_ports = [
|
||||
to_text(p[0], errors="surrogate_or_strict") + "/" + p[1]
|
||||
for p in values["ports"]
|
||||
]
|
||||
result = list(set(image_ports + param_ports))
|
||||
param_ports = {f"{p[0]}/{p[1]}" for p in values["ports"]}
|
||||
result = sorted(image_ports | param_ports)
|
||||
expected_values["exposed_ports"] = result
|
||||
|
||||
if "publish_all_ports" in values:
|
||||
|
||||
@ -106,6 +106,101 @@
|
||||
force_kill: true
|
||||
register: published_ports_3
|
||||
|
||||
- name: published_ports -- port range (same range, but listed explicitly)
|
||||
community.docker.docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
exposed_ports:
|
||||
- "9001"
|
||||
- "9010"
|
||||
- "9011"
|
||||
- "9012"
|
||||
- "9013"
|
||||
- "9014"
|
||||
- "9015"
|
||||
- "9016"
|
||||
- "9017"
|
||||
- "9018"
|
||||
- "9019"
|
||||
- "9020"
|
||||
- "9021"
|
||||
- "9022"
|
||||
- "9023"
|
||||
- "9024"
|
||||
- "9025"
|
||||
- "9026"
|
||||
- "9027"
|
||||
- "9028"
|
||||
- "9029"
|
||||
- "9030"
|
||||
- "9031"
|
||||
- "9032"
|
||||
- "9033"
|
||||
- "9034"
|
||||
- "9035"
|
||||
- "9036"
|
||||
- "9037"
|
||||
- "9038"
|
||||
- "9039"
|
||||
- "9040"
|
||||
- "9041"
|
||||
- "9042"
|
||||
- "9043"
|
||||
- "9044"
|
||||
- "9045"
|
||||
- "9046"
|
||||
- "9047"
|
||||
- "9048"
|
||||
- "9049"
|
||||
- "9050"
|
||||
published_ports:
|
||||
- "9001:9001"
|
||||
- "9020:9020"
|
||||
- "9021:9021"
|
||||
- "9022:9022"
|
||||
- "9023:9023"
|
||||
- "9024:9024"
|
||||
- "9025:9025"
|
||||
- "9026:9026"
|
||||
- "9027:9027"
|
||||
- "9028:9028"
|
||||
- "9029:9029"
|
||||
- "9030:9030"
|
||||
- "9031:9031"
|
||||
- "9032:9032"
|
||||
- "9033:9033"
|
||||
- "9034:9034"
|
||||
- "9035:9035"
|
||||
- "9036:9036"
|
||||
- "9037:9037"
|
||||
- "9038:9038"
|
||||
- "9039:9039"
|
||||
- "9040:9040"
|
||||
- "9041:9041"
|
||||
- "9042:9042"
|
||||
- "9043:9043"
|
||||
- "9044:9044"
|
||||
- "9045:9045"
|
||||
- "9046:9046"
|
||||
- "9047:9047"
|
||||
- "9048:9048"
|
||||
- "9049:9049"
|
||||
- "9050:9050"
|
||||
- "9051:9051"
|
||||
- "9052:9052"
|
||||
- "9053:9053"
|
||||
- "9054:9054"
|
||||
- "9055:9055"
|
||||
- "9056:9056"
|
||||
- "9057:9057"
|
||||
- "9058:9058"
|
||||
- "9059:9059"
|
||||
- "9060:9060"
|
||||
force_kill: true
|
||||
register: published_ports_4
|
||||
|
||||
- name: cleanup
|
||||
community.docker.docker_container:
|
||||
name: "{{ cname }}"
|
||||
@ -118,6 +213,7 @@
|
||||
- published_ports_1 is changed
|
||||
- published_ports_2 is not changed
|
||||
- published_ports_3 is changed
|
||||
- published_ports_4 is not changed
|
||||
|
||||
####################################################################
|
||||
## published_ports: one-element container port range ###############
|
||||
|
||||
Loading…
Reference in New Issue
Block a user