moto/tests/test_ec2/test_launch_templates.py

620 lines
20 KiB
Python

import boto3
import sure # noqa # pylint: disable=unused-import
import pytest
from botocore.client import ClientError
from moto import mock_ec2, settings
from uuid import uuid4
@mock_ec2
def test_launch_template_create():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
resp = cli.create_launch_template(
LaunchTemplateName=template_name,
# the absolute minimum needed to create a template without other resources
LaunchTemplateData={
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [{"Key": "test", "Value": "value"}],
}
]
},
)
resp.should.have.key("LaunchTemplate")
lt = resp["LaunchTemplate"]
lt["LaunchTemplateName"].should.equal(template_name)
lt["DefaultVersionNumber"].should.equal(1)
lt["LatestVersionNumber"].should.equal(1)
with pytest.raises(ClientError) as ex:
cli.create_launch_template(
LaunchTemplateName=template_name,
LaunchTemplateData={
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [{"Key": "test", "Value": "value"}],
}
]
},
)
str(ex.value).should.equal(
"An error occurred (InvalidLaunchTemplateName.AlreadyExistsException) when calling the CreateLaunchTemplate operation: Launch template name already in use."
)
@mock_ec2
def test_describe_launch_template_versions():
template_data = {
"ImageId": "ami-abc123",
"DisableApiTermination": False,
"TagSpecifications": [
{"ResourceType": "instance", "Tags": [{"Key": "test", "Value": "value"}]}
],
"SecurityGroupIds": ["sg-1234", "sg-ab5678"],
}
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
create_resp = cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData=template_data
)
# test using name
resp = cli.describe_launch_template_versions(
LaunchTemplateName=template_name, Versions=["1"]
)
templ = resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]
templ.should.equal(template_data)
# test using id
resp = cli.describe_launch_template_versions(
LaunchTemplateId=create_resp["LaunchTemplate"]["LaunchTemplateId"],
Versions=["1"],
)
templ = resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]
templ.should.equal(template_data)
@mock_ec2
def test_describe_launch_template_versions_by_name_when_absent():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = "foo"
# test using name
with pytest.raises(
ClientError,
match=f"The specified launch template, with template name {template_name}, does not exist",
):
cli.describe_launch_template_versions(LaunchTemplateName=template_name)
@mock_ec2
def test_create_launch_template_version():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
create_resp = cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
version_resp = cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami",
)
version_resp.should.have.key("LaunchTemplateVersion")
version = version_resp["LaunchTemplateVersion"]
version["DefaultVersion"].should.equal(False)
version["LaunchTemplateId"].should.equal(
create_resp["LaunchTemplate"]["LaunchTemplateId"]
)
version["VersionDescription"].should.equal("new ami")
version["VersionNumber"].should.equal(2)
@mock_ec2
def test_create_launch_template_version_by_id():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
create_resp = cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
version_resp = cli.create_launch_template_version(
LaunchTemplateId=create_resp["LaunchTemplate"]["LaunchTemplateId"],
LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami",
)
version_resp.should.have.key("LaunchTemplateVersion")
version = version_resp["LaunchTemplateVersion"]
version["DefaultVersion"].should.equal(False)
version["LaunchTemplateId"].should.equal(
create_resp["LaunchTemplate"]["LaunchTemplateId"]
)
version["VersionDescription"].should.equal("new ami")
version["VersionNumber"].should.equal(2)
@mock_ec2
def test_describe_launch_template_versions_with_multiple_versions():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami",
)
resp = cli.describe_launch_template_versions(LaunchTemplateName=template_name)
resp["LaunchTemplateVersions"].should.have.length_of(2)
resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-abc123"
)
resp["LaunchTemplateVersions"][1]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-def456"
)
@mock_ec2
def test_describe_launch_template_versions_with_versions_option():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami",
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-hij789"},
VersionDescription="new ami, again",
)
resp = cli.describe_launch_template_versions(
LaunchTemplateName=template_name, Versions=["2", "3"]
)
resp["LaunchTemplateVersions"].should.have.length_of(2)
resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-def456"
)
resp["LaunchTemplateVersions"][1]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-hij789"
)
@mock_ec2
def test_describe_launch_template_versions_with_min():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami",
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-hij789"},
VersionDescription="new ami, again",
)
resp = cli.describe_launch_template_versions(
LaunchTemplateName=template_name, MinVersion="2"
)
resp["LaunchTemplateVersions"].should.have.length_of(2)
resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-def456"
)
resp["LaunchTemplateVersions"][1]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-hij789"
)
@mock_ec2
def test_describe_launch_template_versions_with_max():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami",
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-hij789"},
VersionDescription="new ami, again",
)
resp = cli.describe_launch_template_versions(
LaunchTemplateName=template_name, MaxVersion="2"
)
resp["LaunchTemplateVersions"].should.have.length_of(2)
resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-abc123"
)
resp["LaunchTemplateVersions"][1]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-def456"
)
@mock_ec2
def test_describe_launch_template_versions_with_min_and_max():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami",
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-hij789"},
VersionDescription="new ami, again",
)
cli.create_launch_template_version(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-345abc"},
VersionDescription="new ami, because why not",
)
resp = cli.describe_launch_template_versions(
LaunchTemplateName=template_name, MinVersion="2", MaxVersion="3"
)
resp["LaunchTemplateVersions"].should.have.length_of(2)
resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-def456"
)
resp["LaunchTemplateVersions"][1]["LaunchTemplateData"]["ImageId"].should.equal(
"ami-hij789"
)
@mock_ec2
def test_describe_launch_templates_with_non_existent_name():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
with pytest.raises(ClientError) as ex:
cli.describe_launch_templates(LaunchTemplateNames=[template_name])
str(ex.value).should.equal(
"An error occurred (InvalidLaunchTemplateName.NotFoundException) when calling the DescribeLaunchTemplates operation: At least one of the launch templates specified in the request does not exist."
)
@mock_ec2
def test_describe_launch_templates():
cli = boto3.client("ec2", region_name="us-east-1")
lt_ids = []
template_name = str(uuid4())
r = cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
lt_ids.append(r["LaunchTemplate"]["LaunchTemplateId"])
template_name2 = str(uuid4())
r = cli.create_launch_template(
LaunchTemplateName=template_name2, LaunchTemplateData={"ImageId": "ami-abc123"}
)
lt_ids.append(r["LaunchTemplate"]["LaunchTemplateId"])
# general call, all templates
if not settings.TEST_SERVER_MODE:
# Bug: Only 15 launch templates are returned, ever
# ServerMode may have many more templates, created in parallel
all_templates = retrieve_all_templates(cli)
my_templates = [t for t in all_templates if t["LaunchTemplateId"] in lt_ids]
my_templates[0]["LaunchTemplateName"].should.equal(template_name)
my_templates[1]["LaunchTemplateName"].should.equal(template_name2)
# filter by names
resp = cli.describe_launch_templates(
LaunchTemplateNames=[template_name2, template_name]
)
resp.should.have.key("LaunchTemplates")
resp["LaunchTemplates"].should.have.length_of(2)
resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal(template_name2)
resp["LaunchTemplates"][1]["LaunchTemplateName"].should.equal(template_name)
# filter by ids
resp = cli.describe_launch_templates(LaunchTemplateIds=lt_ids)
resp.should.have.key("LaunchTemplates")
resp["LaunchTemplates"].should.have.length_of(2)
resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal(template_name)
resp["LaunchTemplates"][1]["LaunchTemplateName"].should.equal(template_name2)
@mock_ec2
def test_describe_launch_templates_with_filters():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
r = cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
tag_value = str(uuid4())
cli.create_tags(
Resources=[r["LaunchTemplate"]["LaunchTemplateId"]],
Tags=[
{"Key": "tag1", "Value": tag_value},
{"Key": "another-key", "Value": "this value"},
],
)
template_name_no_tags = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name_no_tags,
LaunchTemplateData={"ImageId": "ami-abc123"},
)
resp = cli.describe_launch_templates(
Filters=[{"Name": "tag:tag1", "Values": [tag_value]}]
)
resp["LaunchTemplates"].should.have.length_of(1)
resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal(template_name)
resp = cli.describe_launch_templates(
Filters=[{"Name": "launch-template-name", "Values": [template_name_no_tags]}]
)
resp["LaunchTemplates"].should.have.length_of(1)
resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal(template_name_no_tags)
@mock_ec2
def test_create_launch_template_with_tag_spec():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-abc123"},
TagSpecifications=[
{"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "value"}]}
],
)
resp = cli.describe_launch_template_versions(
LaunchTemplateName=template_name, Versions=["1"]
)
version = resp["LaunchTemplateVersions"][0]
version["LaunchTemplateData"].should.have.key("TagSpecifications")
version["LaunchTemplateData"]["TagSpecifications"].should.have.length_of(1)
version["LaunchTemplateData"]["TagSpecifications"][0].should.equal(
{"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "value"}]}
)
@mock_ec2
def test_delete_launch_template__dryrun():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-abc123"},
TagSpecifications=[
{"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "value"}]}
],
)
cli.describe_launch_templates(LaunchTemplateNames=[template_name])[
"LaunchTemplates"
].should.have.length_of(1)
with pytest.raises(ClientError) as exc:
cli.delete_launch_template(DryRun=True, LaunchTemplateName=template_name)
err = exc.value.response["Error"]
err.should.have.key("Code").equals("DryRunOperation")
# Template still exists
cli.describe_launch_templates(LaunchTemplateNames=[template_name])[
"LaunchTemplates"
].should.have.length_of(1)
@mock_ec2
def test_delete_launch_template__by_name():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)
cli.describe_launch_templates(LaunchTemplateNames=[template_name])[
"LaunchTemplates"
].should.have.length_of(1)
cli.delete_launch_template(LaunchTemplateName=template_name)
with pytest.raises(ClientError) as exc:
cli.describe_launch_templates(LaunchTemplateNames=[template_name])[
"LaunchTemplates"
]
err = exc.value.response["Error"]
err.should.have.key("Code").equals("InvalidLaunchTemplateName.NotFoundException")
err.should.have.key("Message").equals(
"At least one of the launch templates specified in the request does not exist."
)
# Ensure deleted template name can be reused
cli.create_launch_template(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-abc123"},
)
@mock_ec2
def test_delete_launch_template__by_id():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
with pytest.raises(ClientError) as exc:
cli.delete_launch_template()
err = exc.value.response["Error"]
err.should.have.key("Code").equals("MissingParameter")
err.should.have.key("Message").equals(
"The request must contain the parameter launch template ID or launch template name"
)
template_id = cli.create_launch_template(
LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
)["LaunchTemplate"]["LaunchTemplateId"]
cli.describe_launch_templates(LaunchTemplateNames=[template_name])[
"LaunchTemplates"
].should.have.length_of(1)
cli.delete_launch_template(LaunchTemplateId=template_id)
with pytest.raises(ClientError) as exc:
cli.describe_launch_templates(LaunchTemplateNames=[template_name])[
"LaunchTemplates"
]
err = exc.value.response["Error"]
err.should.have.key("Code").equals("InvalidLaunchTemplateName.NotFoundException")
err.should.have.key("Message").equals(
"At least one of the launch templates specified in the request does not exist."
)
# Ensure deleted template name can be reused
cli.create_launch_template(
LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-abc123"},
)
def retrieve_all_templates(client, filters=[]): # pylint: disable=W0102
resp = client.describe_launch_templates(Filters=filters)
all_templates = resp["LaunchTemplates"]
next_token = resp.get("NextToken")
while next_token:
resp = client.describe_launch_templates(Filters=filters, NextToken=next_token)
all_templates.extend(resp["LaunchTemplates"])
next_token = resp.get("NextToken")
return all_templates
@mock_ec2
def test_launch_template_create_with_tags():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
resp = cli.create_launch_template(
LaunchTemplateName=template_name,
# the absolute minimum needed to create a template without other resources
LaunchTemplateData={
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [{"Key": "test", "Value": "value"}],
}
]
},
TagSpecifications=[
{
"ResourceType": "launch-template",
"Tags": [{"Key": "test1", "Value": "value1"}],
}
],
)
resp.should.have.key("LaunchTemplate")
lt = resp["LaunchTemplate"]
lt["LaunchTemplateName"].should.equal(template_name)
lt["DefaultVersionNumber"].should.equal(1)
lt["LatestVersionNumber"].should.equal(1)
lt["Tags"].should.have.length_of(1)
lt["Tags"][0].should.equal({"Key": "test1", "Value": "value1"})
@mock_ec2
def test_launch_template_describe_with_tags():
cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template(
LaunchTemplateName=template_name,
# the absolute minimum needed to create a template without other resources
LaunchTemplateData={
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [{"Key": "test", "Value": "value"}],
}
]
},
TagSpecifications=[
{
"ResourceType": "launch-template",
"Tags": [{"Key": "test1", "Value": "value1"}],
}
],
)
lt = cli.describe_launch_templates(LaunchTemplateNames=[template_name])[
"LaunchTemplates"
][0]
lt["LaunchTemplateName"].should.equal(template_name)
lt["DefaultVersionNumber"].should.equal(1)
lt["LatestVersionNumber"].should.equal(1)
lt["Tags"].should.have.length_of(1)
lt["Tags"][0].should.equal({"Key": "test1", "Value": "value1"})