Repository: getmoto/moto
Pull request #7966 (2024-08-11 06:11:45)

chore: update EC2 Instance Offerings
Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action


Patch:
diff --git a/moto/cloudformation/models.py b/moto/cloudformation/models.py
index 6d5c6bee5..08ce7c7d7 100644
--- a/moto/cloudformation/models.py
+++ b/moto/cloudformation/models.py
@@ -28,6 +28,7 @@ from .utils import (
     generate_stackset_arn,
     generate_stackset_id,
     get_stack_from_s3_url,
+    validate_create_change_set,
     validate_template_cfn_lint,
     yaml_tag_constructor,
 )
@@ -1007,6 +1008,7 @@ class CloudFormationBackend(BaseBackend):
         tags: Optional[Dict[str, str]] = None,
         role_arn: Optional[str] = None,
     ) -> Tuple[str, str]:
+        validate_create_change_set(change_set_name)
         if change_set_type == "UPDATE":
             for stack in self.stacks.values():
                 if stack.name == stack_name:
diff --git a/moto/cloudformation/utils.py b/moto/cloudformation/utils.py
index af47a4068..598f8dc7c 100644
--- a/moto/cloudformation/utils.py
+++ b/moto/cloudformation/utils.py
@@ -8,6 +8,8 @@ import yaml
 from moto.moto_api._internal import mock_random as random
 from moto.utilities.utils import get_partition
 
+from .exceptions import ValidationError
+
 
 def generate_stack_id(stack_name: str, region: str, account: str) -> str:
     random_id = random.uuid4()
@@ -134,3 +136,19 @@ def get_stack_from_s3_url(template_url: str, account_id: str, partition: str) ->
 
     key = s3_backends[account_id][partition].get_object(bucket_name, key_name)
     return key.value.decode("utf-8")  # type: ignore[union-attr]
+
+
+def validate_create_change_set(change_set_name: str) -> None:
+    if not (change_set_name and change_set_name[0].isalpha()):
+        raise ValidationError(f"Invalid change set name: {change_set_name}")
+
+    if not all(c.isalnum() or c == "-" for c in change_set_name):
+        raise ValidationError(f"Invalid change set name: {change_set_name}")
+
+    if len(change_set_name) > 128:
+        raise ValidationError(
+            f"Change set name exceeds 128 characters: {change_set_name}"
+        )
+
+    # Additional validations can be added here later
+    return
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-northeast-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-northeast-1.json
index db480dcb5..cd498e3a3 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-northeast-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-northeast-1.json
@@ -5131,6 +5131,46 @@
   "InstanceType": "r7i.xlarge",
   "Location": "apne1-az2"
  },
+ {
+  "InstanceType": "r7iz.12xlarge",
+  "Location": "apne1-az2"
+ },
+ {
+  "InstanceType": "r7iz.16xlarge",
+  "Location": "apne1-az2"
+ },
+ {
+  "InstanceType": "r7iz.2xlarge",
+  "Location": "apne1-az2"
+ },
+ {
+  "InstanceType": "r7iz.32xlarge",
+  "Location": "apne1-az2"
+ },
+ {
+  "InstanceType": "r7iz.4xlarge",
+  "Location": "apne1-az2"
+ },
+ {
+  "InstanceType": "r7iz.8xlarge",
+  "Location": "apne1-az2"
+ },
+ {
+  "InstanceType": "r7iz.large",
+  "Location": "apne1-az2"
+ },
+ {
+  "InstanceType": "r7iz.metal-16xl",
+  "Location": "apne1-az2"
+ },
+ {
+  "InstanceType": "r7iz.metal-32xl",
+  "Location": "apne1-az2"
+ },
+ {
+  "InstanceType": "r7iz.xlarge",
+  "Location": "apne1-az2"
+ },
  {
   "InstanceType": "t2.2xlarge",
   "Location": "apne1-az2"
@@ -5963,6 +6003,26 @@
   "InstanceType": "c7gn.xlarge",
   "Location": "apne1-az4"
  },
