Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.

Commit 806a1d5

Browse files
Updates, as recommend in PR review.
1 parent 7a28cfa commit 806a1d5

File tree

5 files changed

+138
-7
lines changed

5 files changed

+138
-7
lines changed

localstack-core/localstack/services/cloudformation/scaffolding/__main__.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import json
44
import os
5+
import subprocess
6+
import sys
57
import zipfile
68
from collections.abc import Generator
79
from dataclasses import dataclass
@@ -353,12 +355,7 @@ def render(
353355
resource_name, FileType.attribute_template, tests_output_path, pro=self.pro
354356
)
355357
)
356-
case FileType.provider:
357-
kwargs["service"] = resource_name.python_compatible_service_name.lower()
358-
kwargs["lower_resource"] = resource_name.resource.lower()
359-
kwargs["pro"] = self.pro
360-
pass
361-
case FileType.provider_base:
358+
case FileType.provider | FileType.provider_base:
362359
property_ir = generate_ir_for_type(
363360
[self.schema],
364361
resource_name.full_name,
@@ -384,6 +381,9 @@ def render(
384381
kwargs["list_permissions"] = (
385382
self.schema.get("handlers", {}).get("list", {}).get("permissions")
386383
)
384+
kwargs["service"] = resource_name.python_compatible_service_name.lower()
385+
kwargs["lower_resource"] = resource_name.resource.lower()
386+
kwargs["pro"] = self.pro
387387
case FileType.plugin:
388388
kwargs["service"] = resource_name.python_compatible_service_name.lower()
389389
kwargs["lower_resource"] = resource_name.resource.lower()
@@ -728,13 +728,25 @@ def confirm_overwrite(self, destination_file: Path) -> bool:
728728
729729
:return True if file should be (over-)written, False otherwise
730730
"""
731-
return self.overwrite or click.confirm("Destination files already exist, overwrite?")
731+
return self.overwrite or click.confirm(
732+
f"Destination file {destination_file} already exists, overwrite?"
733+
)
732734

733735
@staticmethod
734736
def write_text(contents: str, destination: Path):
735737
with destination.open("wt") as outfile:
736738
print(contents, file=outfile)
737739

740+
# for Python files, use ruff to clean up formatting errors introduced by scaffolding
741+
if destination.suffix == ".py":
742+
command = [sys.executable, "-m", "ruff", "format", destination]
743+
try:
744+
subprocess.run(command, check=True, capture_output=True, text=True)
745+
except subprocess.CalledProcessError as e:
746+
print(
747+
f"Ruff fix command failed (exit code {e.returncode}):\n{e.stdout}\n{e.stderr}"
748+
)
749+
738750
@staticmethod
739751
def ensure_python_init_files(path: Path):
740752
"""

localstack-core/localstack/services/cloudformation/scaffolding/templates/provider_base_template.py.j2

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,19 @@ class {{ resource }}ProviderBase(ResourceProvider[{{ resource }}Properties], ABC
121121
{%- endif %}
122122
"""
123123
raise NotImplementedError
124+
125+
@abstractmethod
126+
def list(
127+
self,
128+
request: ResourceRequest[{{ resource }}Properties],
129+
) -> ProgressEvent[{{ resource }}Properties]:
130+
"""
131+
List available resources of this type
132+
{% if list_permissions -%}
133+
IAM permissions required:
134+
{%- for permission in list_permissions %}
135+
- {{ permission }}
136+
{%- endfor %}
137+
{%- endif %}
138+
"""
139+
raise NotImplementedError

localstack-core/localstack/services/cloudformation/scaffolding/templates/provider_template.py.j2

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,44 @@ class {{ resource }}Provider({{ resource }}ProviderBase):
2222
self,
2323
request: ResourceRequest[{{ resource }}Properties],
2424
) -> ProgressEvent[{{ resource }}Properties]:
25+
"""
26+
Create a new resource.
27+
28+
{% if primary_identifier -%}
29+
Primary identifier fields:
30+
{%- for property in primary_identifier %}
31+
- {{ property }}
32+
{%- endfor %}
33+
{%- endif %}
34+
35+
{% if required_properties -%}
36+
Required properties:
37+
{%- for property in required_properties %}
38+
- {{ property }}
39+
{%- endfor %}
40+
{%- endif %}
41+
42+
{% if create_only_properties -%}
43+
Create-only properties:
44+
{%- for property in create_only_properties %}
45+
- {{ property }}
46+
{%- endfor %}
47+
{%- endif %}
48+
49+
{% if read_only_properties -%}
50+
Read-only properties:
51+
{%- for property in read_only_properties %}
52+
- {{ property }}
53+
{%- endfor %}
54+
{%- endif %}
55+
56+
{% if create_permissions -%}
57+
IAM permissions required:
58+
{%- for permission in create_permissions %}
59+
- {{ permission }}
60+
{%- endfor -%}
61+
{%- endif %}
62+
"""
2563
model = request.desired_state
2664

2765
# TODO: validations
@@ -50,16 +88,61 @@ class {{ resource }}Provider({{ resource }}ProviderBase):
5088
self,
5189
request: ResourceRequest[{{ resource }}Properties],
5290
) -> ProgressEvent[{{ resource }}Properties]:
91+
"""
92+
Fetch resource information
93+
94+
{% if read_permissions -%}
95+
IAM permissions required:
96+
{%- for permission in read_permissions %}
97+
- {{ permission }}
98+
{%- endfor %}
99+
{%- endif %}
100+
"""
53101
raise NotImplementedError
54102

55103
def delete(
56104
self,
57105
request: ResourceRequest[{{ resource }}Properties],
58106
) -> ProgressEvent[{{ resource }}Properties]:
107+
"""
108+
Delete a resource
109+
110+
{% if delete_permissions -%}
111+
IAM permissions required:
112+
{%- for permission in delete_permissions %}
113+
- {{ permission }}
114+
{%- endfor %}
115+
{%- endif %}
116+
"""
59117
raise NotImplementedError
60118

61119
def update(
62120
self,
63121
request: ResourceRequest[{{ resource }}Properties],
64122
) -> ProgressEvent[{{ resource }}Properties]:
123+
"""
124+
Update a resource
125+
126+
{% if update_permissions -%}
127+
IAM permissions required:
128+
{%- for permission in update_permissions %}
129+
- {{ permission }}
130+
{%- endfor %}
131+
{%- endif %}
132+
"""
133+
raise NotImplementedError
134+
135+
def list(
136+
self,
137+
request: ResourceRequest[{{ resource }}Properties],
138+
) -> ProgressEvent[{{ resource }}Properties]:
139+
"""
140+
List available resources of this type
141+
{% if list_permissions -%}
142+
IAM permissions required:
143+
{%- for permission in list_permissions %}
144+
- {{ permission }}
145+
{%- endfor %}
146+
{%- endif %}
147+
"""
65148
raise NotImplementedError

localstack-core/localstack/services/sqs/resource_providers/aws_sqs_queuepolicy.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,12 @@ def update(
8686
status=OperationStatus.SUCCESS,
8787
resource_model=model,
8888
)
89+
90+
def list(
91+
self,
92+
request: ResourceRequest[SQSQueuePolicyProperties],
93+
) -> ProgressEvent[SQSQueuePolicyProperties]:
94+
"""
95+
List available resources of this type
96+
"""
97+
raise NotImplementedError

localstack-core/localstack/services/sqs/resource_providers/generated/aws_sqs_queuepolicy_base.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,14 @@ def update(
9393
- sqs:SetQueueAttributes
9494
"""
9595
raise NotImplementedError
96+
97+
@abstractmethod
98+
def list(
99+
self,
100+
request: ResourceRequest[SQSQueuePolicyProperties],
101+
) -> ProgressEvent[SQSQueuePolicyProperties]:
102+
"""
103+
List available resources of this type
104+
105+
"""
106+
raise NotImplementedError

0 commit comments

Comments
 (0)