Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
docker-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Build the Docker image
run: docker build . --file Dockerfile --tag linode/cli:$(date +%s) --build-arg="github_token=$GITHUB_TOKEN"
env:
Expand All @@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout repo
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: setup python 3
uses: actions/setup-python@v6
Expand All @@ -37,7 +37,7 @@ jobs:
python-version: [ "3.9","3.10","3.11", "3.12", "3.13" ]
steps:
- name: Clone Repository
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Setup Python
uses: actions/setup-python@v6
Expand All @@ -59,7 +59,7 @@ jobs:
runs-on: windows-latest
steps:
- name: Clone Repository
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Setup Python
uses: actions/setup-python@v6
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
build-mode: none
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout repository'
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: 'Dependency Review'
uses: actions/dependency-review-action@v4
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/e2e-suite-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
steps:
# Check out merge commit
- name: Checkout PR
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
ref: ${{ inputs.sha }}

Expand Down Expand Up @@ -109,7 +109,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: 'recursive'
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/e2e-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ jobs:
steps:
- name: Checkout Repository with SHA
if: ${{ inputs.sha != '' }}
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: 'recursive'
ref: ${{ inputs.sha }}

- name: Checkout Repository without SHA
if: ${{ inputs.sha == '' }}
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: 'recursive'
Expand Down Expand Up @@ -170,7 +170,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: 'recursive'
Expand Down Expand Up @@ -237,7 +237,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: 'recursive'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
-
name: Run Labeler
uses: crazy-max/ghaction-github-labeler@24d110aa46a59976b8a7f35518cb7f14f434c916
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 @@ -18,7 +18,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: 'recursive'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-wiki.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ jobs:
publish-wiki:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: Andrew-Chen-Wang/github-wiki-action@6448478bd55f1f3f752c93af8ac03207eccc3213 # pin@v5.0.3
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone Repository
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: setup python 3
uses: actions/setup-python@v6
Expand Down Expand Up @@ -86,7 +86,7 @@ jobs:
environment: pypi-release
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Setup Python
uses: actions/setup-python@v6
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/remote-release-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
private_key: ${{ secrets.CLI_RELEASE_PRIVATE_KEY }}

- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
# We want to checkout the main branch
ref: 'main'
Expand Down
4 changes: 0 additions & 4 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,6 @@ py-version=3.9
# Discover python modules and packages in the file system subtree.
recursive=no

# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes

# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
Expand Down
69 changes: 57 additions & 12 deletions linodecli/configuration/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import argparse
import os
import sys
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Type, TypeVar, cast

from linodecli.exit_codes import ExitCodes

Expand All @@ -27,6 +27,8 @@

ENV_TOKEN_NAME = "LINODE_CLI_TOKEN"

T = TypeVar("T")


class CLIConfig:
"""
Expand Down Expand Up @@ -216,15 +218,12 @@ def plugin_set_value(self, key: str, value: Any):
:param value: The value to set for this key
:type value: any
"""
if self.running_plugin is None:
raise RuntimeError(
"No running plugin to retrieve configuration for!"
)

username = self.username or self.default_username()
self.config.set(username, f"plugin-{self.running_plugin}-{key}", value)
self.config.set(username, self._get_plugin_key(key), value)

def plugin_get_value(self, key: str) -> Optional[Any]:
def plugin_get_value(
self, key: str, default: Optional[T] = None, value_type: Type[T] = str
) -> Optional[T]:
"""
Retrieves and returns a config value previously set for a plugin. Your
plugin should have set this value in the past. If this value does not
Expand All @@ -235,18 +234,54 @@ def plugin_get_value(self, key: str) -> Optional[Any]:
:param key: The key of the value to return
:type key: str

:param default: The default value to return if the key is not set
:type default: T

:param value_type: The type to which the value should be cast
:type value_type: Type[T]

:returns: The value for this plugin for this key, or None if not set
:rtype: any
"""
username = self.username or self.default_username() or "DEFAULT"
value = self.config.get(
username, self._get_plugin_key(key), fallback=None
)
if value is None:
return default

if value_type == str:
return value

if value_type == bool:
bool_value = self.parse_boolean(value)
return bool_value if bool_value is not None else default

try:
return cast(T, value_type(value))
except (ValueError, TypeError):
print(
f"Could not cast config value {value} to {value_type}.",
file=sys.stderr,
)
return default

def plugin_remove_option(self, key: str):
"""
Removes a plugin configuration option.

:param key: The key of the option to remove
"""
username = self.username or self.default_username()
self.config.remove_option(username, self._get_plugin_key(key))

def _get_plugin_key(self, key: str) -> str:
if self.running_plugin is None:
raise RuntimeError(
"No running plugin to retrieve configuration for!"
)

username = self.username or self.default_username() or "DEFAULT"
full_key = f"plugin-{self.running_plugin}-{key}"

return self.config.get(username, full_key, fallback=None)
return f"plugin-{self.running_plugin}-{key}"

# TODO: this is more of an argparsing function than it is a config function
# might be better to move this to argparsing during refactor and just have
Expand Down Expand Up @@ -654,3 +689,13 @@ def get_custom_aliases(self) -> Dict[str, str]:
if (self.config.has_section("custom_aliases"))
else {}
)

def parse_boolean(self, value: str) -> Optional[bool]:
"""
Parses a string config value into a boolean. Returns None if the value
cannot be parsed as a boolean.

:param value: The string value to parse.
:return: The parsed boolean value.
"""
return self.config.BOOLEAN_STATES.get(value.lower(), None)
Loading
Loading