This is an automated email from the ASF dual-hosted git repository.
potiuk 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 9f874c3a6f6 Add 'breeze k8s dev' command for hot-reloading DAGs and
core sources (#40005) (#59747)
9f874c3a6f6 is described below
commit 9f874c3a6f65efdbf84deaefe18c62a4851eeb56
Author: Aaron Chen <[email protected]>
AuthorDate: Fri Dec 26 07:16:18 2025 +0800
Add 'breeze k8s dev' command for hot-reloading DAGs and core sources
(#40005) (#59747)
* Add 'breeze k8s dev' command for hot-reloading DAGs and core sources
(#40005)
* fix CI test error
* Add Kubernetes development output files and update documentation
- Updated output_k8s.txt with new hash value.
- Added output_k8s_dev.svg for visual representation of the 'k8s dev'
command usage.
- Created output_k8s_dev.txt with corresponding hash for the new SVG output.
* Update documentation for Breeze test commands
* update output files and add log level parameter to Kubernetes commands
---
contributing-docs/testing/k8s_tests.rst | 20 ++
dev/breeze/doc/05_test_commands.rst | 27 +++
dev/breeze/doc/images/output_k8s.svg | 40 ++--
dev/breeze/doc/images/output_k8s.txt | 2 +-
dev/breeze/doc/images/output_k8s_dev.svg | 188 ++++++++++++++++
dev/breeze/doc/images/output_k8s_dev.txt | 1 +
.../output_setup_check-all-params-in-groups.svg | 4 +-
.../output_setup_check-all-params-in-groups.txt | 2 +-
.../output_setup_regenerate-command-images.svg | 4 +-
.../output_setup_regenerate-command-images.txt | 2 +-
.../airflow_breeze/commands/kubernetes_commands.py | 242 ++++++++++++++++++++-
.../commands/kubernetes_commands_config.py | 17 ++
dev/breeze/src/airflow_breeze/global_constants.py | 3 +
.../src/airflow_breeze/utils/kubernetes_utils.py | 20 ++
14 files changed, 548 insertions(+), 24 deletions(-)
diff --git a/contributing-docs/testing/k8s_tests.rst
b/contributing-docs/testing/k8s_tests.rst
index 4a16bae3249..bfb823cf828 100644
--- a/contributing-docs/testing/k8s_tests.rst
+++ b/contributing-docs/testing/k8s_tests.rst
@@ -121,6 +121,26 @@ you need to deploy Airflow with the ``--executor
KubernetesExecutor`` flag.
breeze k8s deploy-airflow --executor KubernetesExecutor
+Hot-reloading DAGs and core sources
+-----------------------------------
+
+If you want to iterate on DAGs or core sources without rebuilding images, run
``breeze k8s dev`` after the
+cluster is deployed. It starts a skaffold loop that syncs local changes under
``dags/`` and
+``airflow-core/src/airflow`` into the running pods. Scheduler, triggerer, and
dag-processor run in dev
+hot-reload mode; the API server and webserver UI are not hot-reloaded by
default.
+
+.. code-block:: bash
+
+ breeze k8s dev
+
+If skaffold cannot find the running pods (for example if the release was
deployed outside skaffold),
+rerun with ``--deploy`` so it upgrades the Helm release and manages the
resources:
+
+.. code-block:: bash
+
+ breeze k8s dev --deploy
+
+
Running tests with Kubernetes Cluster
-------------------------------------
diff --git a/dev/breeze/doc/05_test_commands.rst
b/dev/breeze/doc/05_test_commands.rst
index 9b062a1b2d2..5ae0372978f 100644
--- a/dev/breeze/doc/05_test_commands.rst
+++ b/dev/breeze/doc/05_test_commands.rst
@@ -424,6 +424,7 @@ You can:
* Manage KinD Kubernetes cluster and upload image and deploy Airflow to KinD
cluster via
``breeze k8s create-cluster``, ``breeze k8s configure-cluster``, ``breeze
k8s deploy-airflow``, ``breeze k8s status``,
``breeze k8s upload-k8s-image``, ``breeze k8s delete-cluster`` commands
+* Hot-reload DAGs and core sources (scheduler/triggerer/dag-processor) with
``breeze k8s dev`` (skaffold sync)
* Run Kubernetes tests specified with ``breeze k8s tests`` command
* Run complete test run with ``breeze k8s run-complete-tests`` - performing
the full cycle of creating
cluster, uploading the image, deploying airflow, running tests and deleting
the cluster
@@ -547,6 +548,32 @@ All parameters of the command are here:
:width: 100%
:alt: Breeze k8s deploy-airflow
+Hot-reloading DAGs and core sources
+...................................
+
+After deploying Airflow you can run ``breeze k8s dev`` to sync local ``dags/``
and
+``airflow-core/src/airflow`` changes into running pods without rebuilding
images. Scheduler,
+triggerer, and dag-processor run in dev hot-reload mode; the API server and
webserver UI are not
+hot-reloaded by default.
+
+.. code-block:: bash
+
+ breeze k8s dev
+
+If skaffold cannot find the pods (for example if the release was deployed
outside skaffold), rerun with
+``--deploy`` so it upgrades the Helm release and manages the resources:
+
+.. code-block:: bash
+
+ breeze k8s dev --deploy
+
+All parameters of the command are here:
+
+.. image:: ./images/output_k8s_dev.svg
+ :target:
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/images/output_k8s_dev.svg
+ :width: 100%
+ :alt: Breeze k8s dev
+
Checking status of the K8S cluster
..................................
diff --git a/dev/breeze/doc/images/output_k8s.svg
b/dev/breeze/doc/images/output_k8s.svg
index 38d7f5afc95..27ac395e5d4 100644
--- a/dev/breeze/doc/images/output_k8s.svg
+++ b/dev/breeze/doc/images/output_k8s.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 782.0"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 830.8"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -43,7 +43,7 @@
<defs>
<clipPath id="breeze-k8s-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="731.0" />
+ <rect x="0" y="0" width="1463.0" height="779.8" />
</clipPath>
<clipPath id="breeze-k8s-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -132,9 +132,15 @@
<clipPath id="breeze-k8s-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-k8s-line-29">
+ <rect x="0" y="709.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-line-30">
+ <rect x="0" y="733.5" 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="780" rx="8"/><text class="breeze-k8s-title"
fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: k8s</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="828.8" rx="8"/><text class="breeze-k8s-title"
fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: k8s</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -161,19 +167,21 @@
</text><text class="breeze-k8s-r5" x="0" y="361.6" textLength="12.2"
clip-path="url(#breeze-k8s-line-14)">│</text><text class="breeze-k8s-r4"
x="24.4" y="361.6" textLength="207.4"
clip-path="url(#breeze-k8s-line-14)">build-k8s-image  </text><text
class="breeze-k8s-r1" x="256.2" y="361.6" textLength="1183.4"
clip-path="url(#breeze-k8s-line-14)">Build k8s-ready airflow image (optionally all images in parallel).     
[...]
</text><text class="breeze-k8s-r5" x="0" y="386" textLength="12.2"
clip-path="url(#breeze-k8s-line-15)">│</text><text class="breeze-k8s-r4"
x="24.4" y="386" textLength="207.4"
clip-path="url(#breeze-k8s-line-15)">upload-k8s-image </text><text
class="breeze-k8s-r1" x="256.2" y="386" textLength="1183.4"
clip-path="url(#breeze-k8s-line-15)">Upload k8s-ready airflow image to the KinD cluster (optionally to all clusters in 
[...]
</text><text class="breeze-k8s-r5" x="0" y="410.4" textLength="12.2"
clip-path="url(#breeze-k8s-line-16)">│</text><text class="breeze-k8s-r4"
x="24.4" y="410.4" textLength="207.4"
clip-path="url(#breeze-k8s-line-16)">deploy-airflow   </text><text
class="breeze-k8s-r1" x="256.2" y="410.4" textLength="1183.4"
clip-path="url(#breeze-k8s-line-16)">Deploy airflow image to the current KinD cluster (or all clusters).  &#
[...]
-</text><text class="breeze-k8s-r5" x="0" y="434.8" textLength="12.2"
clip-path="url(#breeze-k8s-line-17)">│</text><text class="breeze-k8s-r4"
x="24.4" y="434.8" textLength="207.4"
clip-path="url(#breeze-k8s-line-17)">delete-cluster   </text><text
class="breeze-k8s-r1" x="256.2" y="434.8" textLength="1183.4"
clip-path="url(#breeze-k8s-line-17)">Delete the current KinD Cluster (optionally all clusters).      &#
[...]
-</text><text class="breeze-k8s-r5" x="0" y="459.2" textLength="1464"
clip-path="url(#breeze-k8s-line-18)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-k8s-r1" x="1464" y="459.2" textLength="12.2"
clip-path="url(#breeze-k8s-line-18)">
-</text><text class="breeze-k8s-r5" x="0" y="483.6" textLength="24.4"
clip-path="url(#breeze-k8s-line-19)">╭─</text><text class="breeze-k8s-r5"
x="24.4" y="483.6" textLength="305"
clip-path="url(#breeze-k8s-line-19)"> K8S inspection commands </text><text
class="breeze-k8s-r5" x="329.4" y="483.6" textLength="1110.2"
clip-path="url(#breeze-k8s-line-19)">───────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-k [...]
-</text><text class="breeze-k8s-r5" x="0" y="508" textLength="12.2"
clip-path="url(#breeze-k8s-line-20)">│</text><text class="breeze-k8s-r4"
x="24.4" y="508" textLength="97.6"
clip-path="url(#breeze-k8s-line-20)">status  </text><text
class="breeze-k8s-r1" x="146.4" y="508" textLength="1293.2"
clip-path="url(#breeze-k8s-line-20)">Check status of the current cluster and airflow deployed to it (optionally all clusters
[...]
-</text><text class="breeze-k8s-r5" x="0" y="532.4" textLength="12.2"
clip-path="url(#breeze-k8s-line-21)">│</text><text class="breeze-k8s-r4"
x="24.4" y="532.4" textLength="97.6"
clip-path="url(#breeze-k8s-line-21)">logs    </text><text
class="breeze-k8s-r1" x="146.4" y="532.4" textLength="463.6"
clip-path="url(#breeze-k8s-line-21)">Dump k8s logs to ${TMP_DIR}/kind_logs_</text><text
class="breeze-k8s-r7" x="610" y="532.4" textLength="170.8" clip-pa [...]
-</text><text class="breeze-k8s-r5" x="0" y="556.8" textLength="1464"
clip-path="url(#breeze-k8s-line-22)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-k8s-r1" x="1464" y="556.8" textLength="12.2"
clip-path="url(#breeze-k8s-line-22)">
-</text><text class="breeze-k8s-r5" x="0" y="581.2" textLength="24.4"
clip-path="url(#breeze-k8s-line-23)">╭─</text><text class="breeze-k8s-r5"
x="24.4" y="581.2" textLength="268.4"
clip-path="url(#breeze-k8s-line-23)"> K8S testing commands </text><text
class="breeze-k8s-r5" x="292.8" y="581.2" textLength="1146.8"
clip-path="url(#breeze-k8s-line-23)">──────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze [...]
-</text><text class="breeze-k8s-r5" x="0" y="605.6" textLength="12.2"
clip-path="url(#breeze-k8s-line-24)">│</text><text class="breeze-k8s-r4"
x="24.4" y="605.6" textLength="219.6"
clip-path="url(#breeze-k8s-line-24)">tests             </text><text
class="breeze-k8s-r1" x="268.4" y="605.6" textLength="1171.2"
clip-path="url(#breeze-k8s-line-24)">Run tests against the current KinD cluster (o
[...]
-</text><text class="breeze-k8s-r5" x="0" y="630" textLength="12.2"
clip-path="url(#breeze-k8s-line-25)">│</text><text class="breeze-k8s-r4"
x="24.4" y="630" textLength="219.6"
clip-path="url(#breeze-k8s-line-25)">run-complete-tests</text><text
class="breeze-k8s-r1" x="268.4" y="630" textLength="1171.2"
clip-path="url(#breeze-k8s-line-25)">Run complete k8s tests consisting of: creating cluster, building and uploading image, deplo
[...]
-</text><text class="breeze-k8s-r5" x="0" y="654.4" textLength="12.2"
clip-path="url(#breeze-k8s-line-26)">│</text><text class="breeze-k8s-r1"
x="268.4" y="654.4" textLength="1171.2"
clip-path="url(#breeze-k8s-line-26)">airflow, running tests and deleting clusters (optionally for all clusters in parallel).         </text><text
class="breeze-k8s-r5" x="1451.8" y="654.4" textLength="12.2" cli [...]
-</text><text class="breeze-k8s-r5" x="0" y="678.8" textLength="12.2"
clip-path="url(#breeze-k8s-line-27)">│</text><text class="breeze-k8s-r4"
x="24.4" y="678.8" textLength="219.6"
clip-path="url(#breeze-k8s-line-27)">shell             </text><text
class="breeze-k8s-r1" x="268.4" y="678.8" textLength="1171.2"
clip-path="url(#breeze-k8s-line-27)">Run shell environment for the current KinD cl
[...]
-</text><text class="breeze-k8s-r5" x="0" y="703.2" textLength="12.2"
clip-path="url(#breeze-k8s-line-28)">│</text><text class="breeze-k8s-r4"
x="24.4" y="703.2" textLength="219.6"
clip-path="url(#breeze-k8s-line-28)">k9s               </text><text
class="breeze-k8s-r1" x="268.4" y="703.2" textLength="1171.2"
clip-path="url(#breeze-k8s-line-28)">Run k9s tool. You can pass any k9s&
[...]
-</text><text class="breeze-k8s-r5" x="0" y="727.6" textLength="1464"
clip-path="url(#breeze-k8s-line-29)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-k8s-r1" x="1464" y="727.6" textLength="12.2"
clip-path="url(#breeze-k8s-line-29)">
+</text><text class="breeze-k8s-r5" x="0" y="434.8" textLength="12.2"
clip-path="url(#breeze-k8s-line-17)">│</text><text class="breeze-k8s-r4"
x="24.4" y="434.8" textLength="207.4"
clip-path="url(#breeze-k8s-line-17)">dev              </text><text
class="breeze-k8s-r1" x="256.2" y="434.8" textLength="1183.4"
clip-path="url(#breeze-k8s-line-17)">Run skaffold dev loop to sync dags and
[...]
+</text><text class="breeze-k8s-r5" x="0" y="459.2" textLength="12.2"
clip-path="url(#breeze-k8s-line-18)">│</text><text class="breeze-k8s-r1"
x="256.2" y="459.2" textLength="1183.4"
clip-path="url(#breeze-k8s-line-18)">(scheduler/triggerer/dag-processor hot-reload; API server/webserver UI not by default).          </text><text
class="breeze-k8s-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#b
[...]
+</text><text class="breeze-k8s-r5" x="0" y="483.6" textLength="12.2"
clip-path="url(#breeze-k8s-line-19)">│</text><text class="breeze-k8s-r4"
x="24.4" y="483.6" textLength="207.4"
clip-path="url(#breeze-k8s-line-19)">delete-cluster   </text><text
class="breeze-k8s-r1" x="256.2" y="483.6" textLength="1183.4"
clip-path="url(#breeze-k8s-line-19)">Delete the current KinD Cluster (optionally all clusters).      &#
[...]
+</text><text class="breeze-k8s-r5" x="0" y="508" textLength="1464"
clip-path="url(#breeze-k8s-line-20)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-k8s-r1" x="1464" y="508" textLength="12.2"
clip-path="url(#breeze-k8s-line-20)">
+</text><text class="breeze-k8s-r5" x="0" y="532.4" textLength="24.4"
clip-path="url(#breeze-k8s-line-21)">╭─</text><text class="breeze-k8s-r5"
x="24.4" y="532.4" textLength="305"
clip-path="url(#breeze-k8s-line-21)"> K8S inspection commands </text><text
class="breeze-k8s-r5" x="329.4" y="532.4" textLength="1110.2"
clip-path="url(#breeze-k8s-line-21)">───────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-k [...]
+</text><text class="breeze-k8s-r5" x="0" y="556.8" textLength="12.2"
clip-path="url(#breeze-k8s-line-22)">│</text><text class="breeze-k8s-r4"
x="24.4" y="556.8" textLength="97.6"
clip-path="url(#breeze-k8s-line-22)">status  </text><text
class="breeze-k8s-r1" x="146.4" y="556.8" textLength="1293.2"
clip-path="url(#breeze-k8s-line-22)">Check status of the current cluster and airflow deployed to it (optionally all cl
[...]
+</text><text class="breeze-k8s-r5" x="0" y="581.2" textLength="12.2"
clip-path="url(#breeze-k8s-line-23)">│</text><text class="breeze-k8s-r4"
x="24.4" y="581.2" textLength="97.6"
clip-path="url(#breeze-k8s-line-23)">logs    </text><text
class="breeze-k8s-r1" x="146.4" y="581.2" textLength="463.6"
clip-path="url(#breeze-k8s-line-23)">Dump k8s logs to ${TMP_DIR}/kind_logs_</text><text
class="breeze-k8s-r7" x="610" y="581.2" textLength="170.8" clip-pa [...]
+</text><text class="breeze-k8s-r5" x="0" y="605.6" textLength="1464"
clip-path="url(#breeze-k8s-line-24)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-k8s-r1" x="1464" y="605.6" textLength="12.2"
clip-path="url(#breeze-k8s-line-24)">
+</text><text class="breeze-k8s-r5" x="0" y="630" textLength="24.4"
clip-path="url(#breeze-k8s-line-25)">╭─</text><text class="breeze-k8s-r5"
x="24.4" y="630" textLength="268.4"
clip-path="url(#breeze-k8s-line-25)"> K8S testing commands </text><text
class="breeze-k8s-r5" x="292.8" y="630" textLength="1146.8"
clip-path="url(#breeze-k8s-line-25)">──────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-k8s-r [...]
+</text><text class="breeze-k8s-r5" x="0" y="654.4" textLength="12.2"
clip-path="url(#breeze-k8s-line-26)">│</text><text class="breeze-k8s-r4"
x="24.4" y="654.4" textLength="219.6"
clip-path="url(#breeze-k8s-line-26)">tests             </text><text
class="breeze-k8s-r1" x="268.4" y="654.4" textLength="1171.2"
clip-path="url(#breeze-k8s-line-26)">Run tests against the current KinD cluster (o
[...]
+</text><text class="breeze-k8s-r5" x="0" y="678.8" textLength="12.2"
clip-path="url(#breeze-k8s-line-27)">│</text><text class="breeze-k8s-r4"
x="24.4" y="678.8" textLength="219.6"
clip-path="url(#breeze-k8s-line-27)">run-complete-tests</text><text
class="breeze-k8s-r1" x="268.4" y="678.8" textLength="1171.2"
clip-path="url(#breeze-k8s-line-27)">Run complete k8s tests consisting of: creating cluster, building and uploading image, 
[...]
+</text><text class="breeze-k8s-r5" x="0" y="703.2" textLength="12.2"
clip-path="url(#breeze-k8s-line-28)">│</text><text class="breeze-k8s-r1"
x="268.4" y="703.2" textLength="1171.2"
clip-path="url(#breeze-k8s-line-28)">airflow, running tests and deleting clusters (optionally for all clusters in parallel).         </text><text
class="breeze-k8s-r5" x="1451.8" y="703.2" textLength="12.2" cli [...]
+</text><text class="breeze-k8s-r5" x="0" y="727.6" textLength="12.2"
clip-path="url(#breeze-k8s-line-29)">│</text><text class="breeze-k8s-r4"
x="24.4" y="727.6" textLength="219.6"
clip-path="url(#breeze-k8s-line-29)">shell             </text><text
class="breeze-k8s-r1" x="268.4" y="727.6" textLength="1171.2"
clip-path="url(#breeze-k8s-line-29)">Run shell environment for the current KinD cl
[...]
+</text><text class="breeze-k8s-r5" x="0" y="752" textLength="12.2"
clip-path="url(#breeze-k8s-line-30)">│</text><text class="breeze-k8s-r4"
x="24.4" y="752" textLength="219.6"
clip-path="url(#breeze-k8s-line-30)">k9s               </text><text
class="breeze-k8s-r1" x="268.4" y="752" textLength="1171.2"
clip-path="url(#breeze-k8s-line-30)">Run k9s tool. You can pass any k9s a
[...]
+</text><text class="breeze-k8s-r5" x="0" y="776.4" textLength="1464"
clip-path="url(#breeze-k8s-line-31)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-k8s-r1" x="1464" y="776.4" textLength="12.2"
clip-path="url(#breeze-k8s-line-31)">
</text>
</g>
</g>
diff --git a/dev/breeze/doc/images/output_k8s.txt
b/dev/breeze/doc/images/output_k8s.txt
index 2014dc199a3..7967bb9bd0d 100644
--- a/dev/breeze/doc/images/output_k8s.txt
+++ b/dev/breeze/doc/images/output_k8s.txt
@@ -1 +1 @@
-753a8c2dae15310166438602584a4775
+8f44d97d272fb33b061059e6b4239497
diff --git a/dev/breeze/doc/images/output_k8s_dev.svg
b/dev/breeze/doc/images/output_k8s_dev.svg
new file mode 100644
index 00000000000..bd43ff2b65d
--- /dev/null
+++ b/dev/breeze/doc/images/output_k8s_dev.svg
@@ -0,0 +1,188 @@
+<svg class="rich-terminal" viewBox="0 0 1482 830.8"
xmlns="http://www.w3.org/2000/svg">
+ <!-- Generated with Rich https://www.textualize.io -->
+ <style>
+
+ @font-face {
+ font-family: "Fira Code";
+ src: local("FiraCode-Regular"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2")
format("woff2"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff")
format("woff");
+ font-style: normal;
+ font-weight: 400;
+ }
+ @font-face {
+ font-family: "Fira Code";
+ src: local("FiraCode-Bold"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2")
format("woff2"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff")
format("woff");
+ font-style: bold;
+ font-weight: 700;
+ }
+
+ .breeze-k8s-dev-matrix {
+ font-family: Fira Code, monospace;
+ font-size: 20px;
+ line-height: 24.4px;
+ font-variant-east-asian: full-width;
+ }
+
+ .breeze-k8s-dev-title {
+ font-size: 18px;
+ font-weight: bold;
+ font-family: arial;
+ }
+
+ .breeze-k8s-dev-r1 { fill: #c5c8c6 }
+.breeze-k8s-dev-r2 { fill: #d0b344 }
+.breeze-k8s-dev-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-k8s-dev-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-k8s-dev-r5 { fill: #868887 }
+.breeze-k8s-dev-r6 { fill: #98a84b;font-weight: bold }
+.breeze-k8s-dev-r7 { fill: #8d7b39 }
+ </style>
+
+ <defs>
+ <clipPath id="breeze-k8s-dev-clip-terminal">
+ <rect x="0" y="0" width="1463.0" height="779.8" />
+ </clipPath>
+ <clipPath id="breeze-k8s-dev-line-0">
+ <rect x="0" y="1.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-1">
+ <rect x="0" y="25.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-2">
+ <rect x="0" y="50.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-3">
+ <rect x="0" y="74.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-4">
+ <rect x="0" y="99.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-5">
+ <rect x="0" y="123.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-6">
+ <rect x="0" y="147.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-7">
+ <rect x="0" y="172.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-8">
+ <rect x="0" y="196.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-9">
+ <rect x="0" y="221.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-10">
+ <rect x="0" y="245.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-11">
+ <rect x="0" y="269.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-12">
+ <rect x="0" y="294.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-13">
+ <rect x="0" y="318.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-14">
+ <rect x="0" y="343.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-15">
+ <rect x="0" y="367.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-16">
+ <rect x="0" y="391.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-17">
+ <rect x="0" y="416.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-18">
+ <rect x="0" y="440.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-19">
+ <rect x="0" y="465.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-20">
+ <rect x="0" y="489.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-21">
+ <rect x="0" y="513.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-22">
+ <rect x="0" y="538.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-23">
+ <rect x="0" y="562.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-24">
+ <rect x="0" y="587.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-25">
+ <rect x="0" y="611.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-26">
+ <rect x="0" y="635.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-27">
+ <rect x="0" y="660.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-28">
+ <rect x="0" y="684.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-29">
+ <rect x="0" y="709.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-k8s-dev-line-30">
+ <rect x="0" y="733.5" 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="828.8" rx="8"/><text
class="breeze-k8s-dev-title" fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Command: k8s dev</text>
+ <g transform="translate(26,22)">
+ <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+ <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+ <circle cx="44" cy="0" r="7" fill="#28c840"/>
+ </g>
+
+ <g transform="translate(9, 41)"
clip-path="url(#breeze-k8s-dev-clip-terminal)">
+
+ <g class="breeze-k8s-dev-matrix">
+ <text class="breeze-k8s-dev-r1" x="1464" y="20" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-0)">
+</text><text class="breeze-k8s-dev-r2" x="12.2" y="44.4" textLength="73.2"
clip-path="url(#breeze-k8s-dev-line-1)">Usage:</text><text
class="breeze-k8s-dev-r3" x="97.6" y="44.4" textLength="170.8"
clip-path="url(#breeze-k8s-dev-line-1)">breeze k8s dev</text><text
class="breeze-k8s-dev-r1" x="280.6" y="44.4" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-1)">[</text><text class="breeze-k8s-dev-r4"
x="292.8" y="44.4" textLength="85.4" clip-path="url(#breeze-k8s-dev-line-1)
[...]
+</text><text class="breeze-k8s-dev-r1" x="1464" y="68.8" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-2)">
+</text><text class="breeze-k8s-dev-r1" x="12.2" y="93.2" textLength="1354.2"
clip-path="url(#breeze-k8s-dev-line-3)">Run skaffold dev loop to sync dags and airflow-core sources to running pods (scheduler/triggerer/dag-processor </text><text
class="breeze-k8s-dev-r1" x="1464" y="93.2" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-3)">
+</text><text class="breeze-k8s-dev-r1" x="12.2" y="117.6" textLength="634.4"
clip-path="url(#breeze-k8s-dev-line-4)">hot-reload; API server/webserver UI not by default).</text><text
class="breeze-k8s-dev-r1" x="1464" y="117.6" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-4)">
+</text><text class="breeze-k8s-dev-r1" x="1464" y="142" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-5)">
+</text><text class="breeze-k8s-dev-r5" x="0" y="166.4" textLength="24.4"
clip-path="url(#breeze-k8s-dev-line-6)">╭─</text><text
class="breeze-k8s-dev-r5" x="24.4" y="166.4" textLength="244"
clip-path="url(#breeze-k8s-dev-line-6)"> Skaffold dev flags </text><text
class="breeze-k8s-dev-r5" x="268.4" y="166.4" textLength="1171.2"
clip-path="url(#breeze-k8s-dev-line-6)">────────────────────────────────────────────────────────────────────────────────────────────────</text>
[...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="190.8" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-7)">│</text><text class="breeze-k8s-dev-r4"
x="24.4" y="190.8" textLength="97.6"
clip-path="url(#breeze-k8s-dev-line-7)">--python</text><text
class="breeze-k8s-dev-r6" x="317.2" y="190.8" textLength="24.4"
clip-path="url(#breeze-k8s-dev-line-7)">-p</text><text
class="breeze-k8s-dev-r1" x="366" y="190.8" textLength="732"
clip-path="url(#breeze-k8s-dev-line-7)">Python major/min [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="215.2" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-8)">│</text><text class="breeze-k8s-dev-r7"
x="366" y="215.2" textLength="732"
clip-path="url(#breeze-k8s-dev-line-8)">(>3.10< | 3.11 | 3.12 | 3.13)                               </text><text
[...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="239.6" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-9)">│</text><text class="breeze-k8s-dev-r5"
x="366" y="239.6" textLength="732"
clip-path="url(#breeze-k8s-dev-line-9)">[default: 3.10]                                        
[...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="264" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-10)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="264" textLength="244"
clip-path="url(#breeze-k8s-dev-line-10)">--kubernetes-version</text><text
class="breeze-k8s-dev-r1" x="366" y="264" textLength="658.8"
clip-path="url(#breeze-k8s-dev-line-10)">Kubernetes version used to create the KinD cluster of.</text><text
class="breeze-k8s-dev-r [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="288.4" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-11)">│</text><text
class="breeze-k8s-dev-r7" x="366" y="288.4" textLength="658.8"
clip-path="url(#breeze-k8s-dev-line-11)">(>v1.30.13< | v1.31.12 | v1.32.8 | v1.33.4 | v1.34.0) </text><text
class="breeze-k8s-dev-r5" x="1451.8" y="288.4" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-11)">│</text><text class="breeze-k8s-dev-
[...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="312.8" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-12)">│</text><text
class="breeze-k8s-dev-r5" x="366" y="312.8" textLength="658.8"
clip-path="url(#breeze-k8s-dev-line-12)">[default: v1.30.13]                                   </text><text
class="breeze [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="337.2" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-13)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="337.2" textLength="122"
clip-path="url(#breeze-k8s-dev-line-13)">--executor</text><text
class="breeze-k8s-dev-r1" x="366" y="337.2" textLength="1073.6"
clip-path="url(#breeze-k8s-dev-line-13)">Executor to use for a kubernetes cluster.          &#
[...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="361.6" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-14)">│</text><text
class="breeze-k8s-dev-r7" x="366" y="361.6" textLength="1073.6"
clip-path="url(#breeze-k8s-dev-line-14)">(>LocalExecutor< | KubernetesExecutor | CeleryExecutor | CeleryKubernetesExecutor |     </text><text
class="breeze-k8s-dev-r5" x="1451.8" y="361.6" textLength="12.2"
clip-path="url(#breeze-k8s- [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="386" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-15)">│</text><text
class="breeze-k8s-dev-r7" x="366" y="386" textLength="1073.6"
clip-path="url(#breeze-k8s-dev-line-15)">EdgeExecutor)                                         
[...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="410.4" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-16)">│</text><text
class="breeze-k8s-dev-r5" x="366" y="410.4" textLength="1073.6"
clip-path="url(#breeze-k8s-dev-line-16)">[default: LocalExecutor]                                      &#
[...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="434.8" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-17)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="434.8" textLength="134.2"
clip-path="url(#breeze-k8s-dev-line-17)">--log-level</text><text
class="breeze-k8s-dev-r1" x="366" y="434.8" textLength="634.4"
clip-path="url(#breeze-k8s-dev-line-17)">Log level for Airflow components when using k8s dev.</text><text
class="breeze-k8s-dev-r5" [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="459.2" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-18)">│</text><text
class="breeze-k8s-dev-r7" x="366" y="459.2" textLength="634.4"
clip-path="url(#breeze-k8s-dev-line-18)">(>INFO< | DEBUG | WARNING | ERROR | CRITICAL)       </text><text
class="breeze-k8s-dev-r5" x="1451.8" y="459.2" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-18)">│</text> [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="483.6" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-19)">│</text><text
class="breeze-k8s-dev-r5" x="366" y="483.6" textLength="634.4"
clip-path="url(#breeze-k8s-dev-line-19)">[default: INFO]                                     </text><text
class [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="508" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-20)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="508" textLength="256.2"
clip-path="url(#breeze-k8s-dev-line-20)">--use-standard-naming</text><text
class="breeze-k8s-dev-r1" x="366" y="508" textLength="244"
clip-path="url(#breeze-k8s-dev-line-20)">Use standard naming.</text><text
class="breeze-k8s-dev-r5" x="1451.8" y="508" textLength="12.2"
clip-path="url(#breeze- [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="532.4" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-21)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="532.4" textLength="268.4"
clip-path="url(#breeze-k8s-dev-line-21)">--multi-namespace-mode</text><text
class="breeze-k8s-dev-r1" x="366" y="532.4" textLength="305"
clip-path="url(#breeze-k8s-dev-line-21)">Use multi namespace mode.</text><text
class="breeze-k8s-dev-r5" x="1451.8" y="532.4" textLength="12.2" clip [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="556.8" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-22)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="556.8" textLength="134.2"
clip-path="url(#breeze-k8s-dev-line-22)">--dags-path</text><text
class="breeze-k8s-dev-r1" x="366" y="556.8" textLength="353.8"
clip-path="url(#breeze-k8s-dev-line-22)">Local dags directory to sync.</text><text
class="breeze-k8s-dev-r7" x="732" y="556.8" textLength="134.2" clip-p [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="581.2" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-23)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="581.2" textLength="134.2"
clip-path="url(#breeze-k8s-dev-line-23)">--dags-dest</text><text
class="breeze-k8s-dev-r1" x="366" y="581.2" textLength="671"
clip-path="url(#breeze-k8s-dev-line-23)">Destination path inside the Airflow container for dags.</text><text
class="breeze-k8s-dev-r7" x="1 [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="605.6" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-24)">│</text><text
class="breeze-k8s-dev-r5" x="366" y="605.6" textLength="671"
clip-path="url(#breeze-k8s-dev-line-24)">[default: /opt/airflow/dags]                           </text><text
class="breeze-k8s-dev-r5" x="1451.8" y="605.6" textLen [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="630" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-25)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="630" textLength="97.6"
clip-path="url(#breeze-k8s-dev-line-25)">--deploy</text><text
class="breeze-k8s-dev-r1" x="122" y="630" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-25)">/</text><text
class="breeze-k8s-dev-r4" x="134.2" y="630" textLength="134.2"
clip-path="url(#breeze-k8s-dev-line-25)">--no-deploy</text><text [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="654.4" textLength="1464"
clip-path="url(#breeze-k8s-dev-line-26)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-k8s-dev-r1" x="1464" y="654.4" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-26)">
+</text><text class="breeze-k8s-dev-r5" x="0" y="678.8" textLength="24.4"
clip-path="url(#breeze-k8s-dev-line-27)">╭─</text><text
class="breeze-k8s-dev-r5" x="24.4" y="678.8" textLength="195.2"
clip-path="url(#breeze-k8s-dev-line-27)"> Common options </text><text
class="breeze-k8s-dev-r5" x="219.6" y="678.8" textLength="1220"
clip-path="url(#breeze-k8s-dev-line-27)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><t
[...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="703.2" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-28)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="703.2" textLength="109.8"
clip-path="url(#breeze-k8s-dev-line-28)">--verbose</text><text
class="breeze-k8s-dev-r6" x="158.6" y="703.2" textLength="24.4"
clip-path="url(#breeze-k8s-dev-line-28)">-v</text><text
class="breeze-k8s-dev-r1" x="207.4" y="703.2" textLength="585.6"
clip-path="url(#breeze-k8s-dev-line-28)">Print  [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="727.6" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-29)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="727.6" textLength="109.8"
clip-path="url(#breeze-k8s-dev-line-29)">--dry-run</text><text
class="breeze-k8s-dev-r6" x="158.6" y="727.6" textLength="24.4"
clip-path="url(#breeze-k8s-dev-line-29)">-D</text><text
class="breeze-k8s-dev-r1" x="207.4" y="727.6" textLength="719.8"
clip-path="url(#breeze-k8s-dev-line-29)">If dry [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="752" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-30)">│</text><text
class="breeze-k8s-dev-r4" x="24.4" y="752" textLength="73.2"
clip-path="url(#breeze-k8s-dev-line-30)">--help</text><text
class="breeze-k8s-dev-r6" x="158.6" y="752" textLength="24.4"
clip-path="url(#breeze-k8s-dev-line-30)">-h</text><text
class="breeze-k8s-dev-r1" x="207.4" y="752" textLength="329.4"
clip-path="url(#breeze-k8s-dev-line-30)">Show this mes [...]
+</text><text class="breeze-k8s-dev-r5" x="0" y="776.4" textLength="1464"
clip-path="url(#breeze-k8s-dev-line-31)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-k8s-dev-r1" x="1464" y="776.4" textLength="12.2"
clip-path="url(#breeze-k8s-dev-line-31)">
+</text>
+ </g>
+ </g>
+</svg>
diff --git a/dev/breeze/doc/images/output_k8s_dev.txt
b/dev/breeze/doc/images/output_k8s_dev.txt
new file mode 100644
index 00000000000..6b642713c15
--- /dev/null
+++ b/dev/breeze/doc/images/output_k8s_dev.txt
@@ -0,0 +1 @@
+99d0fd2bbb0308c67b89d704ed4b7b97
diff --git a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
index 63e5006c43d..1df98773e64 100644
--- a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
+++ b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
@@ -206,8 +206,8 @@
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="215.2" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="215.2"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">ci-image:import-mount-cache | ci-image:load | ci-image:pull | ci-image:save | ci-image:verify |   
[...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="239.6" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="239.6"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">ci:fix-ownership | ci:free-space | ci:get-workflow-info | ci:resource-check | ci:selective-check |   
[...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="264"
textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="264"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">ci:upgrade | cleanup | doctor | down | exec | generate-migration-file | k8s | k8s:build-k8s-i
[...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="288.4" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="288.4"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">k8s:configure-cluster | k8s:create-cluster | k8s:delete-cluster | k8s:deploy-airflow | k8s:k9s |   
[...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="312.8" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="312.8"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">k8s:logs | k8s:run-complete-tests | k8s:setup-env | k8s:shell | k8s:status | k8s:tests |  
[...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="288.4" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="288.4"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">k8s:configure-cluster | k8s:create-cluster | k8s:delete-cluster | k8s:deploy-airflow | k8s:dev |   
[...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="312.8" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="312.8"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">k8s:k9s | k8s:logs | k8s:run-complete-tests | k8s:setup-env | k8s:shell | k8s:status | k8s:tests
[...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="337.2" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="337.2"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">k8s:upload-k8s-image | prod-image | prod-image:build | prod-image:load | prod-image:pull |    
[...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="361.6" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="361.6"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">prod-image:save | prod-image:verify | release-management | release-management:add-back-references |    <
[...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="386"
textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="386"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">release-management:check-release-files | release-management:clean-old-provider-artifacts |         
[...]
diff --git a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
index 0e394088c98..85993056fe5 100644
--- a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
+++ b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
@@ -1 +1 @@
-c5a1381f3c729a659592af33c840201f
+7e7a7c30c1e7fdc5417d2167dff16e12
diff --git a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
index d7eb4c80afb..732444d3c66 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
@@ -216,8 +216,8 @@
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="239.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-9)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="239.6"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-9)">ci-image:import-mount-cache | ci-image:load | ci-image:pull | ci-image:save | ci-image:verify |    &
[...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="264"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-10)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="264"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-10)">ci:fix-ownership | ci:free-space | ci:get-workflow-info | ci:resource-check | ci:selective-check |  </text><text
[...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="288.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-11)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="288.4"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-11)">ci:upgrade | cleanup | doctor | down | exec | generate-migration-file | k8s | k8s:build-k8s-i
[...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="312.8"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-12)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="312.8"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-12)">k8s:configure-cluster | k8s:create-cluster | k8s:delete-cluster | k8s:deploy-airflow | k8s:k9s |   
[...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="337.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="337.2"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">k8s:logs | k8s:run-complete-tests | k8s:setup-env | k8s:shell | k8s:status | k8s:tests |   &#
[...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="312.8"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-12)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="312.8"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-12)">k8s:configure-cluster | k8s:create-cluster | k8s:delete-cluster | k8s:deploy-airflow | k8s:dev |   
[...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="337.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="337.2"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">k8s:k9s | k8s:logs | k8s:run-complete-tests | k8s:setup-env | k8s:shell | k8s:status | k8s:tests |
[...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="361.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-14)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="361.6"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-14)">k8s:upload-k8s-image | prod-image | prod-image:build | prod-image:load | prod-image:pull |    
[...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="386"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-15)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="386"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-15)">prod-image:save | prod-image:verify | release-management | release-management:add-back-references | </text><text
class="breeze- [...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="410.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="410.4"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">release-management:check-release-files | release-management:clean-old-provider-artifacts |         
[...]
diff --git a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
index 2416eaa09d1..908310fb627 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
@@ -1 +1 @@
-627080d0a4c38036722abf94230efa2f
+cafa5d4043930c4c1b8e2b2db4a12b6a
diff --git a/dev/breeze/src/airflow_breeze/commands/kubernetes_commands.py
b/dev/breeze/src/airflow_breeze/commands/kubernetes_commands.py
index 11c6e731f01..0de0496405b 100644
--- a/dev/breeze/src/airflow_breeze/commands/kubernetes_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/kubernetes_commands.py
@@ -26,8 +26,10 @@ from copy import deepcopy
from itertools import chain
from pathlib import Path
from shlex import quote
+from typing import Any
import click
+import yaml
from airflow_breeze.commands.common_options import (
option_answer,
@@ -44,9 +46,13 @@ from airflow_breeze.commands.common_options import (
)
from airflow_breeze.commands.production_image_commands import
run_build_production_image
from airflow_breeze.global_constants import (
+ AIRFLOW_SOURCES_TO,
ALLOWED_EXECUTORS,
ALLOWED_KUBERNETES_VERSIONS,
+ ALLOWED_LOG_LEVELS,
CELERY_EXECUTOR,
+ DEFAULT_ALLOWED_EXECUTOR,
+ DEFAULT_LOG_LEVEL,
KUBERNETES_EXECUTOR,
)
from airflow_breeze.params.build_prod_params import BuildProdParams
@@ -69,6 +75,7 @@ from airflow_breeze.utils.kubernetes_utils import (
get_kubernetes_port_numbers,
get_kubernetes_python_combos,
make_sure_kubernetes_tools_are_installed,
+ make_sure_skaffold_installed,
print_cluster_urls,
run_command_with_k8s_env,
set_random_cluster_ports,
@@ -80,6 +87,7 @@ from airflow_breeze.utils.parallel import (
check_async_run_results,
run_with_pool,
)
+from airflow_breeze.utils.path_utils import AIRFLOW_ROOT_PATH
from airflow_breeze.utils.recording import generating_command_images
from airflow_breeze.utils.run_utils import RunCommandResult,
check_if_image_exists, run_command
@@ -128,9 +136,17 @@ option_executor = click.option(
help="Executor to use for a kubernetes cluster.",
type=CacheableChoice(ALLOWED_EXECUTORS),
show_default=True,
- default=CacheableDefault(ALLOWED_EXECUTORS[0]),
+ default=CacheableDefault(DEFAULT_ALLOWED_EXECUTOR),
envvar="EXECUTOR",
)
+option_log_level = click.option(
+ "--log-level",
+ help="Log level for Airflow components when using k8s dev.",
+ type=CacheableChoice(ALLOWED_LOG_LEVELS),
+ show_default=True,
+ default=CacheableDefault(DEFAULT_LOG_LEVEL),
+ envvar="LOG_LEVEL",
+)
option_force_recreate_cluster = click.option(
"--force-recreate-cluster",
help="Force recreation of the cluster even if it is already created.",
@@ -165,6 +181,26 @@ option_multi_namespace_mode = click.option(
is_flag=True,
envvar="MULTI_NAMESPACE_MODE",
)
+option_dags_path = click.option(
+ "--dags-path",
+ help="Local dags directory to sync.",
+ type=click.Path(file_okay=False, dir_okay=True, path_type=Path),
+ default="dags",
+ show_default=True,
+)
+option_dags_dest = click.option(
+ "--dags-dest",
+ help="Destination path inside the Airflow container for dags.",
+ default="/opt/airflow/dags",
+ show_default=True,
+)
+option_skaffold_deploy = click.option(
+ "--deploy/--no-deploy",
+ help="Let skaffold deploy/upgrade Airflow via Helm.",
+ default=False,
+ show_default=True,
+ envvar="SKAFFOLD_DEPLOY",
+)
option_rebuild_base_image = click.option(
"--rebuild-base-image",
help="Rebuilds base Airflow image before building K8S image.",
@@ -804,6 +840,100 @@ HELM_AIRFLOW_NAMESPACE = "airflow"
TEST_NAMESPACE = "test-namespace"
+def _build_skaffold_config(
+ python: str,
+ kubernetes_version: str,
+ executor: str,
+ use_standard_naming: bool,
+ multi_namespace_mode: bool,
+ dags_relative_path: str,
+ dags_dest: str,
+ log_level: str,
+) -> dict[str, Any]:
+ from packaging.version import Version
+
+ params = BuildProdParams(python=python)
+ use_flask_appbuilder = Version(python) < Version("3.13")
+ if use_flask_appbuilder:
+ auth_manager =
"airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager"
+ else:
+ auth_manager =
"airflow.api_fastapi.auth.managers.simple.simple_auth_manager.SimpleAuthManager"
+ _, api_server_port = get_kubernetes_port_numbers(python=python,
kubernetes_version=kubernetes_version)
+ set_values: dict[str, object] = {
+ "defaultAirflowRepository": params.airflow_image_kubernetes,
+ "defaultAirflowTag": "latest",
+ "images.airflow.repository": params.airflow_image_kubernetes,
+ "images.airflow.tag": "latest",
+ "config.logging.logging_level": log_level,
+ "executor": executor,
+ "airflowVersion": params.airflow_semver_version,
+ "config.api_auth.jwt_secret": "foo",
+ "config.core.auth_manager": auth_manager,
+ "config.api.base_url": f"http://localhost:{api_server_port}",
+ }
+ if multi_namespace_mode:
+ set_values["multiNamespaceMode"] = True
+ if not use_flask_appbuilder:
+ set_values["webserver.defaultUser.enabled"] = False
+ if use_standard_naming:
+ set_values["useStandardNaming"] = True
+ sync_entries: list[dict[str, str]] = []
+ sync_entry: dict[str, str] = {
+ "src": f"{dags_relative_path}/**",
+ "dest": dags_dest,
+ }
+ if dags_relative_path != ".":
+ sync_entry["strip"] = f"{dags_relative_path}/"
+ dependencies_paths = [f"{dags_relative_path}/**"]
+ else:
+ dependencies_paths = ["**"]
+ sync_entries.append(sync_entry)
+ core_relative_path = "airflow-core/src/airflow"
+ core_dest = f"{AIRFLOW_SOURCES_TO}/airflow-core/src/airflow"
+ sync_entries.append(
+ {
+ "src": f"{core_relative_path}/**",
+ "dest": core_dest,
+ "strip": f"{core_relative_path}/",
+ }
+ )
+ if dependencies_paths != ["**"]:
+ dependencies_paths.append(f"{core_relative_path}/**")
+ return {
+ "apiVersion": "skaffold/v4beta13",
+ "kind": "Config",
+ "metadata": {"name": "airflow-dags-dev"},
+ "build": {
+ "tagPolicy": {"envTemplate": {"template": "latest"}},
+ "artifacts": [
+ {
+ "image": params.airflow_image_kubernetes,
+ "context": AIRFLOW_ROOT_PATH.as_posix(),
+ "custom": {
+ "buildCommand": "true",
+ "dependencies": {"paths": dependencies_paths},
+ },
+ "sync": {"manual": sync_entries},
+ }
+ ],
+ "local": {"push": False},
+ },
+ "deploy": {
+ "helm": {
+ "releases": [
+ {
+ "name": "airflow",
+ "chartPath": CHART_PATH.as_posix(),
+ "namespace": HELM_AIRFLOW_NAMESPACE,
+ "skipBuildDependencies": True,
+ "setValues": set_values,
+ }
+ ]
+ }
+ },
+ }
+
+
def _recreate_namespaces(
python: str,
kubernetes_version: str,
@@ -1256,6 +1386,116 @@ def deploy_airflow(
sys.exit(return_code)
+@kubernetes_group.command(
+ name="dev",
+ help=(
+ "Run skaffold dev loop to sync dags and airflow-core sources to
running pods "
+ "(scheduler/triggerer/dag-processor hot-reload; API server/webserver
UI not by default)."
+ ),
+ context_settings=dict(
+ ignore_unknown_options=True,
+ ),
+)
+@option_python
+@option_kubernetes_version
+@option_executor
+@option_log_level
+@option_use_standard_naming
+@option_multi_namespace_mode
+@option_dags_path
+@option_dags_dest
+@option_skaffold_deploy
+@option_verbose
+@option_dry_run
[email protected]("skaffold_args", nargs=-1, type=click.UNPROCESSED)
+def dev(
+ python: str,
+ kubernetes_version: str,
+ executor: str,
+ log_level: str,
+ use_standard_naming: bool,
+ multi_namespace_mode: bool,
+ dags_path: Path,
+ dags_dest: str,
+ deploy: bool,
+ skaffold_args: tuple[str, ...],
+):
+ result = sync_virtualenv(force_venv_setup=False)
+ if result.returncode != 0:
+ sys.exit(result.returncode)
+ make_sure_kubernetes_tools_are_installed()
+ make_sure_skaffold_installed()
+ dags_path_abs = dags_path
+ if not dags_path_abs.is_absolute():
+ dags_path_abs = AIRFLOW_ROOT_PATH / dags_path_abs
+ dags_path_abs = dags_path_abs.resolve()
+ if not dags_path_abs.is_dir():
+ get_console().print(f"[error]DAGs path does not exist or is not a
directory: {dags_path_abs}")
+ sys.exit(1)
+ try:
+ dags_relative_path =
dags_path_abs.relative_to(AIRFLOW_ROOT_PATH).as_posix()
+ except ValueError:
+ get_console().print(f"[error]DAGs path must be under the Airflow
sources: {AIRFLOW_ROOT_PATH}")
+ sys.exit(1)
+ if not get_kind_cluster_config_path(python=python,
kubernetes_version=kubernetes_version).exists():
+ get_console().print(
+ f"\n[warning]Cluster for Python {python} and Kubernetes
{kubernetes_version} "
+ "has not been created yet.\n"
+ )
+ get_console().print(
+ "[info]Run: "
+ f"`breeze k8s create-cluster --python {python}
--kubernetes-version {kubernetes_version}`\n"
+ )
+ sys.exit(1)
+ skaffold_config = _build_skaffold_config(
+ python=python,
+ kubernetes_version=kubernetes_version,
+ executor=executor,
+ use_standard_naming=use_standard_naming,
+ multi_namespace_mode=multi_namespace_mode,
+ dags_relative_path=dags_relative_path,
+ dags_dest=dags_dest,
+ log_level=log_level,
+ )
+ if not deploy:
+ get_console().print(
+ "[info]Running skaffold without deploying Helm resources. "
+ "If sync cannot find pods, rerun with --deploy."
+ )
+ with tempfile.TemporaryDirectory(prefix="skaffold_") as tmp_dir:
+ dev_env_values = {
+ "scheduler": {"env": [{"name": "DEV_MODE", "value": "true"}]},
+ "triggerer": {"env": [{"name": "DEV_MODE", "value": "true"}]},
+ "dagProcessor": {"env": [{"name": "DEV_MODE", "value": "true"}]},
+ }
+ dev_env_values_path = Path(tmp_dir) / "dev-env-values.yaml"
+ dev_env_values_path.write_text(yaml.safe_dump(dev_env_values,
sort_keys=False))
+ skaffold_config["deploy"]["helm"]["releases"][0]["valuesFiles"] =
[dev_env_values_path.as_posix()]
+ skaffold_config_path = Path(tmp_dir) / "skaffold.yaml"
+ skaffold_config_path.write_text(yaml.safe_dump(skaffold_config,
sort_keys=False))
+ skaffold_command = [
+ "skaffold",
+ "dev",
+ "-f",
+ skaffold_config_path.as_posix(),
+ "--auto-build=false",
+ ]
+ if not deploy:
+ skaffold_command.append("--auto-deploy=false")
+ skaffold_command.append("--cleanup=false")
+ if skaffold_args:
+ skaffold_command.extend(skaffold_args)
+ result = run_command_with_k8s_env(
+ skaffold_command,
+ python=python,
+ kubernetes_version=kubernetes_version,
+ executor=executor,
+ check=False,
+ cwd=AIRFLOW_ROOT_PATH.as_posix(),
+ )
+ sys.exit(result.returncode)
+
+
@kubernetes_group.command(
name="k9s",
help="Run k9s tool. You can pass any k9s args as extra args.",
diff --git
a/dev/breeze/src/airflow_breeze/commands/kubernetes_commands_config.py
b/dev/breeze/src/airflow_breeze/commands/kubernetes_commands_config.py
index 1a38be39022..4a048949be8 100644
--- a/dev/breeze/src/airflow_breeze/commands/kubernetes_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/kubernetes_commands_config.py
@@ -25,6 +25,7 @@ KUBERNETES_CLUSTER_COMMANDS: dict[str, str | list[str]] = {
"build-k8s-image",
"upload-k8s-image",
"deploy-airflow",
+ "dev",
"delete-cluster",
],
}
@@ -177,6 +178,22 @@ KUBERNETES_PARAMETERS: dict[str, list[dict[str, str |
list[str]]]] = {
],
},
],
+ "breeze k8s dev": [
+ {
+ "name": "Skaffold dev flags",
+ "options": [
+ "--python",
+ "--kubernetes-version",
+ "--executor",
+ "--log-level",
+ "--use-standard-naming",
+ "--multi-namespace-mode",
+ "--dags-path",
+ "--dags-dest",
+ "--deploy",
+ ],
+ },
+ ],
"breeze k8s delete-cluster": [
{
"name": "K8S cluster delete flags",
diff --git a/dev/breeze/src/airflow_breeze/global_constants.py
b/dev/breeze/src/airflow_breeze/global_constants.py
index bb31177ee87..a632ddead65 100644
--- a/dev/breeze/src/airflow_breeze/global_constants.py
+++ b/dev/breeze/src/airflow_breeze/global_constants.py
@@ -142,6 +142,8 @@ AUTOCOMPLETE_ALL_INTEGRATIONS = sorted(
)
ALLOWED_TTY = ["auto", "enabled", "disabled"]
ALLOWED_DOCKER_COMPOSE_PROJECTS = ["breeze", "prek", "docker-compose"]
+ALLOWED_LOG_LEVELS = ["INFO", "DEBUG", "WARNING", "ERROR", "CRITICAL"]
+DEFAULT_LOG_LEVEL = ALLOWED_LOG_LEVELS[0]
# Unlike everything else, k8s versions are supported as long as 2 major cloud
providers support them.
# See:
@@ -679,6 +681,7 @@ DEFAULT_EXECUTOR = CURRENT_EXECUTORS[0]
KIND_VERSION = "v0.30.0"
HELM_VERSION = "v3.17.3"
+SKAFFOLD_VERSION = "v2.17.0"
# Initialize image build variables - Have to check if this has to go to ci
dataclass
USE_AIRFLOW_VERSION = None
diff --git a/dev/breeze/src/airflow_breeze/utils/kubernetes_utils.py
b/dev/breeze/src/airflow_breeze/utils/kubernetes_utils.py
index a3fb7d9974d..1d11e00cbdc 100644
--- a/dev/breeze/src/airflow_breeze/utils/kubernetes_utils.py
+++ b/dev/breeze/src/airflow_breeze/utils/kubernetes_utils.py
@@ -36,6 +36,7 @@ from airflow_breeze.global_constants import (
ALLOWED_ARCHITECTURES,
HELM_VERSION,
KIND_VERSION,
+ SKAFFOLD_VERSION,
)
from airflow_breeze.utils.console import Output, get_console
from airflow_breeze.utils.host_info_utils import Architecture,
get_host_architecture, get_host_os
@@ -49,6 +50,7 @@ K8S_BIN_BASE_PATH = K8S_ENV_PATH / "bin"
KIND_BIN_PATH = K8S_BIN_BASE_PATH / "kind"
KUBECTL_BIN_PATH = K8S_BIN_BASE_PATH / "kubectl"
HELM_BIN_PATH = K8S_BIN_BASE_PATH / "helm"
+SKAFFOLD_BIN_PATH = K8S_BIN_BASE_PATH / "skaffold"
PYTHON_BIN_PATH = K8S_BIN_BASE_PATH / "python"
SCRIPTS_CI_KUBERNETES_PATH = AIRFLOW_ROOT_PATH / "scripts" / "ci" /
"kubernetes"
PYPROJECT_TOML_AIRFLOW_CORE_PATH = AIRFLOW_ROOT_PATH / "airflow-core" /
"pyproject.toml"
@@ -228,6 +230,18 @@ def _download_helm_if_needed():
)
+def _download_skaffold_if_needed():
+ _download_tool_if_needed(
+ tool="skaffold",
+ version=SKAFFOLD_VERSION,
+ version_pattern=r".*v?(\d+\.\d+\.\d+).*",
+ version_flag=["version"],
+ url=f"https://storage.googleapis.com/skaffold/releases/"
+
f"{SKAFFOLD_VERSION}/skaffold-{get_host_os()}-{get_architecture_string_for_urls()}",
+ path=SKAFFOLD_BIN_PATH,
+ )
+
+
def _check_architecture_supported():
architecture, machine = get_host_architecture()
if architecture not in ALLOWED_ARCHITECTURES:
@@ -244,6 +258,12 @@ def make_sure_helm_installed():
_download_helm_if_needed()
+def make_sure_skaffold_installed():
+ K8S_CLUSTERS_PATH.mkdir(parents=True, exist_ok=True)
+ _check_architecture_supported()
+ _download_skaffold_if_needed()
+
+
def make_sure_kubernetes_tools_are_installed():
K8S_CLUSTERS_PATH.mkdir(parents=True, exist_ok=True)
_check_architecture_supported()