Skip to content

Commit

Permalink
Merge branch 'linode:dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
vshanthe authored Jul 11, 2024
2 parents 05a39c6 + 37482a2 commit b4c33e9
Show file tree
Hide file tree
Showing 35 changed files with 203 additions and 132 deletions.
34 changes: 26 additions & 8 deletions .github/workflows/e2e-suite.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
name: Integration Tests
on:
workflow_dispatch: null
workflow_dispatch:
inputs:
use_minimal_test_account:
description: 'Use minimal test account'
required: false
default: 'false'
sha:
description: 'The hash value of the commit.'
required: false
default: ''
push:
branches:
- main
Expand All @@ -9,11 +18,18 @@ jobs:
integration-tests:
name: Run integration tests
runs-on: ubuntu-latest
env:
EXIT_STATUS: 0
steps:
- name: Clone Repository
uses: actions/checkout@v3
- name: Clone Repository with SHA
if: ${{ inputs.sha != '' }}
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: 'recursive'
ref: ${{ inputs.sha }}

- name: Clone Repository without SHA
if: ${{ inputs.sha == '' }}
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: 'recursive'
Expand Down Expand Up @@ -45,20 +61,22 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Set LINODE_CLI_TOKEN
run: |
echo "LINODE_CLI_TOKEN=${{ secrets[inputs.use_minimal_test_account == 'true' && 'MINIMAL_LINODE_TOKEN' || 'LINODE_TOKEN'] }}" >> $GITHUB_ENV
- name: Run the integration test suite
run: |
timestamp=$(date +'%Y%m%d%H%M')
report_filename="${timestamp}_cli_test_report.xml"
make testint TEST_ARGS="--junitxml=${report_filename}"
env:
LINODE_CLI_TOKEN: ${{ secrets.LINODE_TOKEN }}
- name: Apply Calico Rules to LKE
if: always()
run: |
cd scripts && ./lke_calico_rules_e2e.sh
env:
LINODE_TOKEN: ${{ secrets.LINODE_TOKEN }}
LINODE_TOKEN: ${{ env.LINODE_CLI_TOKEN }}

- name: Upload test results
if: always()
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly-smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ jobs:
run: |
make smoketest
env:
LINODE_CLI_TOKEN: ${{ secrets.LINODE_TOKEN_2 }}
LINODE_CLI_TOKEN: ${{ secrets.LINODE_TOKEN }}
39 changes: 20 additions & 19 deletions linodecli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from rich.table import Column, Table

from linodecli import plugins
from linodecli.exit_codes import ExitCodes

from .arg_helpers import (
bake_command,
Expand Down Expand Up @@ -85,7 +86,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
# print version info and exit - but only if no command was given
print(f"linode-cli {VERSION}")
print(f"Built from spec version {cli.spec_version}")
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)
else:
# something else might want to parse version
# find where it was originally, as it was removed from args
Expand All @@ -96,50 +97,50 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
if parsed.command == "bake":
if parsed.action is None:
print("No spec provided, cannot bake")
sys.exit(9)
sys.exit(ExitCodes.ARGUMENT_ERROR)
bake_command(cli, parsed.action)
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)
elif cli.ops is None:
# if not spec was found and we weren't baking, we're doomed
sys.exit(3)
sys.exit(ExitCodes.ARGUMENT_ERROR)

if parsed.command == "register-plugin":
if parsed.action is None:
print("register-plugin requires a module name!")
sys.exit(9)
sys.exit(ExitCodes.ARGUMENT_ERROR)
msg, code = register_plugin(parsed.action, cli.config, cli.ops)
print(msg)
sys.exit(code)

if parsed.command == "remove-plugin":
if parsed.action is None:
print("remove-plugin requires a plugin name to remove!")
sys.exit(9)
sys.exit(ExitCodes.ARGUMENT_ERROR)
msg, code = remove_plugin(parsed.action, cli.config)
print(msg)
sys.exit(code)

if parsed.command == "completion":
print(get_completions(cli.ops, parsed.help, parsed.action))
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