+ {
+  "InstanceType": "c7i-flex.2xlarge",
+  "Location": "apne1-az4"
+ },
+ {
+  "InstanceType": "c7i-flex.4xlarge",
+  "Location": "apne1-az4"
+ },
+ {
+  "InstanceType": "c7i-flex.8xlarge",
+  "Location": "apne1-az4"
+ },
+ {
+  "InstanceType": "c7i-flex.large",
+  "Location": "apne1-az4"
+ },
+ {
+  "InstanceType": "c7i-flex.xlarge",
+  "Location": "apne1-az4"
+ },
  {
   "InstanceType": "c7i.12xlarge",
   "Location": "apne1-az4"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-northeast-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-northeast-2.json
index 5a6f116e0..71dedfdda 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-northeast-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-northeast-2.json
@@ -1807,6 +1807,10 @@
   "InstanceType": "u-12tb1.112xlarge",
   "Location": "apne2-az1"
  },
+ {
+  "InstanceType": "u-24tb1.112xlarge",
+  "Location": "apne2-az1"
+ },
  {
   "InstanceType": "u-6tb1.112xlarge",
   "Location": "apne2-az1"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-central-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-central-1.json
index f26218770..f0910b081 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-central-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-central-1.json
@@ -5007,6 +5007,10 @@
   "InstanceType": "u-12tb1.112xlarge",
   "Location": "euc1-az2"
  },
+ {
+  "InstanceType": "u-18tb1.112xlarge",
+  "Location": "euc1-az2"
+ },
  {
   "InstanceType": "u-3tb1.56xlarge",
   "Location": "euc1-az2"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-3.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-3.json
index a630f5361..42da48e25 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-3.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-3.json
@@ -1447,6 +1447,10 @@
   "InstanceType": "u-6tb1.56xlarge",
   "Location": "euw3-az1"
  },
+ {
+  "InstanceType": "u-9tb1.112xlarge",
+  "Location": "euw3-az1"
+ },
  {
   "InstanceType": "x1.16xlarge",
   "Location": "euw3-az1"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-1.json
index 2fae83566..7a7ed40cf 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-1.json
@@ -571,6 +571,42 @@
   "InstanceType": "c7gd.xlarge",
   "Location": "use1-az1"
  },
+ {
+  "InstanceType": "c7gn.12xlarge",
+  "Location": "use1-az1"
+ },
+ {
+  "InstanceType": "c7gn.16xlarge",
+  "Location": "use1-az1"
+ },
+ {
+  "InstanceType": "c7gn.2xlarge",
+  "Location": "use1-az1"
+ },
+ {
+  "InstanceType": "c7gn.4xlarge",
+  "Location": "use1-az1"
+ },
+ {
+  "InstanceType": "c7gn.8xlarge",
+  "Location": "use1-az1"
+ },
+ {
+  "InstanceType": "c7gn.large",
+  "Location": "use1-az1"
+ },
+ {
+  "InstanceType": "c7gn.medium",
+  "Location": "use1-az1"
+ },
+ {
+  "InstanceType": "c7gn.metal",
+  "Location": "use1-az1"
+ },
+ {
+  "InstanceType": "c7gn.xlarge",
+  "Location": "use1-az1"
+ },
  {
   "InstanceType": "c7i.12xlarge",
   "Location": "use1-az1"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-west-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-west-2.json
index bfed43c4a..3b0847951 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-west-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-west-2.json
@@ -635,6 +635,26 @@
   "InstanceType": "c7gn.xlarge",
   "Location": "usw2-az1"
  },
+ {
+  "InstanceType": "c7i-flex.2xlarge",
+  "Location": "usw2-az1"
+ },
+ {
+  "InstanceType": "c7i-flex.4xlarge",
+  "Location": "usw2-az1"
+ },
+ {
+  "InstanceType": "c7i-flex.8xlarge",
+  "Location": "usw2-az1"
+ },
+ {
+  "InstanceType": "c7i-flex.large",
+  "Location": "usw2-az1"
+ },
+ {
+  "InstanceType": "c7i-flex.xlarge",
+  "Location": "usw2-az1"
+ },
  {
   "InstanceType": "c7i.12xlarge",
   "Location": "usw2-az1"
@@ -9731,6 +9751,26 @@
   "InstanceType": "c7gd.xlarge",
   "Location": "usw2-az4"
  },
