diff --git a/oks_cli/cache.py b/oks_cli/cache.py index a03b737..c1f3cf2 100644 --- a/oks_cli/cache.py +++ b/oks_cli/cache.py @@ -24,11 +24,12 @@ def delete_cache(force): @cache.command('kubeconfigs', help="List cached kubeconfigs") @click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer) @click.option('--cluster-name', '--name', '-c', required=False, help="Cluster Name", shell_complete=cluster_completer) -@click.option('--plain', is_flag=True, help="Plain table format") -@click.option('--msword', is_flag=True, help="Microsoft Word table format") +@click.option('--style', multiple=False, type=click.Choice(["msword", "plain"]), help="Optional table style format output") +@click.option('--plain', is_flag=True, help="Plain table format", deprecated="Use --style instead") +@click.option('--msword', is_flag=True, help="Microsoft Word table format", deprecated="Use --style instead") @click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer) @click.pass_context -def list_kubeconfigs(ctx, project_name, cluster_name, plain, msword, profile): +def list_kubeconfigs(ctx, project_name, cluster_name, style, plain, msword, profile): """Display cached kubeconfigs with expiration dates in table format.""" project_name, cluster_name, profile = ctx_update(ctx, project_name, cluster_name, profile) login_profile(profile) @@ -55,10 +56,10 @@ def list_kubeconfigs(ctx, project_name, cluster_name, plain, msword, profile): row = user, group, exp data.append({"user": user, "group": group, "expires_at": exp}) - style = None - if plain: + if style == 'plain' or plain: style = TableStyle.PLAIN_COLUMNS - if msword: + + if style == 'msword' or msword: style = TableStyle.MSWORD_FRIENDLY print_table(data, fields, style=style) diff --git a/oks_cli/cluster.py b/oks_cli/cluster.py index 352fb63..809ef0d 100644 --- a/oks_cli/cluster.py +++ b/oks_cli/cluster.py @@ -11,6 +11,7 @@ import human_readable import pathlib import prettytable +from prettytable import TableStyle import logging import yaml @@ -82,14 +83,15 @@ def cluster_logout(ctx, profile): @click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer) @click.option('--cluster-name', '--name', '-c', required=False, help="Cluster Name", shell_complete=cluster_completer) @click.option('--deleted', '-x', is_flag=True, help="List deleted clusters") # x pour "deleted" / "removed" -@click.option('--plain', is_flag=True, help="Plain table format") -@click.option('--msword', is_flag=True, help="Microsoft Word table format") +@click.option('--style', multiple=False, type=click.Choice(["msword", "plain"]), help="Optional table style format output") +@click.option('--plain', is_flag=True, help="Plain table format", deprecated="Use --style instead") +@click.option('--msword', is_flag=True, help="Microsoft Word table format", deprecated="Use --style instead") @click.option('--watch', '-w', is_flag=True, help="Watch the changes") @click.option('--output', '-o', type=click.Choice(["json", "yaml", "wide"]), help="Specify output format") @click.option('--profile', help="Configuration profile to use") @click.option('--all', '-A', is_flag=True, help="List clusters from all projects") @click.pass_context -def cluster_list(ctx, project_name, cluster_name, deleted, plain, msword, watch, output, profile, all): +def cluster_list(ctx, project_name, cluster_name, deleted, style, plain, msword, watch, output, profile, all): """Display clusters with optional filtering and real-time monitoring.""" project_name, cluster_name, profile = ctx_update(ctx, project_name, cluster_name, profile) login_profile(profile) @@ -136,11 +138,11 @@ def cluster_list(ctx, project_name, cluster_name, deleted, plain, msword, watch, table._min_width = {"CREATED": 13, "UPDATED": 13, "STATUS": 10} - if plain or watch: + if style == 'plain' or plain or watch: table.set_style(TableStyle.PLAIN_COLUMNS) - if msword: - table.set_style(prettytable.MSWORD_FRIENDLY) + if style == 'msword' or msword: + table.set_style(TableStyle.MSWORD_FRIENDLY) initial_clusters = {} diff --git a/oks_cli/project.py b/oks_cli/project.py index a92d5e0..fe6af08 100644 --- a/oks_cli/project.py +++ b/oks_cli/project.py @@ -4,8 +4,8 @@ import dateutil.parser import human_readable import prettytable -import os from prettytable import TableStyle +import os from .utils import do_request, print_output, print_table, find_project_id_by_name, get_project_id, set_project_id, \ detect_and_parse_input, transform_tuple, ctx_update, set_cluster_id, get_template, get_project_name, \ @@ -64,14 +64,15 @@ def project_logout(ctx, profile): @project.command('list', help="List all projects") @click.option('--project-name', '-p', help="Name of project", type=click.STRING, shell_complete=project_completer) @click.option('--deleted', '-x', is_flag=True, help="List deleted projects") -@click.option('--plain', is_flag=True, help="Plain table format") -@click.option('--msword', is_flag=True, help="Microsoft Word table format") +@click.option('--style', multiple=False, type=click.Choice(["msword", "plain"]), help="Optional table style format output") +@click.option('--plain', is_flag=True, help="Plain table format", deprecated="Use --style instead") +@click.option('--msword', is_flag=True, help="Microsoft Word table format", deprecated="Use --style instead") @click.option('--uuid', is_flag=True, help="Show UUID") @click.option('--watch', '-w', is_flag=True, help="Watch the changes") @click.option('--output', '-o', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json") @click.option('--profile', help="Configuration profile to use") @click.pass_context -def project_list(ctx, project_name, deleted, plain, msword, uuid, watch, output, profile): +def project_list(ctx, project_name, deleted, style, plain, msword, uuid, watch, output, profile): """List projects with filtering, formatting, and live watch capabilities.""" project_name, _, profile = ctx_update(ctx, project_name, None, profile) login_profile(profile) @@ -102,11 +103,11 @@ def project_list(ctx, project_name, deleted, plain, msword, uuid, watch, output, table._min_width = {"CREATED": 13, "UPDATED": 13, "STATUS": 10} - if plain or watch: + if style == 'plain' or plain or watch: table.set_style(TableStyle.PLAIN_COLUMNS) - if msword: - table.set_style(prettytable.MSWORD_FRIENDLY) + if style == 'msword' or msword: + table.set_style(TableStyle.MSWORD_FRIENDLY) initial_projects = {} diff --git a/tests/test_cache.py b/tests/test_cache.py index 6af023f..e2c5c72 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -17,4 +17,28 @@ def test_cache_kubeconfigs_command(mock_request, add_default_profile): runner = CliRunner() result = runner.invoke(cli, ["--profile", "default", "cache", "kubeconfigs", "-p", "test", "-c", "test"]) assert result.exit_code == 0 - assert '| user | group | expiration date |' in result.output \ No newline at end of file + assert '| user | group | expiration date |' in result.output + +@patch("oks_cli.utils.requests.request") +def test_cache_kubeconfigs_plain_deprecation(mock_request, add_default_profile): + mock_request.side_effect = [ + MagicMock(status_code=200, headers = {}, json=lambda: {"ResponseContext": {}, "Projects": [{"id": "12345"}]}), + MagicMock(status_code=200, headers = {}, json=lambda: {"ResponseContext": {}, "Clusters": [{"id": "12345"}]}) + ] + + runner = CliRunner() + result = runner.invoke(cli, ["cache", "kubeconfigs", "-p", "test", "-c", "test", "--plain"]) + assert result.exit_code == 0 + assert "DeprecationWarning: The options 'plain' is deprecated. use --style instead" + +@patch("oks_cli.utils.requests.request") +def test_cache_kubeconfigs_msword_deprecation(mock_request, add_default_profile): + mock_request.side_effect = [ + MagicMock(status_code=200, headers = {}, json=lambda: {"ResponseContext": {}, "Projects": [{"id": "12345"}]}), + MagicMock(status_code=200, headers = {}, json=lambda: {"ResponseContext": {}, "Clusters": [{"id": "12345"}]}) + ] + + runner = CliRunner() + result = runner.invoke(cli, ["cache", "kubeconfigs", "-p", "test", "-c", "test", "--msword"]) + assert result.exit_code == 0 + assert "DeprecationWarning: The options 'msword' is deprecated. use --style instead" \ No newline at end of file diff --git a/tests/test_cluster.py b/tests/test_cluster.py index b10228e..721766e 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -41,6 +41,44 @@ def test_cluster_list_command(mock_request, add_default_profile): assert result.exit_code == 0 assert '"name": "test"' in result.output +# Test the "cluster list --plain" command: verifies deprecation warning is thrown +@patch("oks_cli.utils.requests.request") +def test_cluster_list_command_plain_deprecation(mock_request, add_default_profile): + mock_request.side_effect = [ + MagicMock(status_code=200, headers = {}, json=lambda: {"ResponseContext": {}, "Projects": [{"id": "12345"}]}), + MagicMock(status_code=200, headers = {}, json=lambda: { + "ResponseContext": {}, + "Clusters": [ + {"id": "12345", "name": "test", + "statuses": {"status": "ready", + "created_at": "2019-08-24T14:15:22Z", + "updated_at": "2019-08-24T14:15:22Z"}}]}), + ] + + runner = CliRunner() + result = runner.invoke(cli, ["cluster", "list", "-p", "test", "-c", "test", '--plain']) + assert result.exit_code == 0 + assert "DeprecationWarning: The options 'plain' is deprecated. use --style instead" + +# Test the "cluster list --msword" command: verifies deprecation warning is thrown +@patch("oks_cli.utils.requests.request") +def test_cluster_list_command_msword_deprecation(mock_request, add_default_profile): + mock_request.side_effect = [ + MagicMock(status_code=200, headers = {}, json=lambda: {"ResponseContext": {}, "Projects": [{"id": "12345"}]}), + MagicMock(status_code=200, headers = {}, json=lambda: { + "ResponseContext": {}, + "Clusters": [ + {"id": "12345", "name": "test", + "statuses": {"status": "ready", + "created_at": "2019-08-24T14:15:22Z", + "updated_at": "2019-08-24T14:15:22Z"}}]}), + ] + + runner = CliRunner() + result = runner.invoke(cli, ["cluster", "list", "-p", "test", "-c", "test", '--msword']) + assert result.exit_code == 0 + assert "DeprecationWarning: The options 'msword' is deprecated. use --style instead" + # Test the "cluster list" command with all arguments: verifies that advanced filters @patch("oks_cli.utils.requests.request") def test_cluster_list_all_args(mock_request, add_default_profile): diff --git a/tests/test_project.py b/tests/test_project.py index a5fae33..077671d 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -5,6 +5,44 @@ import json # START PROJECT LIST COMMAND +# Test the "project list --plain" command: verifies deprecation warning +@patch("oks_cli.utils.requests.request") +def test_project_list_plain_deprecation_command(mock_request, add_default_profile): + mock_request.side_effect = [ + MagicMock(status_code=200, headers = {}, json=lambda: { + "ResponseContext": {}, + "Projects": [ + {"id": "12345", "name": "test", + "created_at": "2019-08-24T14:15:22Z", + "updated_at": "2019-08-24T14:15:22Z", + "status": "ready", + "region":"eu-west-2"}]}) + ] + + runner = CliRunner() + result = runner.invoke(cli, ["project", "list", '--plain']) + assert result.exit_code == 0 + assert "DeprecationWarning: The options 'plain' is deprecated. use --style instead" + +# Test the "project list --msword" command: verifies deprecation warning +@patch("oks_cli.utils.requests.request") +def test_project_list_msword_deprecation_command(mock_request, add_default_profile): + mock_request.side_effect = [ + MagicMock(status_code=200, headers = {}, json=lambda: { + "ResponseContext": {}, + "Projects": [ + {"id": "12345", "name": "test", + "created_at": "2019-08-24T14:15:22Z", + "updated_at": "2019-08-24T14:15:22Z", + "status": "ready", + "region":"eu-west-2"}]}) + ] + + runner = CliRunner() + result = runner.invoke(cli, ["project", "list", '--msword']) + assert result.exit_code == 0 + assert "DeprecationWarning: The options 'msword' is deprecated. use --style instead" + # Test the "project list" command: verifies region and profile are shown @patch("oks_cli.utils.requests.request") def test_project_list_command_with_region_and_profile(mock_request, add_default_profile):