# handle a help for the CLI
if parsed.command is None or (parsed.command is None and parsed.help):
parser.print_help()
print_help_default()
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

if parsed.command == "env-vars":
print_help_env_vars()
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

if parsed.command == "commands":
print_help_commands(cli.ops)
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

if parsed.command == "plugins":
print_help_plugins(cli.config)
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

# configure
if parsed.command == "configure":
Expand All @@ -151,7 +152,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
)
else:
cli.configure()
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

# block of commands for user-focused operations
if parsed.command == "set-user":
Expand All @@ -163,7 +164,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
)
else:
cli.config.set_default_user(parsed.action)
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

if parsed.command == "show-users":
if parsed.help:
Expand All @@ -177,7 +178,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
)
else:
cli.config.print_users()
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

if parsed.command == "remove-user":
if parsed.help or not parsed.action:
Expand All @@ -190,7 +191,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
)
else:
cli.config.remove_user(parsed.action)
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

# check for plugin invocation
if parsed.command not in cli.ops and parsed.command in plugins.available(
Expand All @@ -202,7 +203,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
plugin_args = argv[1:] # don't include the program name
plugin_args.remove(parsed.command) # don't include the plugin name
plugins.invoke(parsed.command, plugin_args, context)
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

# unknown commands
if (
Expand All @@ -211,7 +212,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
and parsed.command not in HELP_TOPICS
):
print(f"Unrecognized command {parsed.command}")
sys.exit(1)
sys.exit(ExitCodes.UNRECOGNIZED_COMMAND)

# handle a help for a command - either --help or no action triggers this
if (
Expand All @@ -236,10 +237,10 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
table.add_row(*row)

rprint(table)
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

if parsed.command is not None and parsed.action is not None:
if parsed.help:
print_help_action(cli, parsed.command, parsed.action)
sys.exit(0)
sys.exit(ExitCodes.SUCCESS)
cli.handle_command(parsed.command, parsed.action, args)
3 changes: 2 additions & 1 deletion linodecli/api_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from packaging import version
from requests import Response

from linodecli.exit_codes import ExitCodes
from linodecli.helpers import API_CA_PATH

from .baked.operation import (
Expand Down Expand Up @@ -394,7 +395,7 @@ def _handle_error(ctx, response):
title="errors",
to=sys.stderr,
)
sys.exit(1)
sys.exit(ExitCodes.REQUEST_FAILED)


def _check_retry(response):
Expand Down
3 changes: 2 additions & 1 deletion linodecli/arg_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import yaml

from linodecli import plugins
from linodecli.exit_codes import ExitCodes
from linodecli.helpers import (
register_args_shared,
register_debug_arg,
Expand Down Expand Up @@ -183,6 +184,6 @@ def bake_command(cli, spec_loc):
raise RuntimeError(f"Request failed to {spec_loc}")
except Exception as e:
print(f"Could not load spec: {e}")
sys.exit(2)
sys.exit(ExitCodes.REQUEST_FAILED)

cli.bake(spec)
3 changes: 2 additions & 1 deletion linodecli/baked/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from linodecli.baked.request import OpenAPIFilteringRequest, OpenAPIRequest
from linodecli.baked.response import OpenAPIResponse
from linodecli.exit_codes import ExitCodes
from linodecli.output.output_handler import OutputHandler
from linodecli.overrides import OUTPUT_OVERRIDES

Expand Down Expand Up @@ -586,7 +587,7 @@ def _validate_parent_child_conflicts(self, parsed: argparse.Namespace):
file=sys.stderr,
)

sys.exit(2)
sys.exit(ExitCodes.ARGUMENT_ERROR)

@staticmethod
def _handle_list_items(
Expand Down
3 changes: 2 additions & 1 deletion linodecli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from linodecli.api_request import do_request, get_all_pages
from linodecli.baked import OpenAPIOperation
from linodecli.configuration import CLIConfig
from linodecli.exit_codes import ExitCodes
from linodecli.output.output_handler import OutputHandler, OutputMode

METHODS = ("get", "post", "put", "delete")
Expand Down Expand Up @@ -123,7 +124,7 @@ def handle_command(self, command, action, args):
operation = self.find_operation(command, action)
except ValueError as e:
print(e, file=sys.stderr)
sys.exit(1)
sys.exit(ExitCodes.REQUEST_FAILED)

if not self.pagination:
result = get_all_pages(self, operation, args)
Expand Down
7 changes: 4 additions & 3 deletions linodecli/configuration/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import requests

from linodecli.exit_codes import ExitCodes
from linodecli.helpers import API_CA_PATH

TOKEN_GENERATION_URL = "https://cloud.linode.com/profile/tokens"
Expand Down Expand Up @@ -59,7 +60,7 @@ def _handle_response_status(

print(f"Could not contact {response.url} - Error: {response.status_code}")
if exit_on_error:
sys.exit(4)
sys.exit(ExitCodes.REQUEST_FAILED)


# TODO: merge config do_request and cli do_request
Expand Down Expand Up @@ -243,7 +244,7 @@ def _get_token_web(base_url: str) -> Tuple[str, str]:

if username is None:
print("OAuth failed. Please try again of use a token for auth.")
sys.exit(1)
sys.exit(ExitCodes.OAUTH_ERROR)

# the token returned via public oauth will expire in 2 hours, which
# isn't great. Instead, we're gonna make a token that expires never
Expand Down Expand Up @@ -345,6 +346,6 @@ def log_message(self, form, *args): # pylint: disable=arguments-differ
"try token using a token by invoking with `linode-cli configure --token`, "
"and open an issue at https://github.com/linode/linode-cli"
)
sys.exit(1)
sys.exit(ExitCodes.OAUTH_ERROR)

return serv.token
12 changes: 7 additions & 5 deletions linodecli/configuration/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import sys
from typing import Any, Dict, List, Optional

from linodecli.exit_codes import ExitCodes

from .auth import (
_check_full_access,
_do_get_request,
Expand Down Expand Up @@ -95,7 +97,7 @@ def set_user(self, username: str):
"""
if not self.config.has_section(username):
print(f"User {username} is not configured!")
sys.exit(1)
sys.exit(ExitCodes.USERNAME_ERROR)

self.username = username

Expand All @@ -112,7 +114,7 @@ def remove_user(self, username: str):
f"Cannot remove {username} as they are the default user! You can "
"change the default user with: `linode-cli set-user USERNAME`"
)
sys.exit(1)
sys.exit(ExitCodes.USERNAME_ERROR)

if self.config.has_section(username):
self.config.remove_section(username)
Expand All @@ -129,15 +131,15 @@ def print_users(self):
if sec != "DEFAULT":
print(f'{"*" if sec == default_user else " "} {sec}')

sys.exit(0)
sys.exit(ExitCodes.SUCCESS)

def set_default_user(self, username: str):
"""
Sets the default user. If that user isn't in the config, exits with error
"""
if not self.config.has_section(username):
print(f"User {username} is not configured!")
sys.exit(1)
sys.exit(ExitCodes.USERNAME_ERROR)

self.config.set("DEFAULT", "default-user", username)
self.write_config()
Expand Down Expand Up @@ -263,7 +265,7 @@ def update(
ENV_TOKEN_NAME, None
):
print(f"User {username} is not configured.")
sys.exit(1)
sys.exit(ExitCodes.USERNAME_ERROR)
if not self.config.has_section(username) or allowed_defaults is None:
return namespace

Expand Down
22 changes: 22 additions & 0 deletions linodecli/exit_codes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""
This is an enumeration of the various exit codes in Linode CLI
"""

from enum import IntEnum


class ExitCodes(IntEnum):
"""
An enumeration of the various exit codes in Linode CLI
"""

SUCCESS = 0
UNRECOGNIZED_COMMAND = 1
REQUEST_FAILED = 2
OAUTH_ERROR = 3
USERNAME_ERROR = 4
FIREWALL_ERROR = 5
KUBECONFIG_ERROR = 6
ARGUMENT_ERROR = 7
FILE_ERROR = 8
Loading

0 comments on commit b4c33e9

Please sign in to comment.