Skip to content

Commit be61d50

Browse files
authored
Implement read operation for AWS::SSM::Parameter & update resource spec (#11962)
1 parent 5a2a3f8 commit be61d50

File tree

5 files changed

+130
-38
lines changed

5 files changed

+130
-38
lines changed

localstack-core/localstack/services/cloudformation/engine/quirks.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
"AWS::Events::EventBus": "/properties/Name",
2929
"AWS::Logs::LogStream": "/properties/LogStreamName",
3030
"AWS::Logs::SubscriptionFilter": "/properties/LogGroupName",
31-
"AWS::SSM::Parameter": "/properties/Name",
3231
"AWS::RDS::DBProxyTargetGroup": "/properties/TargetGroupName",
3332
"AWS::Glue::SchemaVersionMetadata": "</properties/SchemaVersionId>|</properties/Key>|</properties/Value>", # composite
3433
"AWS::WAFv2::WebACL": "</properties/Name>|</properties/Id>|</properties/Scope>",

localstack-core/localstack/services/cloudformation/provider_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def recursive_convert(obj):
227227

228228

229229
# LocalStack specific utilities
230-
def get_schema_path(file_path: Path) -> Path:
230+
def get_schema_path(file_path: Path) -> dict:
231231
file_name_base = file_path.name.removesuffix(".py").removesuffix(".py.enc")
232232
with Path(file_path).parent.joinpath(f"{file_name_base}.schema.json").open() as fd:
233233
return json.load(fd)

localstack-core/localstack/services/ssm/resource_providers/aws_ssm_parameter.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ class SSMParameterProperties(TypedDict):
1919
AllowedPattern: Optional[str]
2020
DataType: Optional[str]
2121
Description: Optional[str]
22-
Id: Optional[str]
2322
Name: Optional[str]
2423
Policies: Optional[str]
2524
Tags: Optional[dict]
@@ -41,19 +40,21 @@ def create(
4140
Create a new resource.
4241
4342
Primary identifier fields:
44-
- /properties/Id
43+
- /properties/Name
4544
4645
Required properties:
47-
- Type
4846
- Value
47+
- Type
4948
5049
Create-only properties:
5150
- /properties/Name
5251
53-
Read-only properties:
54-
- /properties/Id
5552
5653
54+
IAM permissions required:
55+
- ssm:PutParameter
56+
- ssm:AddTagsToResource
57+
- ssm:GetParameters
5758
5859
"""
5960
model = request.desired_state
@@ -87,11 +88,7 @@ def create(
8788

8889
ssm.put_parameter(**params)
8990

90-
return ProgressEvent(
91-
status=OperationStatus.SUCCESS,
92-
resource_model=model,
93-
custom_context=request.custom_context,
94-
)
91+
return self.read(request)
9592

9693
def read(
9794
self,
@@ -100,9 +97,27 @@ def read(
10097
"""
10198
Fetch resource information
10299
103-
100+
IAM permissions required:
101+
- ssm:GetParameters
104102
"""
105-
raise NotImplementedError
103+
ssm = request.aws_client_factory.ssm
104+
parameter_name = request.desired_state.get("Name")
105+
try:
106+
resource = ssm.get_parameter(Name=parameter_name, WithDecryption=False)
107+
except ssm.exceptions.ParameterNotFound:
108+
return ProgressEvent(
109+
status=OperationStatus.FAILED,
110+
message=f"Resource of type '{self.TYPE}' with identifier '{parameter_name}' was not found.",
111+
error_code="NotFound",
112+
)
113+
114+
parameter = util.select_attributes(resource["Parameter"], params=self.SCHEMA["properties"])
115+
116+
return ProgressEvent(
117+
status=OperationStatus.SUCCESS,
118+
resource_model=parameter,
119+
custom_context=request.custom_context,
120+
)
106121

107122
def delete(
108123
self,
@@ -111,7 +126,8 @@ def delete(
111126
"""
112127
Delete a resource
113128
114-
129+
IAM permissions required:
130+
- ssm:DeleteParameter
115131
"""
116132
model = request.desired_state
117133
ssm = request.aws_client_factory.ssm
@@ -131,7 +147,11 @@ def update(
131147
"""
132148
Update a resource
133149
134-
150+
IAM permissions required:
151+
- ssm:PutParameter
152+
- ssm:AddTagsToResource
153+
- ssm:RemoveTagsFromResource
154+
- ssm:GetParameters
135155
"""
136156
model = request.desired_state
137157
ssm = request.aws_client_factory.ssm
@@ -203,6 +223,7 @@ def list(
203223
return ProgressEvent(
204224
status=OperationStatus.SUCCESS,
205225
resource_models=[
206-
SSMParameterProperties(Id=resource["Name"]) for resource in resources["Parameters"]
226+
SSMParameterProperties(Name=resource["Name"])
227+
for resource in resources["Parameters"]
207228
],
208229
)

localstack-core/localstack/services/ssm/resource_providers/aws_ssm_parameter.schema.json

Lines changed: 92 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,118 @@
44
"additionalProperties": false,
55
"properties": {
66
"Type": {
7-
"type": "string"
7+
"type": "string",
8+
"description": "The type of the parameter.",
9+
"enum": [
10+
"String",
11+
"StringList",
12+
"SecureString"
13+
]
14+
},
15+
"Value": {
16+
"type": "string",
17+
"description": "The value associated with the parameter."
818
},
919
"Description": {
10-
"type": "string"
20+
"type": "string",
21+
"description": "The information about the parameter."
1122
},
1223
"Policies": {
13-
"type": "string"
24+
"type": "string",
25+
"description": "The policies attached to the parameter."
1426
},
1527
"AllowedPattern": {
16-
"type": "string"
28+
"type": "string",
29+
"description": "The regular expression used to validate the parameter value."
1730
},
1831
"Tier": {
19-
"type": "string"
32+
"type": "string",
33+
"description": "The corresponding tier of the parameter.",
34+
"enum": [
35+
"Standard",
36+
"Advanced",
37+
"Intelligent-Tiering"
38+
]
2039
},
21-
"Value": {
22-
"type": "string"
40+
"Tags": {
41+
"type": "object",
42+
"description": "A key-value pair to associate with a resource.",
43+
"patternProperties": {
44+
"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$": {
45+
"type": "string"
46+
}
47+
},
48+
"additionalProperties": false
2349
},
2450
"DataType": {
25-
"type": "string"
26-
},
27-
"Id": {
28-
"type": "string"
29-
},
30-
"Tags": {
31-
"type": "object"
51+
"type": "string",
52+
"description": "The corresponding DataType of the parameter.",
53+
"enum": [
54+
"text",
55+
"aws:ec2:image"
56+
]
3257
},
3358
"Name": {
34-
"type": "string"
59+
"type": "string",
60+
"description": "The name of the parameter."
3561
}
3662
},
3763
"required": [
38-
"Type",
39-
"Value"
64+
"Value",
65+
"Type"
4066
],
67+
"tagging": {
68+
"taggable": true,
69+
"tagOnCreate": true,
70+
"tagUpdatable": true,
71+
"cloudFormationSystemTags": true,
72+
"tagProperty": "/properties/Tags"
73+
},
4174
"createOnlyProperties": [
4275
"/properties/Name"
4376
],
4477
"primaryIdentifier": [
45-
"/properties/Id"
78+
"/properties/Name"
79+
],
80+
"writeOnlyProperties": [
81+
"/properties/Tags",
82+
"/properties/Description",
83+
"/properties/Tier",
84+
"/properties/AllowedPattern",
85+
"/properties/Policies"
4686
],
47-
"readOnlyProperties": [
48-
"/properties/Id"
49-
]
87+
"handlers": {
88+
"create": {
89+
"permissions": [
90+
"ssm:PutParameter",
91+
"ssm:AddTagsToResource",
92+
"ssm:GetParameters"
93+
],
94+
"timeoutInMinutes": 5
95+
},
96+
"read": {
97+
"permissions": [
98+
"ssm:GetParameters"
99+
]
100+
},
101+
"update": {
102+
"permissions": [
103+
"ssm:PutParameter",
104+
"ssm:AddTagsToResource",
105+
"ssm:RemoveTagsFromResource",
106+
"ssm:GetParameters"
107+
],
108+
"timeoutInMinutes": 5
109+
},
110+
"delete": {
111+
"permissions": [
112+
"ssm:DeleteParameter"
113+
]
114+
},
115+
"list": {
116+
"permissions": [
117+
"ssm:DescribeParameters"
118+
]
119+
}
120+
}
50121
}

localstack-core/localstack/utils/aws/client_types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ class ServicePrincipal(str):
264264
"""
265265

266266
apigateway = "apigateway"
267+
cloudformation = "cloudformation"
267268
dms = "dms"
268269
events = "events"
269270
firehose = "firehose"

0 commit comments

Comments
 (0)