+ {
+  "InstanceType": "c7i-flex.2xlarge",
+  "Location": "usw2-az4"
+ },
+ {
+  "InstanceType": "c7i-flex.4xlarge",
+  "Location": "usw2-az4"
+ },
+ {
+  "InstanceType": "c7i-flex.8xlarge",
+  "Location": "usw2-az4"
+ },
+ {
+  "InstanceType": "c7i-flex.large",
+  "Location": "usw2-az4"
+ },
+ {
+  "InstanceType": "c7i-flex.xlarge",
+  "Location": "usw2-az4"
+ },
  {
   "InstanceType": "c7i.12xlarge",
   "Location": "usw2-az4"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-northeast-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-northeast-1.json
index 83c391cce..0f7c0129e 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-northeast-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-northeast-1.json
@@ -627,6 +627,26 @@
   "InstanceType": "c7gn.xlarge",
   "Location": "ap-northeast-1a"
  },
+ {
+  "InstanceType": "c7i-flex.2xlarge",
+  "Location": "ap-northeast-1a"
+ },
+ {
+  "InstanceType": "c7i-flex.4xlarge",
+  "Location": "ap-northeast-1a"
+ },
+ {
+  "InstanceType": "c7i-flex.8xlarge",
+  "Location": "ap-northeast-1a"
+ },
+ {
+  "InstanceType": "c7i-flex.large",
+  "Location": "ap-northeast-1a"
+ },
+ {
+  "InstanceType": "c7i-flex.xlarge",
+  "Location": "ap-northeast-1a"
+ },
  {
   "InstanceType": "c7i.12xlarge",
   "Location": "ap-northeast-1a"
@@ -8011,6 +8031,46 @@
   "InstanceType": "r7i.xlarge",
   "Location": "ap-northeast-1d"
  },
+ {
+  "InstanceType": "r7iz.12xlarge",
+  "Location": "ap-northeast-1d"
+ },
+ {
+  "InstanceType": "r7iz.16xlarge",
+  "Location": "ap-northeast-1d"
+ },
+ {
+  "InstanceType": "r7iz.2xlarge",
+  "Location": "ap-northeast-1d"
+ },
+ {
+  "InstanceType": "r7iz.32xlarge",
+  "Location": "ap-northeast-1d"
+ },
+ {
+  "InstanceType": "r7iz.4xlarge",
+  "Location": "ap-northeast-1d"
+ },
+ {
+  "InstanceType": "r7iz.8xlarge",
+  "Location": "ap-northeast-1d"
+ },
+ {
+  "InstanceType": "r7iz.large",
+  "Location": "ap-northeast-1d"
+ },
+ {
+  "InstanceType": "r7iz.metal-16xl",
+  "Location": "ap-northeast-1d"
+ },
+ {
+  "InstanceType": "r7iz.metal-32xl",
+  "Location": "ap-northeast-1d"
+ },
+ {
+  "InstanceType": "r7iz.xlarge",
+  "Location": "ap-northeast-1d"
+ },
  {
   "InstanceType": "t2.2xlarge",
   "Location": "ap-northeast-1d"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-northeast-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-northeast-2.json
index 44c0c3892..2ad63ec14 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-northeast-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-northeast-2.json
@@ -1807,6 +1807,10 @@
   "InstanceType": "u-12tb1.112xlarge",
   "Location": "ap-northeast-2a"
  },
+ {
+  "InstanceType": "u-24tb1.112xlarge",
+  "Location": "ap-northeast-2a"
+ },
  {
   "InstanceType": "u-6tb1.112xlarge",
   "Location": "ap-northeast-2a"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-central-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-central-1.json
index 6f48996ff..984c96841 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-central-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-central-1.json
@@ -2371,6 +2371,10 @@
   "InstanceType": "u-12tb1.112xlarge",
   "Location": "eu-central-1a"
  },
