This is an automated email from the ASF dual-hosted git repository.
kaxilnaik pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new ee83c05a367 Allow forwarding ports using "breeze run" command (#61544)
ee83c05a367 is described below
commit ee83c05a3671961c2f48149354bc6e0c45dc6d5a
Author: Kaxil Naik <[email protected]>
AuthorDate: Fri Feb 6 17:44:44 2026 +0000
Allow forwarding ports using "breeze run" command (#61544)
On many occassions, I find myself just running "breeze run airflow
standalone" to check something basic where I don't need "breeze start-airflow",
this will allow optionally forwarding ports
---
dev/breeze/doc/images/output_run.svg | 20 ++++++++++++--------
dev/breeze/doc/images/output_run.txt | 2 +-
.../src/airflow_breeze/commands/common_options.py | 6 ++++++
.../airflow_breeze/commands/developer_commands.py | 4 ++++
.../commands/developer_commands_config.py | 1 +
.../src/airflow_breeze/utils/docker_command_utils.py | 12 +++++++++---
6 files changed, 33 insertions(+), 12 deletions(-)
diff --git a/dev/breeze/doc/images/output_run.svg
b/dev/breeze/doc/images/output_run.svg
index 7a7760674f0..24ba497e4e8 100644
--- a/dev/breeze/doc/images/output_run.svg
+++ b/dev/breeze/doc/images/output_run.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 1270.0"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 1294.3999999999999"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -43,7 +43,7 @@
<defs>
<clipPath id="breeze-run-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="1219.0" />
+ <rect x="0" y="0" width="1463.0" height="1243.3999999999999" />
</clipPath>
<clipPath id="breeze-run-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -192,9 +192,12 @@
<clipPath id="breeze-run-line-48">
<rect x="0" y="1172.7" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-run-line-49">
+ <rect x="0" y="1197.1" width="1464" height="24.65"/>
+ </clipPath>
</defs>
- <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="1268" rx="8"/><text class="breeze-run-title"
fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: run</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="1292.4" rx="8"/><text class="breeze-run-title"
fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: run</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -249,11 +252,12 @@
</text><text class="breeze-run-r5" x="0" y="1044.8" textLength="12.2"
clip-path="url(#breeze-run-line-42)">│</text><text class="breeze-run-r4"
x="24.4" y="1044.8" textLength="317.2"
clip-path="url(#breeze-run-line-42)">--skip-image-upgrade-check</text><text
class="breeze-run-r1" x="414.8" y="1044.8" textLength="536.8"
clip-path="url(#breeze-run-line-42)">Skip checking if the CI image is up to date.</text><text
class="breeze-run-r5" x="1451.8" [...]
</text><text class="breeze-run-r5" x="0" y="1069.2" textLength="1464"
clip-path="url(#breeze-run-line-43)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="1069.2" textLength="12.2"
clip-path="url(#breeze-run-line-43)">
</text><text class="breeze-run-r5" x="0" y="1093.6" textLength="24.4"
clip-path="url(#breeze-run-line-44)">╭─</text><text class="breeze-run-r5"
x="24.4" y="1093.6" textLength="195.2"
clip-path="url(#breeze-run-line-44)"> Common options </text><text
class="breeze-run-r5" x="219.6" y="1093.6" textLength="1220"
clip-path="url(#breeze-run-line-44)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-run [...]
-</text><text class="breeze-run-r5" x="0" y="1118" textLength="12.2"
clip-path="url(#breeze-run-line-45)">│</text><text class="breeze-run-r4"
x="24.4" y="1118" textLength="97.6"
clip-path="url(#breeze-run-line-45)">--answer</text><text class="breeze-run-r6"
x="158.6" y="1118" textLength="24.4"
clip-path="url(#breeze-run-line-45)">-a</text><text class="breeze-run-r1"
x="207.4" y="1118" textLength="317.2"
clip-path="url(#breeze-run-line-45)">Force answer to questions.</text><
[...]
-</text><text class="breeze-run-r5" x="0" y="1142.4" textLength="12.2"
clip-path="url(#breeze-run-line-46)">│</text><text class="breeze-run-r4"
x="24.4" y="1142.4" textLength="109.8"
clip-path="url(#breeze-run-line-46)">--dry-run</text><text
class="breeze-run-r6" x="158.6" y="1142.4" textLength="24.4"
clip-path="url(#breeze-run-line-46)">-D</text><text class="breeze-run-r1"
x="207.4" y="1142.4" textLength="719.8"
clip-path="url(#breeze-run-line-46)">If dry-run is set, 
[...]
-</text><text class="breeze-run-r5" x="0" y="1166.8" textLength="12.2"
clip-path="url(#breeze-run-line-47)">│</text><text class="breeze-run-r4"
x="24.4" y="1166.8" textLength="109.8"
clip-path="url(#breeze-run-line-47)">--verbose</text><text
class="breeze-run-r6" x="158.6" y="1166.8" textLength="24.4"
clip-path="url(#breeze-run-line-47)">-v</text><text class="breeze-run-r1"
x="207.4" y="1166.8" textLength="585.6"
clip-path="url(#breeze-run-line-47)">Print verbose information
[...]
-</text><text class="breeze-run-r5" x="0" y="1191.2" textLength="12.2"
clip-path="url(#breeze-run-line-48)">│</text><text class="breeze-run-r4"
x="24.4" y="1191.2" textLength="73.2"
clip-path="url(#breeze-run-line-48)">--help</text><text class="breeze-run-r6"
x="158.6" y="1191.2" textLength="24.4"
clip-path="url(#breeze-run-line-48)">-h</text><text class="breeze-run-r1"
x="207.4" y="1191.2" textLength="329.4"
clip-path="url(#breeze-run-line-48)">Show this message and e
[...]
-</text><text class="breeze-run-r5" x="0" y="1215.6" textLength="1464"
clip-path="url(#breeze-run-line-49)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="1215.6" textLength="12.2"
clip-path="url(#breeze-run-line-49)">
+</text><text class="breeze-run-r5" x="0" y="1118" textLength="12.2"
clip-path="url(#breeze-run-line-45)">│</text><text class="breeze-run-r4"
x="24.4" y="1118" textLength="97.6"
clip-path="url(#breeze-run-line-45)">--answer</text><text class="breeze-run-r6"
x="231.8" y="1118" textLength="24.4"
clip-path="url(#breeze-run-line-45)">-a</text><text class="breeze-run-r1"
x="280.6" y="1118" textLength="317.2"
clip-path="url(#breeze-run-line-45)">Force answer to questions.</text><
[...]
+</text><text class="breeze-run-r5" x="0" y="1142.4" textLength="12.2"
clip-path="url(#breeze-run-line-46)">│</text><text class="breeze-run-r4"
x="24.4" y="1142.4" textLength="109.8"
clip-path="url(#breeze-run-line-46)">--dry-run</text><text
class="breeze-run-r6" x="231.8" y="1142.4" textLength="24.4"
clip-path="url(#breeze-run-line-46)">-D</text><text class="breeze-run-r1"
x="280.6" y="1142.4" textLength="719.8"
clip-path="url(#breeze-run-line-46)">If dry-run is set, 
[...]
+</text><text class="breeze-run-r5" x="0" y="1166.8" textLength="12.2"
clip-path="url(#breeze-run-line-47)">│</text><text class="breeze-run-r4"
x="24.4" y="1166.8" textLength="183"
clip-path="url(#breeze-run-line-47)">--forward-ports</text><text
class="breeze-run-r1" x="280.6" y="1166.8" textLength="866.2"
clip-path="url(#breeze-run-line-47)">Forward ports to host (for accessing Airflow UI/API from host machine).</text><text
class="breeze- [...]
+</text><text class="breeze-run-r5" x="0" y="1191.2" textLength="12.2"
clip-path="url(#breeze-run-line-48)">│</text><text class="breeze-run-r4"
x="24.4" y="1191.2" textLength="109.8"
clip-path="url(#breeze-run-line-48)">--verbose</text><text
class="breeze-run-r6" x="231.8" y="1191.2" textLength="24.4"
clip-path="url(#breeze-run-line-48)">-v</text><text class="breeze-run-r1"
x="280.6" y="1191.2" textLength="585.6"
clip-path="url(#breeze-run-line-48)">Print verbose information
[...]
+</text><text class="breeze-run-r5" x="0" y="1215.6" textLength="12.2"
clip-path="url(#breeze-run-line-49)">│</text><text class="breeze-run-r4"
x="24.4" y="1215.6" textLength="73.2"
clip-path="url(#breeze-run-line-49)">--help</text><text class="breeze-run-r6"
x="231.8" y="1215.6" textLength="24.4"
clip-path="url(#breeze-run-line-49)">-h</text><text class="breeze-run-r1"
x="280.6" y="1215.6" textLength="329.4"
clip-path="url(#breeze-run-line-49)">Show this message and e
[...]
+</text><text class="breeze-run-r5" x="0" y="1240" textLength="1464"
clip-path="url(#breeze-run-line-50)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="1240" textLength="12.2"
clip-path="url(#breeze-run-line-50)">
</text>
</g>
</g>
diff --git a/dev/breeze/doc/images/output_run.txt
b/dev/breeze/doc/images/output_run.txt
index b94f7717712..0f882d41568 100644
--- a/dev/breeze/doc/images/output_run.txt
+++ b/dev/breeze/doc/images/output_run.txt
@@ -1 +1 @@
-102bff8e1fa8eb11f76db9289c4e1e97
+d688a631859f6a913f3dd7dd5a7b52d3
diff --git a/dev/breeze/src/airflow_breeze/commands/common_options.py
b/dev/breeze/src/airflow_breeze/commands/common_options.py
index d76feb7129c..1fda79b50ea 100644
--- a/dev/breeze/src/airflow_breeze/commands/common_options.py
+++ b/dev/breeze/src/airflow_breeze/commands/common_options.py
@@ -185,6 +185,12 @@ option_dry_run = click.option(
option_forward_credentials = click.option(
"-f", "--forward-credentials", help="Forward local credentials to
container when running.", is_flag=True
)
+option_forward_ports = click.option(
+ "--forward-ports",
+ is_flag=True,
+ default=False,
+ help="Forward ports to host (for accessing Airflow UI/API from host
machine).",
+)
option_excluded_providers = click.option(
"--excluded-providers",
help="JSON-string of dictionary containing excluded providers per python
version ({'3.12': ['provider']})",
diff --git a/dev/breeze/src/airflow_breeze/commands/developer_commands.py
b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
index 31a2eafc4d6..f75d9bb4690 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
@@ -51,6 +51,7 @@ from airflow_breeze.commands.common_options import (
option_excluded_providers,
option_force_lowest_dependencies,
option_forward_credentials,
+ option_forward_ports,
option_github_repository,
option_include_not_ready_providers,
option_include_removed_providers,
@@ -1067,6 +1068,7 @@ def doctor(ctx):
@option_dry_run
@option_force_build
@option_forward_credentials
+@option_forward_ports
@option_github_repository
@option_mysql_version
@option_platform_single
@@ -1086,6 +1088,7 @@ def run(
docker_host: str | None,
force_build: bool,
forward_credentials: bool,
+ forward_ports: bool,
github_repository: str,
mysql_version: str,
platform: str | None,
@@ -1181,6 +1184,7 @@ def run(
command=full_command,
# Always preserve the backend specified by user (or resolved from
default)
preserve_backend=True,
+ forward_ports=forward_ports,
)
# Clean up ownership
diff --git
a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
index 84422305cce..3dcb43962d5 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
@@ -296,6 +296,7 @@ DEVELOPER_PARAMETERS: dict[str, list[dict[str, str |
list[str]]]] = {
"--backend",
"--postgres-version",
"--mysql-version",
+ "--forward-ports",
"--tty",
],
},
diff --git a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
index dc0bf13d0cf..8e01428c0fa 100644
--- a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
+++ b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
@@ -772,6 +772,7 @@ def execute_command_in_shell(
output: Output | None = None,
signal_error: bool = True,
preserve_backend: bool = False,
+ forward_ports: bool = False,
) -> RunCommandResult:
"""Executes command in shell.
@@ -781,7 +782,7 @@ def execute_command_in_shell(
* backend - to force sqlite backend (unless preserve_backend=True)
* clean_sql_db=True - to clean the sqlite DB
* forward_ports=False - to avoid forwarding ports from the container to
the host - again that will
- allow to avoid clashes with other commands and opened breeze shell
+ allow to avoid clashes with other commands and opened breeze shell
(unless forward_ports=True is passed)
* project_name - to avoid name clashes with default "breeze" project name
used
* quiet=True - avoid displaying all "interactive" parts of Breeze:
ASCIIART, CHEATSHEET, some diagnostics
* skip_environment_initialization - to avoid initializing interactive
environment
@@ -797,10 +798,12 @@ def execute_command_in_shell(
:param output: output configuration
:param signal_error: whether to signal error
:param preserve_backend: if True, preserve the backend specified in
shell_params instead of forcing sqlite
+ :param forward_ports: if True, keep port forwarding enabled (for accessing
services from host)
"""
if not preserve_backend:
shell_params.backend = "sqlite"
- shell_params.forward_ports = False
+ if not forward_ports:
+ shell_params.forward_ports = False
shell_params.project_name = project_name
shell_params.quiet = True
shell_params.skip_environment_initialization = True
@@ -810,7 +813,10 @@ def execute_command_in_shell(
get_console().print("[warning]Sqlite DB is cleaned[/]")
else:
get_console().print(f"[info]Using backend:
{shell_params.backend}[/]")
- get_console().print("[warning]Disabled port forwarding[/]")
+ if forward_ports:
+ get_console().print("[info]Port forwarding enabled[/]")
+ else:
+ get_console().print("[warning]Disabled port forwarding[/]")
get_console().print(f"[warning]Project name set to: {project_name}[/]")
get_console().print("[warning]Forced quiet mode[/]")
get_console().print("[warning]Forced skipping environment
initialization[/]")