Skip to content

Commit b0415c4

Browse files
Merge branch 'dev' into dependabot/github_actions/Andrew-Chen-Wang/github-wiki-action-5.0.1
2 parents 867cac6 + 9ebee7f commit b0415c4

24 files changed

+470
-126
lines changed

.github/workflows/e2e-suite.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ jobs:
294294
steps:
295295
- name: Notify Slack
296296
id: main_message
297-
uses: slackapi/slack-github-action@v2.1.0
297+
uses: slackapi/slack-github-action@v2
298298
with:
299299
method: chat.postMessage
300300
token: ${{ secrets.SLACK_BOT_TOKEN }}
@@ -326,7 +326,7 @@ jobs:
326326
327327
- name: Test summary thread
328328
if: success()
329-
uses: slackapi/slack-github-action@v2.1.0
329+
uses: slackapi/slack-github-action@v2
330330
with:
331331
method: chat.postMessage
332332
token: ${{ secrets.SLACK_BOT_TOKEN }}

.github/workflows/nightly-smoke-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646

4747
- name: Notify Slack
4848
if: always() && github.repository == 'linode/linode-cli' # Run even if integration tests fail and only on main repository
49-
uses: slackapi/slack-github-action@v2.1.0
49+
uses: slackapi/slack-github-action@v2
5050
with:
5151
method: chat.postMessage
5252
token: ${{ secrets.SLACK_BOT_TOKEN }}

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
steps:
1212
- name: Notify Slack - Main Message
1313
id: main_message
14-
uses: slackapi/slack-github-action@v2.1.0
14+
uses: slackapi/slack-github-action@v2
1515
with:
1616
method: chat.postMessage
1717
token: ${{ secrets.SLACK_BOT_TOKEN }}
@@ -42,7 +42,7 @@ jobs:
4242
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # [email protected]
4343

4444
- name: Set up Docker Buildx
45-
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # pin@v3.10.0
45+
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # pin@v3.11.1
4646

4747
- name: Login to Docker Hub
4848
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # [email protected]

.github/workflows/remote-release-trigger.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
commit_sha: ${{ steps.calculate_head_sha.outputs.commit_sha }}
6767

6868
- name: Release
69-
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # pin@v2.2.2
69+
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # pin@v2.3.2
7070
with:
7171
target_commitish: 'main'
7272
token: ${{ steps.generate_token.outputs.token }}

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ test-unit:
6464
@mkdir -p /tmp/linode/.config
6565
@orig_xdg_config_home=$${XDG_CONFIG_HOME:-}; \
6666
export LINODE_CLI_TEST_MODE=1 XDG_CONFIG_HOME=/tmp/linode/.config; \
67-
pytest -v tests/unit; \
67+
pytest -vv tests/unit; \
6868
exit_code=$$?; \
6969
export XDG_CONFIG_HOME=$$orig_xdg_config_home; \
7070
exit $$exit_code

linodecli/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
8080
cli.page = parsed.page
8181
cli.page_size = parsed.page_size
8282
cli.debug_request = parsed.debug
83+
cli.raw_body = parsed.raw_body
8384

8485
if parsed.as_user and not skip_config:
8586
cli.config.set_user(parsed.as_user)

