diff --git a/moto/elbv2/exceptions.py b/moto/elbv2/exceptions.py
index 9550fcb9e095..dd2fa6ee924e 100644
--- a/moto/elbv2/exceptions.py
+++ b/moto/elbv2/exceptions.py
@@ -35,9 +35,7 @@ def __init__(self) -> None:
class TargetGroupNotFoundError(ELBClientError):
def __init__(self) -> None:
- super().__init__(
- "TargetGroupNotFound", "The specified target group does not exist."
- )
+ super().__init__("TargetGroupNotFound", "One or more target groups not found")
class TooManyTagsError(ELBClientError):
diff --git a/moto/elbv2/models.py b/moto/elbv2/models.py
index 9f0e53e2d2a8..2ae4f3f51658 100644
--- a/moto/elbv2/models.py
+++ b/moto/elbv2/models.py
@@ -1377,20 +1377,33 @@ def describe_target_groups(
target_group_arns: List[str],
names: Optional[List[str]],
) -> Iterable[FakeTargetGroup]:
+
+ args = sum(bool(arg) for arg in [load_balancer_arn, target_group_arns, names])
+
+ if args > 1:
+ raise ValidationError(
+ "Target group names, target group ARNs, and a load balancer ARN cannot be specified at the same time"
+ )
+
if load_balancer_arn:
if load_balancer_arn not in self.load_balancers:
raise LoadBalancerNotFoundError()
- return [
+ target_groups = [
tg
for tg in self.target_groups.values()
if load_balancer_arn in tg.load_balancer_arns
]
+ if target_groups is None or len(target_groups) == 0:
+ raise TargetGroupNotFoundError()
+ return sorted(target_groups, key=lambda tg: tg.name)
if target_group_arns:
try:
- return [self.target_groups[arn] for arn in target_group_arns]
+ target_groups = [self.target_groups[arn] for arn in target_group_arns]
+ return sorted(target_groups, key=lambda tg: tg.name)
except KeyError:
raise TargetGroupNotFoundError()
+
if names:
matched = []
for name in names:
@@ -1401,9 +1414,9 @@ def describe_target_groups(
if not found:
raise TargetGroupNotFoundError()
matched.append(found)
- return matched
+ return sorted(matched, key=lambda tg: tg.name)
- return self.target_groups.values()
+ return sorted(self.target_groups.values(), key=lambda tg: tg.name)
def describe_listeners(
self, load_balancer_arn: Optional[str], listener_arns: List[str]
diff --git a/moto/elbv2/responses.py b/moto/elbv2/responses.py
index 652d5b9b9aa0..443d92fbb416 100644
--- a/moto/elbv2/responses.py
+++ b/moto/elbv2/responses.py
@@ -1070,6 +1070,7 @@ def remove_listener_certificates(self) -> str:
{% if target_group.vpc_id %}
{{ target_group.vpc_id }}
{% endif %}
+ {{ target_group.ip_address_type }}
{{ target_group.healthcheck_protocol }}
{% if target_group.healthcheck_port %}{{ target_group.healthcheck_port }}{% endif %}
{{ target_group.healthcheck_path or '' }}
diff --git a/tests/test_elbv2/test_elbv2_target_groups.py b/tests/test_elbv2/test_elbv2_target_groups.py
index 53e311e11b63..1370cb8fe5fc 100644
--- a/tests/test_elbv2/test_elbv2_target_groups.py
+++ b/tests/test_elbv2/test_elbv2_target_groups.py
@@ -122,7 +122,7 @@ def test_create_target_group_and_listeners():
http_listener_arn = listener["ListenerArn"]
response = conn.describe_target_groups(
- LoadBalancerArn=load_balancer_arn, Names=["a-target"]
+ LoadBalancerArn=load_balancer_arn,
)
assert len(response["TargetGroups"]) == 1
@@ -455,17 +455,23 @@ def test_describe_invalid_target_group():
conn.describe_target_groups(Names=["invalid"])
err = exc.value.response["Error"]
assert err["Code"] == "TargetGroupNotFound"
- assert err["Message"] == "The specified target group does not exist."
+ assert err["Message"] == "One or more target groups not found"
@mock_elbv2
@mock_ec2
-def test_describe_target_groups_no_arguments():
+def test_describe_target_groups():
+ elbv2 = boto3.client("elbv2", region_name="us-east-1")
+
response, vpc, _, _, _, conn = create_load_balancer()
+ lb_arn = response["LoadBalancers"][0]["LoadBalancerArn"]
assert "LoadBalancerArn" in response["LoadBalancers"][0]
- conn.create_target_group(
+ groups = conn.describe_target_groups()["TargetGroups"]
+ assert len(groups) == 0
+
+ response = conn.create_target_group(
Name="a-target",
Protocol="HTTP",
Port=8080,
@@ -479,11 +485,84 @@ def test_describe_target_groups_no_arguments():
UnhealthyThresholdCount=2,
Matcher={"HttpCode": "201"},
)
+ arn_a = response["TargetGroups"][0]["TargetGroupArn"]
+
+ conn.create_listener(
+ LoadBalancerArn=lb_arn,
+ Protocol="HTTP",
+ Port=80,
+ DefaultActions=[{"Type": "forward", "TargetGroupArn": arn_a}],
+ )
groups = conn.describe_target_groups()["TargetGroups"]
assert len(groups) == 1
assert groups[0]["Matcher"] == {"HttpCode": "201"}
+ response = elbv2.create_target_group(
+ Name="c-target",
+ Protocol="HTTP",
+ Port=8081,
+ VpcId=vpc.id,
+ )
+ arn_c = response["TargetGroups"][0]["TargetGroupArn"]
+ groups = conn.describe_target_groups()["TargetGroups"]
+ assert len(groups) == 2
+ assert groups[0]["TargetGroupName"] == "a-target"
+ assert groups[1]["TargetGroupName"] == "c-target"
+
+ response = elbv2.create_target_group(
+ Name="b-target",
+ Protocol="HTTP",
+ Port=8082,
+ VpcId=vpc.id,
+ )
+ arn_b = response["TargetGroups"][0]["TargetGroupArn"]
+ groups = conn.describe_target_groups()["TargetGroups"]
+ assert len(groups) == 3
+ assert groups[0]["TargetGroupName"] == "a-target"
+ assert groups[1]["TargetGroupName"] == "b-target"
+ assert groups[2]["TargetGroupName"] == "c-target"
+
+ groups = conn.describe_target_groups(Names=["a-target"])["TargetGroups"]
+ assert len(groups) == 1
+ assert groups[0]["TargetGroupName"] == "a-target"
+
+ groups = conn.describe_target_groups(Names=["a-target", "b-target"])["TargetGroups"]
+ assert len(groups) == 2
+ assert groups[0]["TargetGroupName"] == "a-target"
+ assert groups[1]["TargetGroupName"] == "b-target"
+
+ groups = conn.describe_target_groups(TargetGroupArns=[arn_b])["TargetGroups"]
+ assert len(groups) == 1
+ assert groups[0]["TargetGroupName"] == "b-target"
+
+ groups = conn.describe_target_groups(TargetGroupArns=[arn_b, arn_c])["TargetGroups"]
+ assert len(groups) == 2
+ assert groups[0]["TargetGroupName"] == "b-target"
+ assert groups[1]["TargetGroupName"] == "c-target"
+
+ groups = conn.describe_target_groups(LoadBalancerArn=lb_arn)["TargetGroups"]
+ assert len(groups) == 1
+ assert groups[0]["TargetGroupName"] == "a-target"
+
+ response = conn.create_target_group(
+ Name="d-target",
+ Protocol="HTTP",
+ Port=8082,
+ VpcId=vpc.id,
+ )
+ arn_d = response["TargetGroups"][0]["TargetGroupArn"]
+ conn.create_listener(
+ LoadBalancerArn=lb_arn,
+ Protocol="HTTP",
+ Port=80,
+ DefaultActions=[{"Type": "forward", "TargetGroupArn": arn_d}],
+ )
+ groups = conn.describe_target_groups(LoadBalancerArn=lb_arn)["TargetGroups"]
+ assert len(groups) == 2
+ assert groups[0]["TargetGroupName"] == "a-target"
+ assert groups[1]["TargetGroupName"] == "d-target"
+
@mock_elbv2
@mock_ec2