+ {
+  "InstanceType": "u-18tb1.112xlarge",
+  "Location": "eu-central-1a"
+ },
  {
   "InstanceType": "u-3tb1.56xlarge",
   "Location": "eu-central-1a"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-3.json b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-3.json
index 2466a2415..24fb02c4a 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-3.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-3.json
@@ -1447,6 +1447,10 @@
   "InstanceType": "u-6tb1.56xlarge",
   "Location": "eu-west-3a"
  },
+ {
+  "InstanceType": "u-9tb1.112xlarge",
+  "Location": "eu-west-3a"
+ },
  {
   "InstanceType": "x1.16xlarge",
   "Location": "eu-west-3a"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-1.json
index 88c7eb22c..e6533f0e6 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-1.json
@@ -9915,6 +9915,42 @@
   "InstanceType": "c7gd.xlarge",
   "Location": "us-east-1d"
  },
+ {
+  "InstanceType": "c7gn.12xlarge",
+  "Location": "us-east-1d"
+ },
+ {
+  "InstanceType": "c7gn.16xlarge",
+  "Location": "us-east-1d"
+ },
+ {
+  "InstanceType": "c7gn.2xlarge",
+  "Location": "us-east-1d"
+ },
+ {
+  "InstanceType": "c7gn.4xlarge",
+  "Location": "us-east-1d"
+ },
+ {
+  "InstanceType": "c7gn.8xlarge",
+  "Location": "us-east-1d"
+ },
+ {
+  "InstanceType": "c7gn.large",
+  "Location": "us-east-1d"
+ },
+ {
+  "InstanceType": "c7gn.medium",
+  "Location": "us-east-1d"
+ },
+ {
+  "InstanceType": "c7gn.metal",
+  "Location": "us-east-1d"
+ },
+ {
+  "InstanceType": "c7gn.xlarge",
+  "Location": "us-east-1d"
+ },
  {
   "InstanceType": "c7i.12xlarge",
   "Location": "us-east-1d"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/us-west-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone/us-west-2.json
index bc3d312b7..ef905cd2e 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/us-west-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/us-west-2.json
@@ -3631,6 +3631,26 @@
   "InstanceType": "c7gn.xlarge",
   "Location": "us-west-2b"
  },
+ {
+  "InstanceType": "c7i-flex.2xlarge",
+  "Location": "us-west-2b"
+ },
+ {
+  "InstanceType": "c7i-flex.4xlarge",
+  "Location": "us-west-2b"
+ },
+ {
+  "InstanceType": "c7i-flex.8xlarge",
+  "Location": "us-west-2b"
+ },
+ {
+  "InstanceType": "c7i-flex.large",
+  "Location": "us-west-2b"
+ },
+ {
+  "InstanceType": "c7i-flex.xlarge",
+  "Location": "us-west-2b"
+ },
  {
   "InstanceType": "c7i.12xlarge",
   "Location": "us-west-2b"
@@ -9731,6 +9751,26 @@
   "InstanceType": "c7gd.xlarge",
   "Location": "us-west-2d"
  },
+ {
+  "InstanceType": "c7i-flex.2xlarge",
+  "Location": "us-west-2d"
+ },
+ {
+  "InstanceType": "c7i-flex.4xlarge",
+  "Location": "us-west-2d"
+ },
+ {
+  "InstanceType": "c7i-flex.8xlarge",
+  "Location": "us-west-2d"
+ },
+ {
+  "InstanceType": "c7i-flex.large",
+  "Location": "us-west-2d"
+ },
+ {
+  "InstanceType": "c7i-flex.xlarge",
+  "Location": "us-west-2d"
+ },
  {
   "InstanceType": "c7i.12xlarge",
   "Location": "us-west-2d"
diff --git a/moto/ec2/resources/instance_type_offerings/region/eu-west-3.json b/moto/ec2/resources/instance_type_offerings/region/eu-west-3.json
index baa50a5a4..410390e3c 100644
--- a/moto/ec2/resources/instance_type_offerings/region/eu-west-3.json
+++ b/moto/ec2/resources/instance_type_offerings/region/eu-west-3.json
@@ -1499,6 +1499,10 @@
   "InstanceType": "u-6tb1.56xlarge",
   "Location": "eu-west-3"
  },
