moto/moto/ec2/responses/launch_templates.py

292 lines
10 KiB
Python
Raw Normal View History

import uuid
from moto.core.responses import BaseResponse
from moto.ec2.models import OWNER_ID
from moto.ec2.exceptions import FilterNotImplementedError
from moto.ec2.utils import filters_from_querystring
from xml.etree import ElementTree
from xml.dom import minidom
def xml_root(name):
2019-10-31 15:44:26 +00:00
root = ElementTree.Element(
name, {"xmlns": "http://ec2.amazonaws.com/doc/2016-11-15/"}
)
request_id = str(uuid.uuid4()) + "example"
ElementTree.SubElement(root, "requestId").text = request_id
return root
def xml_serialize(tree, key, value):
name = key[0].lower() + key[1:]
if isinstance(value, list):
2019-10-31 15:44:26 +00:00
if name[-1] == "s":
name = name[:-1]
2019-10-31 15:44:26 +00:00
name = name + "Set"
node = ElementTree.SubElement(tree, name)
2021-07-26 06:40:39 +00:00
if isinstance(value, (str, int, float, str)):
node.text = str(value)
elif isinstance(value, dict):
2021-07-26 06:40:39 +00:00
for dictkey, dictvalue in value.items():
xml_serialize(node, dictkey, dictvalue)
elif isinstance(value, list):
for item in value:
2019-10-31 15:44:26 +00:00
xml_serialize(node, "item", item)
2019-08-19 23:01:44 +00:00
elif value is None:
pass
else:
2019-10-31 15:44:26 +00:00
raise NotImplementedError(
'Don\'t know how to serialize "{}" to xml'.format(value.__class__)
)
def pretty_xml(tree):
2019-10-31 15:44:26 +00:00
rough = ElementTree.tostring(tree, "utf-8")
parsed = minidom.parseString(rough)
2019-10-31 15:44:26 +00:00
return parsed.toprettyxml(indent=" ")
def parse_object(raw_data):
out_data = {}
2021-07-26 06:40:39 +00:00
for key, value in raw_data.items():
key_fix_splits = key.split("_")
key_len = len(key_fix_splits)
new_key = ""
for i in range(0, key_len):
new_key += key_fix_splits[i][0].upper() + key_fix_splits[i][1:]
data = out_data
splits = new_key.split(".")
for split in splits[:-1]:
if split not in data:
data[split] = {}
data = data[split]
data[splits[-1]] = value
out_data = parse_lists(out_data)
return out_data
def parse_lists(data):
2021-07-26 06:40:39 +00:00
for key, value in data.items():
if isinstance(value, dict):
keys = data[key].keys()
is_list = all(map(lambda k: k.isnumeric(), keys))
if is_list:
new_value = []
keys = sorted(list(keys))
for k in keys:
lvalue = value[k]
if isinstance(lvalue, dict):
lvalue = parse_lists(lvalue)
new_value.append(lvalue)
data[key] = new_value
return data
class LaunchTemplates(BaseResponse):
def create_launch_template(self):
2019-10-31 15:44:26 +00:00
name = self._get_param("LaunchTemplateName")
version_description = self._get_param("VersionDescription")
tag_spec = self._parse_tag_specification("TagSpecification")
2019-10-31 15:44:26 +00:00
raw_template_data = self._get_dict_param("LaunchTemplateData.")
parsed_template_data = parse_object(raw_template_data)
2019-10-31 15:44:26 +00:00
if self.is_not_dryrun("CreateLaunchTemplate"):
if tag_spec:
2019-10-31 15:44:26 +00:00
if "TagSpecifications" not in parsed_template_data:
parsed_template_data["TagSpecifications"] = []
converted_tag_spec = []
2021-07-26 06:40:39 +00:00
for resource_type, tags in tag_spec.items():
2019-10-31 15:44:26 +00:00
converted_tag_spec.append(
{
"ResourceType": resource_type,
"Tags": [
{"Key": key, "Value": value}
2021-07-26 06:40:39 +00:00
for key, value in tags.items()
2019-10-31 15:44:26 +00:00
],
}
)
parsed_template_data["TagSpecifications"].extend(converted_tag_spec)
template = self.ec2_backend.create_launch_template(
name, version_description, parsed_template_data
)
version = template.default_version()
tree = xml_root("CreateLaunchTemplateResponse")
2019-10-31 15:44:26 +00:00
xml_serialize(
tree,
"launchTemplate",
{
"createTime": version.create_time,
"createdBy": "arn:aws:iam::{OWNER_ID}:root".format(
OWNER_ID=OWNER_ID
),
"defaultVersionNumber": template.default_version_number,
"latestVersionNumber": version.number,
"launchTemplateId": template.id,
"launchTemplateName": template.name,
},
)
return pretty_xml(tree)
def create_launch_template_version(self):
2019-10-31 15:44:26 +00:00
name = self._get_param("LaunchTemplateName")
tmpl_id = self._get_param("LaunchTemplateId")
if name:
template = self.ec2_backend.get_launch_template_by_name(name)
if tmpl_id:
template = self.ec2_backend.get_launch_template(tmpl_id)
2019-10-31 15:44:26 +00:00
version_description = self._get_param("VersionDescription")
2019-10-31 15:44:26 +00:00
raw_template_data = self._get_dict_param("LaunchTemplateData.")
template_data = parse_object(raw_template_data)
2019-10-31 15:44:26 +00:00
if self.is_not_dryrun("CreateLaunchTemplate"):
version = template.create_version(template_data, version_description)
tree = xml_root("CreateLaunchTemplateVersionResponse")
2019-10-31 15:44:26 +00:00
xml_serialize(
tree,
"launchTemplateVersion",
{
"createTime": version.create_time,
"createdBy": "arn:aws:iam::{OWNER_ID}:root".format(
OWNER_ID=OWNER_ID
),
"defaultVersion": template.is_default(version),
"launchTemplateData": version.data,
"launchTemplateId": template.id,
"launchTemplateName": template.name,
"versionDescription": version.description,
"versionNumber": version.number,
},
)
return pretty_xml(tree)
# def delete_launch_template(self):
# pass
# def delete_launch_template_versions(self):
# pass
def describe_launch_template_versions(self):
2019-10-31 15:44:26 +00:00
name = self._get_param("LaunchTemplateName")
template_id = self._get_param("LaunchTemplateId")
if name:
template = self.ec2_backend.get_launch_template_by_name(name)
if template_id:
template = self.ec2_backend.get_launch_template(template_id)
max_results = self._get_int_param("MaxResults", 15)
versions = self._get_multi_param("LaunchTemplateVersion")
min_version = self._get_int_param("MinVersion")
max_version = self._get_int_param("MaxVersion")
filters = filters_from_querystring(self.querystring)
if filters:
2019-10-31 15:44:26 +00:00
raise FilterNotImplementedError(
"all filters", "DescribeLaunchTemplateVersions"
)
if self.is_not_dryrun("DescribeLaunchTemplateVersions"):
tree = ElementTree.Element(
"DescribeLaunchTemplateVersionsResponse",
{"xmlns": "http://ec2.amazonaws.com/doc/2016-11-15/"},
)
request_id = ElementTree.SubElement(tree, "requestId")
request_id.text = "65cadec1-b364-4354-8ca8-4176dexample"
versions_node = ElementTree.SubElement(tree, "launchTemplateVersionSet")
ret_versions = []
if versions:
for v in versions:
ret_versions.append(template.get_version(int(v)))
elif min_version:
if max_version:
vMax = max_version
else:
vMax = min_version + max_results
vMin = min_version - 1
ret_versions = template.versions[vMin:vMax]
elif max_version:
vMax = max_version
ret_versions = template.versions[:vMax]
else:
ret_versions = template.versions
ret_versions = ret_versions[:max_results]
for version in ret_versions:
2019-10-31 15:44:26 +00:00
xml_serialize(
versions_node,
"item",
{
"createTime": version.create_time,
"createdBy": "arn:aws:iam::{OWNER_ID}:root".format(
OWNER_ID=OWNER_ID
),
"defaultVersion": True,
"launchTemplateData": version.data,
"launchTemplateId": template.id,
"launchTemplateName": template.name,
"versionDescription": version.description,
"versionNumber": version.number,
},
)
return pretty_xml(tree)
def describe_launch_templates(self):
max_results = self._get_int_param("MaxResults", 15)
template_names = self._get_multi_param("LaunchTemplateName")
template_ids = self._get_multi_param("LaunchTemplateId")
filters = filters_from_querystring(self.querystring)
if self.is_not_dryrun("DescribeLaunchTemplates"):
tree = ElementTree.Element("DescribeLaunchTemplatesResponse")
templates_node = ElementTree.SubElement(tree, "launchTemplates")
2021-08-27 15:12:35 +00:00
templates = self.ec2_backend.describe_launch_templates(
2019-10-31 15:44:26 +00:00
template_names=template_names,
template_ids=template_ids,
filters=filters,
)
templates = templates[:max_results]
for template in templates:
2019-10-31 15:44:26 +00:00
xml_serialize(
templates_node,
"item",
{
"createTime": template.create_time,
"createdBy": "arn:aws:iam::{OWNER_ID}:root".format(
OWNER_ID=OWNER_ID
),
"defaultVersionNumber": template.default_version_number,
"latestVersionNumber": template.latest_version_number,
"launchTemplateId": template.id,
"launchTemplateName": template.name,
},
)
return pretty_xml(tree)
# def modify_launch_template(self):
# pass