diff --git a/airflow-ctl/docs/images/command_hashes.txt b/airflow-ctl/docs/images/command_hashes.txt index 30e8f104adff0..7c97c49f27ad7 100644 --- a/airflow-ctl/docs/images/command_hashes.txt +++ b/airflow-ctl/docs/images/command_hashes.txt @@ -1,4 +1,4 @@ -main:3d89ac882e883c75b3bc51d71039f215 +main:649cfb54e45b91a69ad7ed19cb526e93 assets:bd74e73e54641bac100b88ca29641df2 auth:ef4122d3f5e4b2ac19cb0d3e12c8594b backfills:e0cba4448d576d1b53ea79d6dcdbe035 @@ -10,5 +10,5 @@ jobs:806174e6c9511db669705279ed6a00b9 pools:2c17a4131b6481bd8fe9120982606db2 providers:d053e6f17ff271e1e08942378344d27b variables:cd3970589b2cb1e3ebd9a0b7f2ffdf4d -version:11da98f530c37754403a87151cbe2274 +version:19f901e228111d8ba2ef47d8722f9b87 auth login:348c25d49128b6007ac97dae2ef7563f diff --git a/airflow-ctl/docs/images/output_auth.svg b/airflow-ctl/docs/images/output_auth.svg index 6667db945c139..a444c4bec80ac 100644 --- a/airflow-ctl/docs/images/output_auth.svg +++ b/airflow-ctl/docs/images/output_auth.svg @@ -80,9 +80,9 @@ - + - + Usage: airflowctl auth [-h] COMMAND ... diff --git a/airflow-ctl/docs/images/output_auth_login.svg b/airflow-ctl/docs/images/output_auth_login.svg index 5c39720038046..8df9915cbbbd4 100644 --- a/airflow-ctl/docs/images/output_auth_login.svg +++ b/airflow-ctl/docs/images/output_auth_login.svg @@ -89,9 +89,9 @@ - + - + Usage: airflowctl auth login [-h] [--api-token API_TOKEN] [--api-url API_URL]                              [-e ENV] [--password [PASSWORD]] diff --git a/airflow-ctl/docs/images/output_backfills.svg b/airflow-ctl/docs/images/output_backfills.svg index 773141475e3ae..de061add340cf 100644 --- a/airflow-ctl/docs/images/output_backfills.svg +++ b/airflow-ctl/docs/images/output_backfills.svg @@ -95,9 +95,9 @@ - + - + Usage: airflowctl backfills [-h] COMMAND ... diff --git a/airflow-ctl/docs/images/output_config.svg b/airflow-ctl/docs/images/output_config.svg index 757aa7e0e37a9..48fb30b466615 100644 --- a/airflow-ctl/docs/images/output_config.svg +++ b/airflow-ctl/docs/images/output_config.svg @@ -77,9 +77,9 @@ - + - + Usage: airflowctl config [-h] COMMAND ... diff --git a/airflow-ctl/docs/images/output_connections.svg b/airflow-ctl/docs/images/output_connections.svg index 7d9c884d7a1dc..37f7ed32760ee 100644 --- a/airflow-ctl/docs/images/output_connections.svg +++ b/airflow-ctl/docs/images/output_connections.svg @@ -95,9 +95,9 @@ - + - + Usage: airflowctl connections [-h] COMMAND ... diff --git a/airflow-ctl/docs/images/output_dag.svg b/airflow-ctl/docs/images/output_dag.svg index ece942cf11b91..1238fe8374020 100644 --- a/airflow-ctl/docs/images/output_dag.svg +++ b/airflow-ctl/docs/images/output_dag.svg @@ -113,9 +113,9 @@ - + - + Usage: airflowctl dag [-h] COMMAND ... diff --git a/airflow-ctl/docs/images/output_dagrun.svg b/airflow-ctl/docs/images/output_dagrun.svg index 20792fc3cab65..8037453db8268 100644 --- a/airflow-ctl/docs/images/output_dagrun.svg +++ b/airflow-ctl/docs/images/output_dagrun.svg @@ -80,9 +80,9 @@ - + - + Usage: airflowctl dagrun [-h] COMMAND ... diff --git a/airflow-ctl/docs/images/output_jobs.svg b/airflow-ctl/docs/images/output_jobs.svg index 619d18fec1289..e3dd4f5c38334 100644 --- a/airflow-ctl/docs/images/output_jobs.svg +++ b/airflow-ctl/docs/images/output_jobs.svg @@ -74,9 +74,9 @@ - + - + Usage: airflowctl jobs [-h] COMMAND ... diff --git a/airflow-ctl/docs/images/output_main.svg b/airflow-ctl/docs/images/output_main.svg index c12ad6e555458..ec042419aaf9a 100644 --- a/airflow-ctl/docs/images/output_main.svg +++ b/airflow-ctl/docs/images/output_main.svg @@ -19,135 +19,135 @@ font-weight: 700; } - .terminal-1120912380-matrix { + .terminal-2627781444-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1120912380-title { + .terminal-2627781444-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1120912380-r1 { fill: #c5c8c6 } + .terminal-2627781444-r1 { fill: #c5c8c6 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - Command: main + Command: main - + - - Usage: airflowctl [-h] GROUP_OR_COMMAND ... - -Positional Arguments: -  GROUP_OR_COMMAND - -    Groups -      assets        Perform Assets operations -      auth          Manage authentication for CLI. Either pass token from -                    environment variable/parameter or pass username and -                    password. -      backfills     Perform Backfills operations -      config        Perform Config operations -      connections   Perform Connections operations -      dag           Perform Dag operations -      dagrun        Perform DagRun operations -      jobs          Perform Jobs operations -      pools         Perform Pools operations -      providers     Perform Providers operations -      variables     Perform Variables operations -      version       Perform Version operations - -    Commands: - -Optional Arguments: -  -h, --help        show this help message and exit + + Usage: airflowctl [-h] GROUP_OR_COMMAND ... + +Positional Arguments: +  GROUP_OR_COMMAND + +    Groups +      assets        Perform Assets operations +      auth          Manage authentication for CLI. Either pass token from +                    environment variable/parameter or pass username and +                    password. +      backfills     Perform Backfills operations +      config        Perform Config operations +      connections   Perform Connections operations +      dag           Perform Dag operations +      dagrun        Perform DagRun operations +      jobs          Perform Jobs operations +      pools         Perform Pools operations +      providers     Perform Providers operations +      variables     Perform Variables operations + +    Commands: +      version       Show version information + +Optional Arguments: +  -h, --help        show this help message and exit diff --git a/airflow-ctl/docs/images/output_pools.svg b/airflow-ctl/docs/images/output_pools.svg index 7a5405f2b4e6c..1a6a3f8d463ab 100644 --- a/airflow-ctl/docs/images/output_pools.svg +++ b/airflow-ctl/docs/images/output_pools.svg @@ -112,6 +112,24 @@ Optional Arguments:   -h, --help  show this help message and exit + + + + + Usage: airflowctl pools [-h] COMMAND ... + +Perform Pools operations + +Positional Arguments: +  COMMAND +    create    Perform create operation +    delete    Perform delete operation +    get       Perform get operation +    list      Perform list operation +    update    Perform update operation + +Optional Arguments: +  -h, --help  show this help message and exit diff --git a/airflow-ctl/docs/images/output_providers.svg b/airflow-ctl/docs/images/output_providers.svg index 6771a1cb0b656..5eb9b6bed4956 100644 --- a/airflow-ctl/docs/images/output_providers.svg +++ b/airflow-ctl/docs/images/output_providers.svg @@ -74,9 +74,9 @@ - + - + Usage: airflowctl providers [-h] COMMAND ... diff --git a/airflow-ctl/docs/images/output_variables.svg b/airflow-ctl/docs/images/output_variables.svg index 4baba40504240..84c2b22104825 100644 --- a/airflow-ctl/docs/images/output_variables.svg +++ b/airflow-ctl/docs/images/output_variables.svg @@ -112,6 +112,24 @@ Optional Arguments:   -h, --help  show this help message and exit + + + + + Usage: airflowctl variables [-h] COMMAND ... + +Perform Variables operations + +Positional Arguments: +  COMMAND +    create    Perform create operation +    delete    Perform delete operation +    get       Perform get operation +    list      Perform list operation +    update    Perform update operation + +Optional Arguments: +  -h, --help  show this help message and exit diff --git a/airflow-ctl/docs/images/output_version.svg b/airflow-ctl/docs/images/output_version.svg index ada202db71e34..511817f589a10 100644 --- a/airflow-ctl/docs/images/output_version.svg +++ b/airflow-ctl/docs/images/output_version.svg @@ -1,4 +1,4 @@ - + - - + + - + - + - + - + - + - - - - - - - - - - - - - Command: version + Command: version - + - - Usage: airflowctl version [-h] COMMAND ... - -Perform Version operations - -Positional Arguments: -  COMMAND -    get       Perform get operation - -Optional Arguments: -  -h, --help  show this help message and exit + + Usage: airflowctl version [-h] + +Show version information + +Optional Arguments: +  -h, --help  show this help message and exit diff --git a/airflow-ctl/src/airflowctl/ctl/cli_config.py b/airflow-ctl/src/airflowctl/ctl/cli_config.py index a703b31cc2737..3e75244ab72da 100644 --- a/airflow-ctl/src/airflowctl/ctl/cli_config.py +++ b/airflow-ctl/src/airflowctl/ctl/cli_config.py @@ -352,7 +352,7 @@ def get_function_details(node: ast.FunctionDef, parent_node: ast.ClassDef) -> di with open(self.file_path, encoding="utf-8") as file: tree = ast.parse(file.read(), filename=self.file_path) - exclude_operation_names = ["LoginOperations"] + exclude_operation_names = ["LoginOperations", "VersionOperations"] exclude_method_names = [ "error", "__init__", @@ -574,10 +574,12 @@ def merge_commands( List of merged commands. """ merge_command_map = {} + new_commands: list[CLICommand] = [] for command in commands_will_be_merged: + if isinstance(command, ActionCommand): + new_commands.append(command) if isinstance(command, GroupCommand): merge_command_map[command.name] = command - new_commands: list[CLICommand] = [] merged_commands = [] # Common commands for command in base_commands: @@ -670,6 +672,13 @@ def merge_commands( help="Manage Airflow pools", subcommands=POOL_COMMANDS, ), + ActionCommand( + name="version", + help="Show version information", + description="Show version information", + func=lazy_load_command("airflowctl.ctl.commands.version_command.version_info"), + args=(), + ), GroupCommand( name="variables", help="Manage Airflow variables", diff --git a/airflow-ctl/src/airflowctl/ctl/commands/version_command.py b/airflow-ctl/src/airflowctl/ctl/commands/version_command.py new file mode 100644 index 0000000000000..2c8e103c93736 --- /dev/null +++ b/airflow-ctl/src/airflowctl/ctl/commands/version_command.py @@ -0,0 +1,31 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from __future__ import annotations + +import rich + +from airflowctl import __version__ as airflowctl_version +from airflowctl.api.client import NEW_API_CLIENT, ClientKind, provide_api_client + + +@provide_api_client(kind=ClientKind.CLI) +def version_info(arg, api_client=NEW_API_CLIENT): + """Get version information.""" + version_response = api_client.version.get() + version_dict = version_response.model_dump() + version_dict["airflowctl_version"] = airflowctl_version + rich.print(version_dict) diff --git a/airflow-ctl/tests/airflow_ctl/ctl/commands/test_version_command.py b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_version_command.py new file mode 100644 index 0000000000000..389348b4ec413 --- /dev/null +++ b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_version_command.py @@ -0,0 +1,54 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from __future__ import annotations + +from contextlib import redirect_stdout +from io import StringIO +from unittest import mock + +import pytest + +from airflowctl.api.client import Client +from airflowctl.ctl import cli_parser +from airflowctl.ctl.commands.version_command import version_info + + +@pytest.fixture +def mock_client(): + """create a mock client""" + with mock.patch("airflowctl.api.client.get_client") as mock_get_client: + client = mock.MagicMock(spec=Client) + mock_get_client.return_value.__enter__.return_value = client + + client.version.get.return_value.model_dump.return_value = { + "version": "3.1.0", + "git_version": None, + "airflowctl_version": "1.0.0", + } + + return client + + +parser = cli_parser.get_parser() + + +def test_ctl_version(mock_client): + with redirect_stdout(StringIO()) as stdout: + version_info(parser.parse_args(["version"]), api_client=mock_client) + assert "version" in stdout.getvalue() + assert "git_version" in stdout.getvalue() + assert "airflowctl_version" in stdout.getvalue()