+ {
+  "InstanceType": "u-9tb1.112xlarge",
+  "Location": "eu-west-3"
+ },
  {
   "InstanceType": "x1.16xlarge",
   "Location": "eu-west-3"
diff --git a/moto/ec2/resources/instance_type_offerings/region/us-west-2.json b/moto/ec2/resources/instance_type_offerings/region/us-west-2.json
index 59adabaf8..0a7e73dad 100644
--- a/moto/ec2/resources/instance_type_offerings/region/us-west-2.json
+++ b/moto/ec2/resources/instance_type_offerings/region/us-west-2.json
@@ -659,6 +659,26 @@
   "InstanceType": "c7gn.xlarge",
   "Location": "us-west-2"
  },
+ {
+  "InstanceType": "c7i-flex.2xlarge",
+  "Location": "us-west-2"
+ },
+ {
+  "InstanceType": "c7i-flex.4xlarge",
+  "Location": "us-west-2"
+ },
+ {
+  "InstanceType": "c7i-flex.8xlarge",
+  "Location": "us-west-2"
+ },
+ {
+  "InstanceType": "c7i-flex.large",
+  "Location": "us-west-2"
+ },
+ {
+  "InstanceType": "c7i-flex.xlarge",
+  "Location": "us-west-2"
+ },
  {
   "InstanceType": "c7i.12xlarge",
   "Location": "us-west-2"


Test patch:
diff --git a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py
index d34e6e4d5..c6c5815d1 100644
--- a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py
+++ b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py
@@ -1078,7 +1078,7 @@ def test_get_template_summary_for_stack_created_by_changeset_execution():
     conn.create_change_set(
         StackName="stack_from_changeset",
         TemplateBody=json.dumps(dummy_template3),
-        ChangeSetName="test_changeset",
+        ChangeSetName="test-changeset",
         ChangeSetType="CREATE",
     )
     with pytest.raises(
@@ -1086,7 +1086,7 @@ def test_get_template_summary_for_stack_created_by_changeset_execution():
         match="GetTemplateSummary cannot be called on REVIEW_IN_PROGRESS stacks",
     ):
         conn.get_template_summary(StackName="stack_from_changeset")
-    conn.execute_change_set(ChangeSetName="test_changeset")
+    conn.execute_change_set(ChangeSetName="test-changeset")
     result = conn.get_template_summary(StackName="stack_from_changeset")
     assert result["ResourceTypes"] == ["AWS::EC2::VPC"]
     assert result["Version"] == "2010-09-09"
@@ -2555,6 +2555,46 @@ def test_create_and_update_stack_with_unknown_resource():
             )
 
 
+@mock_aws
+def test_invalid_change_set_name_starting_char():
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    with pytest.raises(ClientError):
+        cf.create_change_set(
+            StackName=TEST_STACK_NAME,
+            ChangeSetName="1invalid-change-set-name",
+            TemplateBody=json.dumps(dummy_template),
+            Description="Test Change Set",
+            ChangeSetType="CREATE",
+        )
+
+
+@mock_aws
+def test_invalid_change_set_name_length():
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    long_name = "a" * 129  # Exceeds the 128 character limit
+    with pytest.raises(ClientError):
+        cf.create_change_set(
+            StackName=TEST_STACK_NAME,
+            ChangeSetName=long_name,
+            TemplateBody=json.dumps(dummy_template),
+            Description="Test Change Set",
+            ChangeSetType="CREATE",
+        )
+
+
+@mock_aws
+def test_invalid_change_set_name_special_chars():
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    with pytest.raises(ClientError):
+        cf.create_change_set(
+            StackName=TEST_STACK_NAME,
+            ChangeSetName="invalid@name",
+            TemplateBody=json.dumps(dummy_template),
+            Description="Test Change Set",
+            ChangeSetType="CREATE",
+        )
+
+
 def get_role_name():
     with mock_aws():
         iam = boto3.client("iam", region_name=REGION_NAME)