linodecli/api_request.py

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,21 +348,49 @@ def _build_request_body(
348348
349349
:return: A JSON string representing the request body, or None if not applicable.
350350
"""
351-
if operation.method == "get":
352-
# Get operations don't have a body
351+
if operation.method in ("get", "delete"):
352+
# GET and DELETE operations don't have a body
353+
if ctx.raw_body is not None:
354+
print(
355+
f"--raw-body cannot be specified for actions with method {operation.method}",
356+
file=sys.stderr,
357+
)
358+
sys.exit(ExitCodes.ARGUMENT_ERROR)
359+
353360
return None
354361

362+
param_names = {param.name for param in operation.params}
363+
364+
# Returns whether the given argument should be included in the request body
365+
def __should_include(key: str, value: Any) -> bool:
366+
return value is not None and key not in param_names
367+
368+
# If the user has specified the --raw-body argument,
369+
# return it.
370+
if ctx.raw_body is not None:
371+
specified_keys = [
372+
k for k, v in vars(parsed_args).items() if __should_include(k, v)
373+
]
374+
375+
if len(specified_keys) > 0:
376+
print(
377+
"--raw-body cannot be specified with action arguments: "
378+
+ ", ".join(sorted(f"--{key}" for key in specified_keys)),
379+
file=sys.stderr,
380+
)
381+
sys.exit(ExitCodes.ARGUMENT_ERROR)
382+
383+
return ctx.raw_body
384+
355385
# Merge defaults into body if applicable
356386
if ctx.defaults:
357387
parsed_args = ctx.config.update(parsed_args, operation.allowed_defaults)
358388

359-
param_names = {param.name for param in operation.params}
360-
361389
expanded_json = {}
362390

363391
# Expand dotted keys into nested dictionaries
364392
for k, v in vars(parsed_args).items():
365-
if v is None or k in param_names:
393+
if not __should_include(k, v):
366394
continue
367395

368396
path_segments = get_path_segments(k)

linodecli/arg_helpers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ def register_args(parser: ArgumentParser) -> ArgumentParser:
8181
help="The alias to set or remove.",
8282
)
8383

84+
parser.add_argument(
85+
"--raw-body",
86+
type=str,
87+
help="The raw JSON to use as the request body of an action. "
88+
+ "This argument cannot be used if action-specific arguments are specified. "
89+
+ "Additionally, this argument can only be used with POST and PUT actions.",
90+
)
91+
8492
# Register shared argument groups
8593
register_output_args_shared(parser)
8694
register_pagination_args_shared(parser)

linodecli/baked/request.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ def __init__( # pylint: disable=too-many-arguments
4848
:type parent: Optional[str]
4949
:param depth: The depth of this argument, or how many parent arguments this argument has.
5050
:type depth: int
51+
:param option_variants: A mapping of options, defined using oneOf in the to spec,
52+
to a variant of this argument.
5153
"""
5254
#: The name of this argument, mostly used for display and docs
5355
self.name = name
@@ -147,6 +149,7 @@ def _parse_request_model(
147149
:returns: The flattened request model, as a list
148150
:rtype: list[OpenAPIRequestArg]
149151
"""
152+
150153
args = []
151154

152155
properties, required = _aggregate_schema_properties(schema)

linodecli/baked/util.py

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,39 @@ def _aggregate_schema_properties(
2424
properties = {}
2525
required = defaultdict(lambda: 0)
2626

27-
def _handle_schema(_schema: Schema):
28-
if _schema.properties is None:
27+
def __inner(
28+
path: List[str],
29+
entry: Schema,
30+
):
31+
if isinstance(entry, dict):
32+
# TODO: Figure out why this happens (openapi3 package bug?)
33+
# pylint: disable=protected-access
34+
entry = Schema(path, entry, schema._root)
35+
36+
if entry.properties is None:
37+
# If there aren't any properties, this might be a
38+
# composite schema
39+
for composition_field in ["oneOf", "allOf", "anyOf"]:
40+
for i, nested_entry in enumerate(
41+
getattr(entry, composition_field) or []
42+
):
43+
__inner(
44+
schema.path + [composition_field, str(i)],
45+
nested_entry,
46+
)
47+
2948
return
3049

50+
# This is a valid option
51+
properties.update(entry.properties)
52+
3153
nonlocal schema_count
3254
schema_count += 1
3355

34-
properties.update(dict(_schema.properties))
35-
36-
# Aggregate required keys and their number of usages.
37-
if _schema.required is not None:
38-
for key in _schema.required:
39-
required[key] += 1
40-
41-
_handle_schema(schema)
42-
43-
one_of = schema.oneOf or []
44-
any_of = schema.anyOf or []
56+
for key in entry.required or []:
57+
required[key] += 1
4558

46-
for entry in one_of + any_of:
47-
# pylint: disable=protected-access
48-
_handle_schema(Schema(schema.path, entry, schema._root))
59+
__inner(schema.path, schema)
4960

5061
return (
5162
properties,

0 commit comments

Comments
 (0)