Repository: getmoto/moto
Pull request #8322 (2024-11-16 13:08:05)

Improve IoT Job and JobTemplate
Hello

In this PR I'd like to enhance IoT Job object and JobTemplate

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getmoto/moto/pull/8322?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) Report
Attention: Patch coverage is `86.72566%` with `15 lines` in your changes missing coverage. Please review.
> Project coverage is 94.56%. Comparing base [(`10bdd08`)](https://app.codecov.io/gh/getmoto/moto/commit/10bdd0837c8dfef21f22118521cf687119168e99?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) to head [(`5323d6f`)](https://app.codecov.io/gh/getmoto/moto/commit/5323d6fd87e0e65c3cdb9851bb66fd18735909f7?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).

| [Files with missing lines](https://app.codecov.io/gh/getmoto/moto/pull/8322?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Patch % | Lines |
|---|---|---|
| [moto/iot/models.py](https://app.codecov.io/gh/getmoto/moto/pull/8322?src=pr&el=tree&filepath=moto%2Fiot%2Fmodels.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#diff-bW90by9pb3QvbW9kZWxzLnB5) | 86.04% | [12 Missing :warning: ](https://app.codecov.io/gh/getmoto/moto/pull/8322?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) |
| [moto/iot/exceptions.py](https://app.codecov.io/gh/getmoto/moto/pull/8322?src=pr&el=tree&filepath=moto%2Fiot%2Fexceptions.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#diff-bW90by9pb3QvZXhjZXB0aW9ucy5weQ==) | 50.00% | [2 Missing :warning: ](https://app.codecov.io/gh/getmoto/moto/pull/8322?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) |
| [moto/iot/utils.py](https://app.codecov.io/gh/getmoto/moto/pull/8322?src=pr&el=tree&filepath=moto%2Fiot%2Futils.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#diff-bW90by9pb3QvdXRpbHMucHk=) | 85.71% | [1 Missing :warning: ](https://app.codecov.io/gh/getmoto/moto/pull/8322?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #8322      +/-   ##
==========================================
- Coverage   94.57%   94.56%   -0.01%     
==========================================
  Files        1159     1159              
  Lines      100936   101048     +112     
==========================================
+ Hits        95458    95555      +97     
- Misses       5478     5493      +15     
```

| [Flag](https://app.codecov.io/gh/getmoto/moto/pull/8322/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Coverage Δ | |
|---|---|---|
| [servertests](https://app.codecov.io/gh/getmoto/moto/pull/8322/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `28.89% <30.97%> (-0.01%)` | :arrow_down: |
| [unittests](https://app.codecov.io/gh/getmoto/moto/pull/8322/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `94.53% <86.72%> (-0.01%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/getmoto/moto/pull/8322?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).


Patch:
diff --git a/CLOUDFORMATION_COVERAGE.md b/CLOUDFORMATION_COVERAGE.md
index 34bcedc0a..9d3cd37dd 100644
--- a/CLOUDFORMATION_COVERAGE.md
+++ b/CLOUDFORMATION_COVERAGE.md
@@ -282,6 +282,11 @@ Please let us know if you'd like support for a resource not yet listed here.
    - [x] update implemented
    - [x] delete implemented
    - [x] Fn::GetAtt implemented
+- AWS::IoT::JobTemplate:
+   - [x] create implemented
+   - [x] update implemented
+   - [x] delete implemented
+   - [x] Fn::GetAtt implemented
 - AWS::KMS::Key:
    - [x] create implemented
    - [ ] update implemented
diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md
index 2349a0b5f..58af0d7b8 100644
--- a/IMPLEMENTATION_COVERAGE.md
+++ b/IMPLEMENTATION_COVERAGE.md
@@ -4528,7 +4528,7 @@
 - [ ] create_dynamic_thing_group
 - [ ] create_fleet_metric
 - [X] create_job
-- [ ] create_job_template
+- [X] create_job_template
 - [X] create_keys_and_certificate
 - [ ] create_mitigation_action
 - [ ] create_ota_update
@@ -4562,7 +4562,7 @@
 - [ ] delete_fleet_metric
 - [X] delete_job
 - [X] delete_job_execution
-- [ ] delete_job_template
+- [X] delete_job_template
 - [ ] delete_mitigation_action
 - [ ] delete_ota_update
 - [ ] delete_package
@@ -4604,7 +4604,7 @@
 - [ ] describe_index
 - [X] describe_job
 - [X] describe_job_execution
-- [ ] describe_job_template
+- [X] describe_job_template
 - [ ] describe_managed_job_template
 - [ ] describe_mitigation_action
 - [ ] describe_provisioning_template
@@ -4665,7 +4665,7 @@
 - [ ] list_indices
 - [X] list_job_executions_for_job
 - [X] list_job_executions_for_thing
-- [ ] list_job_templates
+- [X] list_job_templates
 - [X] list_jobs
 - [ ] list_managed_job_templates
 - [ ] list_metric_values
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 cde066814..4214c3ec5 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
@@ -723,22 +723,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "apne1-az1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "apne1-az1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "apne1-az1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "apne1-az1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "apne1-az1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "apne1-az1"
@@ -6167,22 +6151,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "apne1-az4"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "apne1-az4"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "apne1-az4"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "apne1-az4"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "apne1-az4"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "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 d4635928c..aa09d5167 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
@@ -471,22 +471,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "apne2-az1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "apne2-az1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "apne2-az1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "apne2-az1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "apne2-az1"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "apne2-az1"
@@ -3775,22 +3759,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "apne2-az3"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "apne2-az3"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "apne2-az3"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "apne2-az3"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "apne2-az3"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "apne2-az3"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-1.json
index 599a36196..fe312a9f4 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-1.json
@@ -663,18 +663,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "apse1-az1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "apse1-az1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "apse1-az1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "apse1-az1"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "apse1-az1"
@@ -3303,18 +3291,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "apse1-az2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "apse1-az2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "apse1-az2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "apse1-az2"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "apse1-az2"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-2.json
index 8611e7960..2dbd04a69 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-2.json
@@ -707,22 +707,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "apse2-az1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "apse2-az1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "apse2-az1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "apse2-az1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "apse2-az1"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "apse2-az1"
@@ -5811,22 +5795,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "apse2-az3"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "apse2-az3"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "apse2-az3"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "apse2-az3"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "apse2-az3"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "apse2-az3"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ca-central-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ca-central-1.json
index 3c7cda387..423b99289 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ca-central-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ca-central-1.json
@@ -551,18 +551,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "cac1-az1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "cac1-az1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "cac1-az1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "cac1-az1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "cac1-az1"
@@ -1403,6 +1391,10 @@
   "InstanceType": "m7i.xlarge",
   "Location": "cac1-az1"
  },
+ {
+  "InstanceType": "mac2-m2.metal",
+  "Location": "cac1-az1"
+ },
  {
   "InstanceType": "r4.16xlarge",
   "Location": "cac1-az1"
@@ -2579,18 +2571,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "cac1-az2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "cac1-az2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "cac1-az2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "cac1-az2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "cac1-az2"
@@ -3431,6 +3411,10 @@
   "InstanceType": "m7i.xlarge",
   "Location": "cac1-az2"
  },
+ {
+  "InstanceType": "mac2-m2.metal",
+  "Location": "cac1-az2"
+ },
  {
   "InstanceType": "p3.16xlarge",
   "Location": "cac1-az2"
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 dbc1c5afc..db5a2879f 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
@@ -3479,22 +3479,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "euc1-az2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "euc1-az2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "euc1-az2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "euc1-az2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "euc1-az2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "euc1-az2"
@@ -6275,22 +6259,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "euc1-az3"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "euc1-az3"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "euc1-az3"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "euc1-az3"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "euc1-az3"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "euc1-az3"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-south-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-south-2.json
index 44137ff73..02bc1596e 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-south-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-south-2.json
@@ -391,6 +391,46 @@
   "InstanceType": "g5g.xlarge",
   "Location": "eus2-az1"
  },
+ {
+  "InstanceType": "g6.12xlarge",
+  "Location": "eus2-az1"
+ },
+ {
+  "InstanceType": "g6.16xlarge",
+  "Location": "eus2-az1"
+ },
+ {
+  "InstanceType": "g6.24xlarge",
+  "Location": "eus2-az1"
+ },
+ {
+  "InstanceType": "g6.2xlarge",
+  "Location": "eus2-az1"
+ },
+ {
+  "InstanceType": "g6.48xlarge",
+  "Location": "eus2-az1"
+ },
+ {
+  "InstanceType": "g6.4xlarge",
+  "Location": "eus2-az1"
+ },
+ {
+  "InstanceType": "g6.8xlarge",
+  "Location": "eus2-az1"
+ },
+ {
+  "InstanceType": "g6.xlarge",
+  "Location": "eus2-az1"
+ },
+ {
+  "InstanceType": "gr6.4xlarge",
+  "Location": "eus2-az1"
+ },
+ {
+  "InstanceType": "gr6.8xlarge",
+  "Location": "eus2-az1"
+ },
  {
   "InstanceType": "i3.16xlarge",
   "Location": "eus2-az1"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-1.json
index 83d328580..5cc66a5c9 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-1.json
@@ -791,22 +791,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "euw1-az1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "euw1-az1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "euw1-az1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "euw1-az1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "euw1-az1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "euw1-az1"
@@ -3847,22 +3831,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "euw1-az2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "euw1-az2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "euw1-az2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "euw1-az2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "euw1-az2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "euw1-az2"
@@ -6883,22 +6851,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "euw1-az3"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "euw1-az3"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "euw1-az3"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "euw1-az3"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "euw1-az3"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "euw1-az3"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-2.json
index e57fa2469..aefbeba36 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-west-2.json
@@ -2423,22 +2423,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "euw2-az2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "euw2-az2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "euw2-az2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "euw2-az2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "euw2-az2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "euw2-az2"
@@ -4367,22 +4351,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "euw2-az3"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "euw2-az3"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "euw2-az3"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "euw2-az3"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "euw2-az3"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "euw2-az3"
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 2934b97a1..fbfbf0e02 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
@@ -3951,22 +3951,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "use1-az2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "use1-az2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "use1-az2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "use1-az2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "use1-az2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "use1-az2"
@@ -6383,22 +6367,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "use1-az3"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "use1-az3"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "use1-az3"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "use1-az3"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "use1-az3"
- },
  {
   "InstanceType": "i2.2xlarge",
   "Location": "use1-az3"
@@ -7411,22 +7379,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "use1-az4"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "use1-az4"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "use1-az4"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "use1-az4"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "use1-az4"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "use1-az4"
@@ -13315,22 +13267,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "use1-az6"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "use1-az6"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "use1-az6"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "use1-az6"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "use1-az6"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "use1-az6"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-2.json
index bd34ecbbd..5505fd1f6 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-2.json
@@ -775,22 +775,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "use2-az1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "use2-az1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "use2-az1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "use2-az1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "use2-az1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "use2-az1"
@@ -3831,22 +3815,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "use2-az2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "use2-az2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "use2-az2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "use2-az2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "use2-az2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "use2-az2"
@@ -6887,22 +6855,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "use2-az3"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "use2-az3"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "use2-az3"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "use2-az3"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "use2-az3"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "use2-az3"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-west-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-west-1.json
index 856d28e6e..5a765541d 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-west-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-west-1.json
@@ -559,18 +559,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "usw1-az1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "usw1-az1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "usw1-az1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "usw1-az1"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "usw1-az1"
@@ -2575,18 +2563,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "usw1-az3"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "usw1-az3"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "usw1-az3"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "usw1-az3"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "usw1-az3"
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 5798bb3ee..f4a1ed68c 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
@@ -819,22 +819,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "usw2-az1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "usw2-az1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "usw2-az1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "usw2-az1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "usw2-az1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "usw2-az1"
@@ -4167,22 +4151,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "usw2-az2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "usw2-az2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "usw2-az2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "usw2-az2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "usw2-az2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "usw2-az2"
@@ -7327,22 +7295,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "usw2-az3"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "usw2-az3"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "usw2-az3"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "usw2-az3"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "usw2-az3"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "usw2-az3"
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 2c692c238..8b94541c8 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
@@ -747,22 +747,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "ap-northeast-1a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-northeast-1a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-northeast-1a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-northeast-1a"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "ap-northeast-1a"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "ap-northeast-1a"
@@ -3663,22 +3647,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "ap-northeast-1c"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-northeast-1c"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-northeast-1c"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-northeast-1c"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "ap-northeast-1c"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "ap-northeast-1c"
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 27fa12e07..334037935 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
@@ -471,22 +471,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "ap-northeast-2a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-northeast-2a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-northeast-2a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-northeast-2a"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "ap-northeast-2a"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "ap-northeast-2a"
@@ -3775,22 +3759,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "ap-northeast-2c"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-northeast-2c"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-northeast-2c"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-northeast-2c"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "ap-northeast-2c"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "ap-northeast-2c"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-1.json
index 7ab2e52d8..ba99f04f9 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-1.json
@@ -663,18 +663,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "ap-southeast-1a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-southeast-1a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-southeast-1a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-southeast-1a"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "ap-southeast-1a"
@@ -3303,18 +3291,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "ap-southeast-1b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-southeast-1b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-southeast-1b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-southeast-1b"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "ap-southeast-1b"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-2.json
index ea4d84bdf..b6dbddff3 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-2.json
@@ -671,22 +671,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "ap-southeast-2a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-southeast-2a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-southeast-2a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-southeast-2a"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "ap-southeast-2a"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "ap-southeast-2a"
@@ -3139,22 +3123,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "ap-southeast-2b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-southeast-2b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-southeast-2b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-southeast-2b"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "ap-southeast-2b"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "ap-southeast-2b"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/ca-central-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/ca-central-1.json
index 5f93eada4..381f2979c 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/ca-central-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/ca-central-1.json
@@ -551,18 +551,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "ca-central-1a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ca-central-1a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ca-central-1a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ca-central-1a"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "ca-central-1a"
@@ -1403,6 +1391,10 @@
   "InstanceType": "m7i.xlarge",
   "Location": "ca-central-1a"
  },
+ {
+  "InstanceType": "mac2-m2.metal",
+  "Location": "ca-central-1a"
+ },
  {
   "InstanceType": "r4.16xlarge",
   "Location": "ca-central-1a"
@@ -2579,18 +2571,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "ca-central-1b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ca-central-1b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ca-central-1b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ca-central-1b"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "ca-central-1b"
@@ -3431,6 +3411,10 @@
   "InstanceType": "m7i.xlarge",
   "Location": "ca-central-1b"
  },
+ {
+  "InstanceType": "mac2-m2.metal",
+  "Location": "ca-central-1b"
+ },
  {
   "InstanceType": "p3.16xlarge",
   "Location": "ca-central-1b"
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 b955b9ef0..6b445f80c 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
@@ -679,22 +679,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "eu-central-1a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-central-1a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-central-1a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-central-1a"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-central-1a"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "eu-central-1a"
@@ -3475,22 +3459,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "eu-central-1b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-central-1b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-central-1b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-central-1b"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-central-1b"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "eu-central-1b"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-south-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-south-2.json
index 340152620..80f96a949 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-south-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-south-2.json
@@ -391,6 +391,46 @@
   "InstanceType": "g5g.xlarge",
   "Location": "eu-south-2a"
  },
+ {
+  "InstanceType": "g6.12xlarge",
+  "Location": "eu-south-2a"
+ },
+ {
+  "InstanceType": "g6.16xlarge",
+  "Location": "eu-south-2a"
+ },
+ {
+  "InstanceType": "g6.24xlarge",
+  "Location": "eu-south-2a"
+ },
+ {
+  "InstanceType": "g6.2xlarge",
+  "Location": "eu-south-2a"
+ },
+ {
+  "InstanceType": "g6.48xlarge",
+  "Location": "eu-south-2a"
+ },
+ {
+  "InstanceType": "g6.4xlarge",
+  "Location": "eu-south-2a"
+ },
+ {
+  "InstanceType": "g6.8xlarge",
+  "Location": "eu-south-2a"
+ },
+ {
+  "InstanceType": "g6.xlarge",
+  "Location": "eu-south-2a"
+ },
+ {
+  "InstanceType": "gr6.4xlarge",
+  "Location": "eu-south-2a"
+ },
+ {
+  "InstanceType": "gr6.8xlarge",
+  "Location": "eu-south-2a"
+ },
  {
   "InstanceType": "i3.16xlarge",
   "Location": "eu-south-2a"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-1.json
index 1b641c952..964b78cae 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-1.json
@@ -767,22 +767,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "eu-west-1a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-west-1a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-west-1a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-west-1a"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-west-1a"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "eu-west-1a"
@@ -3755,22 +3739,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "eu-west-1b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-west-1b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-west-1b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-west-1b"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-west-1b"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "eu-west-1b"
@@ -6811,22 +6779,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "eu-west-1c"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-west-1c"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-west-1c"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-west-1c"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-west-1c"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "eu-west-1c"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-2.json
index 279d28039..5d94e645e 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-west-2.json
@@ -559,22 +559,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "eu-west-2a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-west-2a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-west-2a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-west-2a"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-west-2a"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "eu-west-2a"
@@ -2503,22 +2487,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "eu-west-2b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-west-2b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-west-2b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-west-2b"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-west-2b"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "eu-west-2b"
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 e9b86bc49..7753f47fb 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
@@ -795,22 +795,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "us-east-1a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-east-1a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-east-1a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-east-1a"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-east-1a"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-east-1a"
@@ -3999,22 +3983,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "us-east-1b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-east-1b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-east-1b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-east-1b"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-east-1b"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-east-1b"
@@ -7303,22 +7271,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "us-east-1c"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-east-1c"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-east-1c"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-east-1c"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-east-1c"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-east-1c"
@@ -13023,22 +12975,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "us-east-1e"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-east-1e"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-east-1e"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-east-1e"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-east-1e"
- },
  {
   "InstanceType": "i2.2xlarge",
   "Location": "us-east-1e"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-2.json
index 6c4bfcafa..bf9c629f1 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-2.json
@@ -775,22 +775,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "us-east-2a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-east-2a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-east-2a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-east-2a"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-east-2a"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-east-2a"
@@ -3831,22 +3815,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "us-east-2b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-east-2b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-east-2b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-east-2b"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-east-2b"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-east-2b"
@@ -6887,22 +6855,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "us-east-2c"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-east-2c"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-east-2c"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-east-2c"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-east-2c"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-east-2c"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/us-west-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/us-west-1.json
index 7b1de2a15..233bdbd81 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/us-west-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/us-west-1.json
@@ -559,18 +559,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "us-west-1a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-west-1a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-west-1a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-west-1a"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "us-west-1a"
@@ -2575,18 +2563,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "us-west-1b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-west-1b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-west-1b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-west-1b"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "us-west-1b"
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 7cb54471a..98152b25b 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
@@ -839,22 +839,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "us-west-2a"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-west-2a"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-west-2a"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-west-2a"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-west-2a"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-west-2a"
@@ -4011,22 +3995,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "us-west-2b"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-west-2b"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-west-2b"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-west-2b"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-west-2b"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-west-2b"
@@ -7327,22 +7295,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "us-west-2c"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-west-2c"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-west-2c"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-west-2c"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-west-2c"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-west-2c"
diff --git a/moto/ec2/resources/instance_type_offerings/region/ap-northeast-1.json b/moto/ec2/resources/instance_type_offerings/region/ap-northeast-1.json
index 89f205778..e7090e656 100644
--- a/moto/ec2/resources/instance_type_offerings/region/ap-northeast-1.json
+++ b/moto/ec2/resources/instance_type_offerings/region/ap-northeast-1.json
@@ -747,22 +747,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "ap-northeast-1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-northeast-1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-northeast-1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-northeast-1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "ap-northeast-1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "ap-northeast-1"
diff --git a/moto/ec2/resources/instance_type_offerings/region/ap-northeast-2.json b/moto/ec2/resources/instance_type_offerings/region/ap-northeast-2.json
index ad90647b3..33e8c9133 100644
--- a/moto/ec2/resources/instance_type_offerings/region/ap-northeast-2.json
+++ b/moto/ec2/resources/instance_type_offerings/region/ap-northeast-2.json
@@ -491,22 +491,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "ap-northeast-2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-northeast-2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-northeast-2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-northeast-2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "ap-northeast-2"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "ap-northeast-2"
diff --git a/moto/ec2/resources/instance_type_offerings/region/ap-southeast-1.json b/moto/ec2/resources/instance_type_offerings/region/ap-southeast-1.json
index 5363f5eb2..2522f3a15 100644
--- a/moto/ec2/resources/instance_type_offerings/region/ap-southeast-1.json
+++ b/moto/ec2/resources/instance_type_offerings/region/ap-southeast-1.json
@@ -695,18 +695,6 @@
   "InstanceType": "d3en.xlarge",
   "Location": "ap-southeast-1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-southeast-1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-southeast-1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-southeast-1"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "ap-southeast-1"
diff --git a/moto/ec2/resources/instance_type_offerings/region/ap-southeast-2.json b/moto/ec2/resources/instance_type_offerings/region/ap-southeast-2.json
index 69ca74343..b9976c7f9 100644
--- a/moto/ec2/resources/instance_type_offerings/region/ap-southeast-2.json
+++ b/moto/ec2/resources/instance_type_offerings/region/ap-southeast-2.json
@@ -707,22 +707,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "ap-southeast-2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ap-southeast-2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ap-southeast-2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ap-southeast-2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "ap-southeast-2"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "ap-southeast-2"
diff --git a/moto/ec2/resources/instance_type_offerings/region/ca-central-1.json b/moto/ec2/resources/instance_type_offerings/region/ca-central-1.json
index 70ebb861f..7da0d1f9d 100644
--- a/moto/ec2/resources/instance_type_offerings/region/ca-central-1.json
+++ b/moto/ec2/resources/instance_type_offerings/region/ca-central-1.json
@@ -551,18 +551,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "ca-central-1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "ca-central-1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "ca-central-1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "ca-central-1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "ca-central-1"
@@ -1407,6 +1395,10 @@
   "InstanceType": "m7i.xlarge",
   "Location": "ca-central-1"
  },
+ {
+  "InstanceType": "mac2-m2.metal",
+  "Location": "ca-central-1"
+ },
  {
   "InstanceType": "p3.16xlarge",
   "Location": "ca-central-1"
diff --git a/moto/ec2/resources/instance_type_offerings/region/eu-central-1.json b/moto/ec2/resources/instance_type_offerings/region/eu-central-1.json
index 7eb2a4358..afaf63e6f 100644
--- a/moto/ec2/resources/instance_type_offerings/region/eu-central-1.json
+++ b/moto/ec2/resources/instance_type_offerings/region/eu-central-1.json
@@ -795,22 +795,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "eu-central-1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-central-1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-central-1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-central-1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-central-1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "eu-central-1"
diff --git a/moto/ec2/resources/instance_type_offerings/region/eu-west-1.json b/moto/ec2/resources/instance_type_offerings/region/eu-west-1.json
index 65018ec7c..8d5345d00 100644
--- a/moto/ec2/resources/instance_type_offerings/region/eu-west-1.json
+++ b/moto/ec2/resources/instance_type_offerings/region/eu-west-1.json
@@ -791,22 +791,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "eu-west-1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-west-1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-west-1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-west-1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-west-1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "eu-west-1"
diff --git a/moto/ec2/resources/instance_type_offerings/region/eu-west-2.json b/moto/ec2/resources/instance_type_offerings/region/eu-west-2.json
index 70eb1b576..06e770508 100644
--- a/moto/ec2/resources/instance_type_offerings/region/eu-west-2.json
+++ b/moto/ec2/resources/instance_type_offerings/region/eu-west-2.json
@@ -559,22 +559,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "eu-west-2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "eu-west-2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "eu-west-2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "eu-west-2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "eu-west-2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "eu-west-2"
diff --git a/moto/ec2/resources/instance_type_offerings/region/us-east-1.json b/moto/ec2/resources/instance_type_offerings/region/us-east-1.json
index e0feb812d..7f4f0081a 100644
--- a/moto/ec2/resources/instance_type_offerings/region/us-east-1.json
+++ b/moto/ec2/resources/instance_type_offerings/region/us-east-1.json
@@ -843,22 +843,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "us-east-1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-east-1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-east-1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-east-1"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-east-1"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-east-1"
diff --git a/moto/ec2/resources/instance_type_offerings/region/us-east-2.json b/moto/ec2/resources/instance_type_offerings/region/us-east-2.json
index 01c802202..0914efd41 100644
--- a/moto/ec2/resources/instance_type_offerings/region/us-east-2.json
+++ b/moto/ec2/resources/instance_type_offerings/region/us-east-2.json
@@ -775,22 +775,6 @@
   "InstanceType": "d3.xlarge",
   "Location": "us-east-2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-east-2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-east-2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-east-2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-east-2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-east-2"
diff --git a/moto/ec2/resources/instance_type_offerings/region/us-west-1.json b/moto/ec2/resources/instance_type_offerings/region/us-west-1.json
index 3e37de5cf..26708309d 100644
--- a/moto/ec2/resources/instance_type_offerings/region/us-west-1.json
+++ b/moto/ec2/resources/instance_type_offerings/region/us-west-1.json
@@ -559,18 +559,6 @@
   "InstanceType": "d2.xlarge",
   "Location": "us-west-1"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-west-1"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-west-1"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-west-1"
- },
  {
   "InstanceType": "g4dn.12xlarge",
   "Location": "us-west-1"
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 c8c6e0e7a..da5aa5bb4 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
@@ -847,22 +847,6 @@
   "InstanceType": "f1.4xlarge",
   "Location": "us-west-2"
  },
- {
-  "InstanceType": "g3.16xlarge",
-  "Location": "us-west-2"
- },
- {
-  "InstanceType": "g3.4xlarge",
-  "Location": "us-west-2"
- },
- {
-  "InstanceType": "g3.8xlarge",
-  "Location": "us-west-2"
- },
- {
-  "InstanceType": "g3s.xlarge",
-  "Location": "us-west-2"
- },
  {
   "InstanceType": "g4ad.16xlarge",
   "Location": "us-west-2"
diff --git a/moto/ec2/resources/instance_types.json b/moto/ec2/resources/instance_types.json
index 0be6ff57a..e855c163f 100644
--- a/moto/ec2/resources/instance_types.json
+++ b/moto/ec2/resources/instance_types.json
@@ -14721,7 +14721,7 @@
    "NvmeSupport": "required"
   },
   "FreeTierEligible": false,
-  "HibernationSupported": false,
+  "HibernationSupported": true,
   "Hypervisor": "nitro",
   "InstanceStorageSupported": false,
   "InstanceType": "c7a.medium",
@@ -23625,464 +23625,6 @@
    ]
   }
  },
- "g3.16xlarge": {
-  "AutoRecoverySupported": true,
-  "BareMetal": false,
-  "BurstablePerformanceSupported": false,
-  "CurrentGeneration": false,
-  "DedicatedHostsSupported": true,
-  "EbsInfo": {
-   "EbsOptimizedInfo": {
-    "BaselineBandwidthInMbps": 14000,
-    "BaselineIops": 80000,
-    "BaselineThroughputInMBps": 1750.0,
-    "MaximumBandwidthInMbps": 14000,
-    "MaximumIops": 80000,
-    "MaximumThroughputInMBps": 1750.0
-   },
-   "EbsOptimizedSupport": "default",
-   "EncryptionSupport": "supported",
-   "NvmeSupport": "unsupported"
-  },
-  "FreeTierEligible": false,
-  "GpuInfo": {
-   "Gpus": [
-    {
-     "Count": 4,
-     "Manufacturer": "NVIDIA",
-     "MemoryInfo": {
-      "SizeInMiB": 8192
-     },
-     "Name": "M60"
-    }
-   ],
-   "TotalGpuMemoryInMiB": 32768
-  },
-  "HibernationSupported": false,
-  "Hypervisor": "xen",
-  "InstanceStorageSupported": false,
-  "InstanceType": "g3.16xlarge",
-  "MemoryInfo": {
-   "SizeInMiB": 499712
-  },
-  "NetworkInfo": {
-   "DefaultNetworkCardIndex": 0,
-   "EfaSupported": false,
-   "EnaSrdSupported": false,
-   "EnaSupport": "supported",
-   "EncryptionInTransitSupported": false,
-   "Ipv4AddressesPerInterface": 50,
-   "Ipv6AddressesPerInterface": 50,
-   "Ipv6Supported": true,
-   "MaximumNetworkCards": 1,
-   "MaximumNetworkInterfaces": 15,
-   "NetworkCards": [
-    {
-     "BaselineBandwidthInGbps": 5.0,
-     "MaximumNetworkInterfaces": 15,
-     "NetworkCardIndex": 0,
-     "NetworkPerformance": "25 Gigabit",
-     "PeakBandwidthInGbps": 10.0
-    }
-   ],
-   "NetworkPerformance": "25 Gigabit"
-  },
-  "NitroEnclavesSupport": "unsupported",
-  "NitroTpmSupport": "unsupported",
-  "PhcSupport": "unsupported",
-  "PlacementGroupInfo": {
-   "SupportedStrategies": [
-    "cluster",
-    "partition",
-    "spread"
-   ]
-  },
-  "ProcessorInfo": {
-   "Manufacturer": "Intel",
-   "SupportedArchitectures": [
-    "x86_64"
-   ],
-   "SustainedClockSpeedInGhz": 2.3
-  },
-  "SupportedBootModes": [
-   "legacy-bios"
-  ],
-  "SupportedRootDeviceTypes": [
-   "ebs"
-  ],
-  "SupportedUsageClasses": [
-   "on-demand",
-   "spot"
-  ],
-  "SupportedVirtualizationTypes": [
-   "hvm"
-  ],
-  "VCpuInfo": {
-   "DefaultCores": 32,
-   "DefaultThreadsPerCore": 2,
-   "DefaultVCpus": 64,
-   "ValidCores": [
-    2,
-    4,
-    6,
-    8,
-    10,
-    12,
-    14,
-    16,
-    18,
-    20,
-    22,
-    24,
-    26,
-    28,
-    30,
-    32
-   ],
-   "ValidThreadsPerCore": [
-    1,
-    2
-   ]
-  }
- },
- "g3.4xlarge": {
-  "AutoRecoverySupported": true,
-  "BareMetal": false,
-  "BurstablePerformanceSupported": false,
-  "CurrentGeneration": false,
-  "DedicatedHostsSupported": true,
-  "EbsInfo": {
-   "EbsOptimizedInfo": {
-    "BaselineBandwidthInMbps": 3500,
-    "BaselineIops": 20000,
-    "BaselineThroughputInMBps": 437.5,
-    "MaximumBandwidthInMbps": 3500,
-    "MaximumIops": 20000,
-    "MaximumThroughputInMBps": 437.5
-   },
-   "EbsOptimizedSupport": "default",
-   "EncryptionSupport": "supported",
-   "NvmeSupport": "unsupported"
-  },
-  "FreeTierEligible": false,
-  "GpuInfo": {
-   "Gpus": [
-    {
-     "Count": 1,
-     "Manufacturer": "NVIDIA",
-     "MemoryInfo": {
-      "SizeInMiB": 8192
-     },
-     "Name": "M60"
-    }
-   ],
-   "TotalGpuMemoryInMiB": 8192
-  },
-  "HibernationSupported": false,
-  "Hypervisor": "xen",
-  "InstanceStorageSupported": false,
-  "InstanceType": "g3.4xlarge",
-  "MemoryInfo": {
-   "SizeInMiB": 124928
-  },
-  "NetworkInfo": {
-   "DefaultNetworkCardIndex": 0,
-   "EfaSupported": false,
-   "EnaSrdSupported": false,
-   "EnaSupport": "supported",
-   "EncryptionInTransitSupported": false,
-   "Ipv4AddressesPerInterface": 30,
-   "Ipv6AddressesPerInterface": 30,
-   "Ipv6Supported": true,
-   "MaximumNetworkCards": 1,
-   "MaximumNetworkInterfaces": 8,
-   "NetworkCards": [
-    {
-     "BaselineBandwidthInGbps": 5.0,
-     "MaximumNetworkInterfaces": 8,
-     "NetworkCardIndex": 0,
-     "NetworkPerformance": "Up to 10 Gigabit",
-     "PeakBandwidthInGbps": 10.0
-    }
-   ],
-   "NetworkPerformance": "Up to 10 Gigabit"
-  },
-  "NitroEnclavesSupport": "unsupported",
-  "NitroTpmSupport": "unsupported",
-  "PhcSupport": "unsupported",
-  "PlacementGroupInfo": {
-   "SupportedStrategies": [
-    "cluster",
-    "partition",
-    "spread"
-   ]
-  },
-  "ProcessorInfo": {
-   "Manufacturer": "Intel",
-   "SupportedArchitectures": [
-    "x86_64"
-   ],
-   "SustainedClockSpeedInGhz": 2.7
-  },
-  "SupportedBootModes": [
-   "legacy-bios"
-  ],
-  "SupportedRootDeviceTypes": [
-   "ebs"
-  ],
-  "SupportedUsageClasses": [
-   "on-demand",
-   "spot"
-  ],
-  "SupportedVirtualizationTypes": [
-   "hvm"
-  ],
-  "VCpuInfo": {
-   "DefaultCores": 8,
-   "DefaultThreadsPerCore": 2,
-   "DefaultVCpus": 16,
-   "ValidCores": [
-    1,
-    2,
-    3,
-    4,
-    5,
-    6,
-    7,
-    8
-   ],
-   "ValidThreadsPerCore": [
-    1,
-    2
-   ]
-  }
- },
- "g3.8xlarge": {
-  "AutoRecoverySupported": true,
-  "BareMetal": false,
-  "BurstablePerformanceSupported": false,
-  "CurrentGeneration": false,
-  "DedicatedHostsSupported": true,
-  "EbsInfo": {
-   "EbsOptimizedInfo": {
-    "BaselineBandwidthInMbps": 7000,
-    "BaselineIops": 40000,
-    "BaselineThroughputInMBps": 875.0,
-    "MaximumBandwidthInMbps": 7000,
-    "MaximumIops": 40000,
-    "MaximumThroughputInMBps": 875.0
-   },
-   "EbsOptimizedSupport": "default",
-   "EncryptionSupport": "supported",
-   "NvmeSupport": "unsupported"
-  },
-  "FreeTierEligible": false,
-  "GpuInfo": {
-   "Gpus": [
-    {
-     "Count": 2,
-     "Manufacturer": "NVIDIA",
-     "MemoryInfo": {
-      "SizeInMiB": 8192
-     },
-     "Name": "M60"
-    }
-   ],
-   "TotalGpuMemoryInMiB": 16384
-  },
-  "HibernationSupported": false,
-  "Hypervisor": "xen",
-  "InstanceStorageSupported": false,
-  "InstanceType": "g3.8xlarge",
-  "MemoryInfo": {
-   "SizeInMiB": 249856
-  },
-  "NetworkInfo": {
-   "DefaultNetworkCardIndex": 0,
-   "EfaSupported": false,
-   "EnaSrdSupported": false,
-   "EnaSupport": "supported",
-   "EncryptionInTransitSupported": false,
-   "Ipv4AddressesPerInterface": 30,
-   "Ipv6AddressesPerInterface": 30,
-   "Ipv6Supported": true,
-   "MaximumNetworkCards": 1,
-   "MaximumNetworkInterfaces": 8,
-   "NetworkCards": [
-    {
-     "BaselineBandwidthInGbps": 5.0,
-     "MaximumNetworkInterfaces": 8,
-     "NetworkCardIndex": 0,
-     "NetworkPerformance": "10 Gigabit",
-     "PeakBandwidthInGbps": 10.0
-    }
-   ],
-   "NetworkPerformance": "10 Gigabit"
-  },
-  "NitroEnclavesSupport": "unsupported",
-  "NitroTpmSupport": "unsupported",
-  "PhcSupport": "unsupported",
-  "PlacementGroupInfo": {
-   "SupportedStrategies": [
-    "cluster",
-    "partition",
-    "spread"
-   ]
-  },
-  "ProcessorInfo": {
-   "Manufacturer": "Intel",
-   "SupportedArchitectures": [
-    "x86_64"
-   ],
-   "SustainedClockSpeedInGhz": 2.7
-  },
-  "SupportedBootModes": [
-   "legacy-bios"
-  ],
-  "SupportedRootDeviceTypes": [
-   "ebs"
-  ],
-  "SupportedUsageClasses": [
-   "on-demand",
-   "spot"
-  ],
-  "SupportedVirtualizationTypes": [
-   "hvm"
-  ],
-  "VCpuInfo": {
-   "DefaultCores": 16,
-   "DefaultThreadsPerCore": 2,
-   "DefaultVCpus": 32,
-   "ValidCores": [
-    1,
-    2,
-    3,
-    4,
-    5,
-    6,
-    7,
-    8,
-    9,
-    10,
-    11,
-    12,
-    13,
-    14,
-    15,
-    16
-   ],
-   "ValidThreadsPerCore": [
-    1,
-    2
-   ]
-  }
- },
- "g3s.xlarge": {
-  "AutoRecoverySupported": true,
-  "BareMetal": false,
-  "BurstablePerformanceSupported": false,
-  "CurrentGeneration": true,
-  "DedicatedHostsSupported": true,
-  "EbsInfo": {
-   "EbsOptimizedInfo": {
-    "BaselineBandwidthInMbps": 850,
-    "BaselineIops": 5000,
-    "BaselineThroughputInMBps": 106.25,
-    "MaximumBandwidthInMbps": 850,
-    "MaximumIops": 5000,
-    "MaximumThroughputInMBps": 106.25
-   },
-   "EbsOptimizedSupport": "default",
-   "EncryptionSupport": "supported",
-   "NvmeSupport": "unsupported"
-  },
-  "FreeTierEligible": false,
-  "GpuInfo": {
-   "Gpus": [
-    {
-     "Count": 1,
-     "Manufacturer": "NVIDIA",
-     "MemoryInfo": {
-      "SizeInMiB": 8192
-     },
-     "Name": "M60"
-    }
-   ],
-   "TotalGpuMemoryInMiB": 8192
-  },
-  "HibernationSupported": false,
-  "Hypervisor": "xen",
-  "InstanceStorageSupported": false,
-  "InstanceType": "g3s.xlarge",
-  "MemoryInfo": {
-   "SizeInMiB": 31232
-  },
-  "NetworkInfo": {
-   "DefaultNetworkCardIndex": 0,
-   "EfaSupported": false,
-   "EnaSrdSupported": false,
-   "EnaSupport": "required",
-   "EncryptionInTransitSupported": false,
-   "Ipv4AddressesPerInterface": 15,
-   "Ipv6AddressesPerInterface": 15,
-   "Ipv6Supported": true,
-   "MaximumNetworkCards": 1,
-   "MaximumNetworkInterfaces": 4,
-   "NetworkCards": [
-    {
-     "BaselineBandwidthInGbps": 1.25,
-     "MaximumNetworkInterfaces": 4,
-     "NetworkCardIndex": 0,
-     "NetworkPerformance": "Up to 10 Gigabit",
-     "PeakBandwidthInGbps": 10.0
-    }
-   ],
-   "NetworkPerformance": "Up to 10 Gigabit"
-  },
-  "NitroEnclavesSupport": "unsupported",
-  "NitroTpmSupport": "unsupported",
-  "PhcSupport": "unsupported",
-  "PlacementGroupInfo": {
-   "SupportedStrategies": [
-    "cluster",
-    "partition",
-    "spread"
-   ]
-  },
-  "ProcessorInfo": {
-   "Manufacturer": "Intel",
-   "SupportedArchitectures": [
-    "x86_64"
-   ],
-   "SustainedClockSpeedInGhz": 2.7
-  },
-  "SupportedBootModes": [
-   "legacy-bios"
-  ],
-  "SupportedRootDeviceTypes": [
-   "ebs"
-  ],
-  "SupportedUsageClasses": [
-   "on-demand",
-   "spot"
-  ],
-  "SupportedVirtualizationTypes": [
-   "hvm"
-  ],
-  "VCpuInfo": {
-   "DefaultCores": 2,
-   "DefaultThreadsPerCore": 2,
-   "DefaultVCpus": 4,
-   "ValidCores": [
-    1,
-    2
-   ],
-   "ValidThreadsPerCore": [
-    1,
-    2
-   ]
-  }
- },
  "g4ad.16xlarge": {
   "AutoRecoverySupported": false,
   "BareMetal": false,
diff --git a/moto/iot/exceptions.py b/moto/iot/exceptions.py
index b12c481e4..97e35cc5e 100644
--- a/moto/iot/exceptions.py
+++ b/moto/iot/exceptions.py
@@ -83,3 +83,12 @@ class ThingStillAttached(IoTClientError):
             "InvalidRequestException",
             f"Cannot delete. Thing {name} is still attached to one or more principals",
         )
+
+
+class ConflictException(IoTClientError):
+    def __init__(self, name: str):
+        self.code = 409
+        super().__init__(
+            "ConflictException",
+            f"A resource {name} already exists.",
+        )
diff --git a/moto/iot/models.py b/moto/iot/models.py
index d3efc19d6..d5d0f77c0 100644
--- a/moto/iot/models.py
+++ b/moto/iot/models.py
@@ -24,6 +24,7 @@ from moto.utilities.utils import get_partition
 
 from .exceptions import (
     CertificateStateException,
+    ConflictException,
     DeleteConflictException,
     InvalidRequestException,
     InvalidStateTransitionException,
@@ -33,7 +34,7 @@ from .exceptions import (
     VersionConflictException,
     VersionsLimitExceededException,
 )
-from .utils import PAGINATION_MODEL
+from .utils import PAGINATION_MODEL, decapitalize_dict
 
 if TYPE_CHECKING:
     from moto.iotdata.models import FakeShadow
@@ -667,6 +668,10 @@ class FakeJob(BaseModel):
         target_selection: str,
         job_executions_rollout_config: Dict[str, Any],
         document_parameters: Dict[str, str],
+        abort_config: Dict[str, List[Dict[str, Any]]],
+        job_execution_retry_config: Dict[str, Any],
+        scheduling_config: Dict[str, Any],
+        timeout_config: Dict[str, Any],
         account_id: str,
         region_name: str,
     ):
@@ -685,6 +690,10 @@ class FakeJob(BaseModel):
         self.presigned_url_config = presigned_url_config
         self.target_selection = target_selection
         self.job_executions_rollout_config = job_executions_rollout_config
+        self.abort_config = abort_config
+        self.job_execution_retry_config = job_execution_retry_config
+        self.scheduling_config = scheduling_config
+        self.timeout_config = timeout_config
         self.status = "QUEUED"  # IN_PROGRESS | CANCELED | COMPLETED
         self.comment: Optional[str] = None
         self.reason_code: Optional[str] = None
@@ -711,7 +720,7 @@ class FakeJob(BaseModel):
             "description": self.description,
             "presignedUrlConfig": self.presigned_url_config,
             "targetSelection": self.target_selection,
-            "jobExecutionsRolloutConfig": self.job_executions_rollout_config,
+            "timeoutConfig": self.timeout_config,
             "status": self.status,
             "comment": self.comment,
             "forceCanceled": self.force,
@@ -783,6 +792,139 @@ class FakeJobExecution(BaseModel):
         }
 
 
+class FakeJobTemplate(CloudFormationModel):
+    JOB_TEMPLATE_ID_REGEX_PATTERN = "[a-zA-Z0-9_-]+"
+    JOB_TEMPLATE_ID_REGEX = re.compile(JOB_TEMPLATE_ID_REGEX_PATTERN)
+
+    def __init__(
+        self,
+        job_template_id: str,
+        document_source: str,
+        document: str,
+        description: str,
+        presigned_url_config: Dict[str, Any],
+        job_executions_rollout_config: Dict[str, Any],
+        abort_config: Dict[str, List[Dict[str, Any]]],
+        job_execution_retry_config: Dict[str, Any],
+        timeout_config: Dict[str, Any],
+        account_id: str,
+        region_name: str,
+    ):
+        if not self._job_template_id_matcher(job_template_id):
+            raise InvalidRequestException()
+
+        self.account_id = account_id
+        self.region_name = region_name
+        self.job_template_id = job_template_id
+        self.job_template_arn = f"arn:{get_partition(self.region_name)}:iot:{self.region_name}:{self.account_id}:jobtemplate/{job_template_id}"
+        self.document_source = document_source
+        self.document = document
+        self.description = description
+        self.presigned_url_config = presigned_url_config
+        self.job_executions_rollout_config = job_executions_rollout_config
+        self.abort_config = abort_config
+        self.job_execution_retry_config = job_execution_retry_config
+        self.timeout_config = timeout_config
+        self.created_at = time.mktime(datetime(2015, 1, 1).timetuple())
+
+    def to_dict(self) -> Dict[str, Any]:
+        return {
+            "jobTemplateArn": self.job_template_arn,
+            "jobTemplateId": self.job_template_id,
+            "description": self.description,
+            "createdAt": self.created_at,
+        }
+
+    def _job_template_id_matcher(self, argument: str) -> bool:
+        return (
+            self.JOB_TEMPLATE_ID_REGEX.fullmatch(argument) is not None
+            and len(argument) <= 64
+        )
+
+    @staticmethod
+    def cloudformation_name_type() -> str:
+        return "JobTemplate"
+
+    @staticmethod
+    def cloudformation_type() -> str:
+        return "AWS::IoT::JobTemplate"
+
+    @classmethod
+    def has_cfn_attr(cls, attr: str) -> bool:
+        return attr in [
+            "Arn",
+        ]
+
+    def get_cfn_attribute(self, attribute_name: str) -> Any:
+        from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
+
+        if attribute_name == "Arn":
+            return self.job_template_arn
+        raise UnformattedGetAttTemplateException()
+
+    @classmethod
+    def create_from_cloudformation_json(  # type: ignore[misc]
+        cls,
+        resource_name: str,
+        cloudformation_json: Any,
+        account_id: str,
+        region_name: str,
+        **kwargs: Any,
+    ) -> "FakeJobTemplate":
+        iot_backend = iot_backends[account_id][region_name]
+        properties = cloudformation_json["Properties"]
+
+        return iot_backend.create_job_template(
+            job_template_id=properties.get("JobTemplateId", resource_name),
+            document_source=properties.get("DocumentSource", ""),
+            document=properties.get("Document"),
+            description=properties.get("Description"),
+            presigned_url_config=decapitalize_dict(
+                properties.get("PresignedUrlConfig", {})
+            ),
+            job_executions_rollout_config=decapitalize_dict(
+                properties.get("JobExecutionsRolloutConfig", {})
+            ),
+            abort_config=decapitalize_dict(properties.get("AbortConfig", {})),
+            job_execution_retry_config=decapitalize_dict(
+                properties.get("JobExecutionsRetryConfig", {})
+            ),
+            timeout_config=decapitalize_dict(properties.get("TimeoutConfig", {})),
+        )
+
+    @classmethod
+    def update_from_cloudformation_json(  # type: ignore[misc]
+        cls,
+        original_resource: "FakeJobTemplate",
+        new_resource_name: str,
+        cloudformation_json: Any,
+        account_id: str,
+        region_name: str,
+    ) -> "FakeJobTemplate":
+        iot_backend = iot_backends[account_id][region_name]
+        iot_backend.delete_job_template(
+            job_template_id=original_resource.job_template_id
+        )
+
+        return cls.create_from_cloudformation_json(
+            new_resource_name, cloudformation_json, account_id, region_name
+        )
+
+    @classmethod
+    def delete_from_cloudformation_json(  # type: ignore[misc]
+        cls,
+        resource_name: str,
+        cloudformation_json: Any,
+        account_id: str,
+        region_name: str,
+    ) -> None:
+        properties = cloudformation_json["Properties"]
+        job_template_id = properties.get("JobTemplateId", resource_name)
+
+        iot_backend = iot_backends[account_id][region_name]
+        iot_backend.delete_job_template(job_template_id=job_template_id)
+
+
 class FakeEndpoint(BaseModel):
     def __init__(self, endpoint_type: str, region_name: str):
         if endpoint_type not in [
@@ -1110,6 +1252,7 @@ class IoTBackend(BaseBackend):
         super().__init__(region_name, account_id)
         self.things: Dict[str, FakeThing] = OrderedDict()
         self.jobs: Dict[str, FakeJob] = OrderedDict()
+        self.jobs_templates: Dict[str, FakeJobTemplate] = OrderedDict()
         self.job_executions: Dict[Tuple[str, str], FakeJobExecution] = OrderedDict()
         self.thing_types: Dict[str, FakeThingType] = OrderedDict()
         self.thing_groups: Dict[str, FakeThingGroup] = OrderedDict()
@@ -2092,19 +2235,27 @@ class IoTBackend(BaseBackend):
         target_selection: str,
         job_executions_rollout_config: Dict[str, Any],
         document_parameters: Dict[str, str],
+        abort_config: Dict[str, List[Dict[str, Any]]],
+        job_execution_retry_config: Dict[str, Any],
+        scheduling_config: Dict[str, Any],
+        timeout_config: Dict[str, Any],
     ) -> Tuple[str, str, str]:
         job = FakeJob(
-            job_id,
-            targets,
-            document_source,
-            document,
-            description,
-            presigned_url_config,
-            target_selection,
-            job_executions_rollout_config,
-            document_parameters,
-            self.account_id,
-            self.region_name,
+            job_id=job_id,
+            targets=targets,
+            document_source=document_source,
+            document=document,
+            description=description,
+            presigned_url_config=presigned_url_config,
+            target_selection=target_selection,
+            job_executions_rollout_config=job_executions_rollout_config,
+            abort_config=abort_config,
+            job_execution_retry_config=job_execution_retry_config,
+            scheduling_config=scheduling_config,
+            timeout_config=timeout_config,
+            document_parameters=document_parameters,
+            account_id=self.account_id,
+            region_name=self.region_name,
         )
         self.jobs[job_id] = job
 
@@ -2152,28 +2303,12 @@ class IoTBackend(BaseBackend):
     def get_job_document(self, job_id: str) -> FakeJob:
         return self.jobs[job_id]
 
-    def list_jobs(
-        self, max_results: int, token: Optional[str]
-    ) -> Tuple[List[Dict[str, Any]], Optional[str]]:
+    @paginate(PAGINATION_MODEL)  # type: ignore[misc]
+    def list_jobs(self) -> List[Dict[str, Any]]:
         """
         The following parameter are not yet implemented: Status, TargetSelection, ThingGroupName, ThingGroupId
         """
-        all_jobs = [_.to_dict() for _ in self.jobs.values()]
-        filtered_jobs = all_jobs
-
-        if token is None:
-            jobs = filtered_jobs[0:max_results]
-            next_token = str(max_results) if len(filtered_jobs) > max_results else None
-        else:
-            int_token = int(token)
-            jobs = filtered_jobs[int_token : int_token + max_results]
-            next_token = (
-                str(int_token + max_results)
-                if len(filtered_jobs) > int_token + max_results
-                else None
-            )
-
-        return jobs, next_token
+        return [_.to_dict() for _ in self.jobs.values()]
 
     def describe_job_execution(
         self, job_id: str, thing_name: str, execution_number: int
@@ -2475,5 +2610,51 @@ class IoTBackend(BaseBackend):
             thingIndexingConfiguration, thingGroupIndexingConfiguration
         )
 
+    def create_job_template(
+        self,
+        job_template_id: str,
+        document_source: str,
+        document: str,
+        description: str,
+        presigned_url_config: Dict[str, Any],
+        job_executions_rollout_config: Dict[str, Any],
+        abort_config: Dict[str, List[Dict[str, Any]]],
+        job_execution_retry_config: Dict[str, Any],
+        timeout_config: Dict[str, Any],
+    ) -> "FakeJobTemplate":
+        if job_template_id in self.jobs_templates:
+            raise ConflictException(job_template_id)
+
+        job_template = FakeJobTemplate(
+            job_template_id=job_template_id,
+            document_source=document_source,
+            document=document,
+            description=description,
+            presigned_url_config=presigned_url_config,
+            job_executions_rollout_config=job_executions_rollout_config,
+            abort_config=abort_config,
+            job_execution_retry_config=job_execution_retry_config,
+            timeout_config=timeout_config,
+            account_id=self.account_id,
+            region_name=self.region_name,
+        )
+
+        self.jobs_templates[job_template_id] = job_template
+        return job_template
+
+    @paginate(PAGINATION_MODEL)  # type: ignore[misc]
+    def list_job_templates(self) -> List[Dict[str, Any]]:
+        return [_.to_dict() for _ in self.jobs_templates.values()]
+
+    def delete_job_template(self, job_template_id: str) -> None:
+        if job_template_id not in self.jobs_templates:
+            raise ResourceNotFoundException(f"Job template {job_template_id} not found")
+        del self.jobs_templates[job_template_id]
+
+    def describe_job_template(self, job_template_id: str) -> FakeJobTemplate:
+        if job_template_id not in self.jobs_templates:
+            raise ResourceNotFoundException(f"Job template {job_template_id} not found")
+        return self.jobs_templates[job_template_id]
+
 
 iot_backends = BackendDict(IoTBackend, "iot")
diff --git a/moto/iot/responses.py b/moto/iot/responses.py
index 55842b818..69885e2ca 100644
--- a/moto/iot/responses.py
+++ b/moto/iot/responses.py
@@ -155,6 +155,10 @@ class IoTResponse(BaseResponse):
             target_selection=self._get_param("targetSelection"),
             job_executions_rollout_config=self._get_param("jobExecutionsRolloutConfig"),
             document_parameters=self._get_param("documentParameters"),
+            abort_config=self._get_param("abortConfig"),
+            job_execution_retry_config=self._get_param("jobExecutionsRetryConfig"),
+            scheduling_config=self._get_param("schedulingConfig"),
+            timeout_config=self._get_param("timeoutConfig"),
         )
 
         return json.dumps(dict(jobArn=job_arn, jobId=job_id, description=description))
@@ -174,6 +178,10 @@ class IoTResponse(BaseResponse):
                     reasonCode=job.reason_code,
                     jobArn=job.job_arn,
                     jobExecutionsRolloutConfig=job.job_executions_rollout_config,
+                    jobExecutionsRetryConfig=job.job_execution_retry_config,
+                    schedulingConfig=job.scheduling_config,
+                    timeoutConfig=job.timeout_config,
+                    abortConfig=job.abort_config,
                     jobId=job.job_id,
                     jobProcessDetails=job.job_process_details,
                     lastUpdatedAt=job.last_updated_at,
@@ -220,7 +228,7 @@ class IoTResponse(BaseResponse):
         max_results = self._get_int_param("maxResults", 50)
         previous_next_token = self._get_param("nextToken")
         jobs, next_token = self.iot_backend.list_jobs(
-            max_results=max_results, token=previous_next_token
+            max_results=max_results, next_token=previous_next_token
         )
 
         return json.dumps(dict(jobs=jobs, nextToken=next_token))
@@ -836,3 +844,59 @@ class IoTResponse(BaseResponse):
             self._get_param("thingGroupIndexingConfiguration", {}),
         )
         return json.dumps({})
+
+    def create_job_template(self) -> str:
+        job_template = self.iot_backend.create_job_template(
+            job_template_id=self._get_param("jobTemplateId"),
+            description=self._get_param("description"),
+            document_source=self._get_param("documentSource"),
+            document=self._get_param("document"),
+            presigned_url_config=self._get_param("presignedUrlConfig"),
+            job_executions_rollout_config=self._get_param("jobExecutionsRolloutConfig"),
+            abort_config=self._get_param("abortConfig"),
+            job_execution_retry_config=self._get_param("jobExecutionsRetryConfig"),
+            timeout_config=self._get_param("timeoutConfig"),
+        )
+
+        return json.dumps(
+            dict(
+                jobTemplateArn=job_template.job_template_arn,
+                jobTemplateId=job_template.job_template_id,
+            )
+        )
+
+    def list_job_templates(self) -> str:
+        max_results = self._get_int_param("maxResults", 50)
+        current_next_token = self._get_param("nextToken")
+        job_templates, future_next_token = self.iot_backend.list_job_templates(
+            max_results=max_results, next_token=current_next_token
+        )
+
+        return json.dumps(dict(jobTemplates=job_templates, nextToken=future_next_token))
+
+    def delete_job_template(self) -> str:
+        job_template_id = self._get_param("jobTemplateId")
+
+        self.iot_backend.delete_job_template(job_template_id=job_template_id)
+
+        return json.dumps(dict())
+
+    def describe_job_template(self) -> str:
+        job_template_id = self._get_param("jobTemplateId")
+        job_template = self.iot_backend.describe_job_template(job_template_id)
+
+        return json.dumps(
+            {
+                "jobTemplateArn": job_template.job_template_arn,
+                "jobTemplateId": job_template.job_template_id,
+                "description": job_template.description,
+                "documentSource": job_template.document_source,
+                "document": job_template.document,
+                "createdAt": job_template.created_at,
+                "presignedUrlConfig": job_template.presigned_url_config,
+                "jobExecutionsRolloutConfig": job_template.job_executions_rollout_config,
+                "abortConfig": job_template.abort_config,
+                "timeoutConfig": job_template.timeout_config,
+                "jobExecutionsRetryConfig": job_template.job_execution_retry_config,
+            }
+        )
diff --git a/moto/iot/utils.py b/moto/iot/utils.py
index 1a08f56b0..fb71f639a 100644
--- a/moto/iot/utils.py
+++ b/moto/iot/utils.py
@@ -1,8 +1,36 @@
+from typing import Any
+
 PAGINATION_MODEL = {
     "list_job_executions_for_thing": {
         "input_token": "next_token",
         "limit_key": "max_results",
         "limit_default": 100,
         "unique_attribute": "jobId",
-    }
+    },
+    "list_job_templates": {
+        "input_token": "next_token",
+        "limit_key": "max_results",
+        "limit_default": 100,
+        "unique_attribute": "jobTemplateId",
+    },
+    "list_jobs": {
+        "input_token": "next_token",
+        "limit_key": "max_results",
+        "limit_default": 100,
+        "unique_attribute": "jobId",
+    },
 }
+
+
+def decapitalize_str(obj: str) -> str:
+    return obj[0].lower() + obj[1:]
+
+
+def decapitalize_dict(obj: Any) -> Any:
+    if isinstance(obj, dict):
+        return {
+            decapitalize_str(key): decapitalize_dict(value)
+            for key, value in obj.items()
+        }
+    else:
+        return obj


Test patch:
diff --git a/tests/test_iot/test_iot_cloudformation.py b/tests/test_iot/test_iot_cloudformation.py
index 27199d2cb..8eb60fe46 100644
--- a/tests/test_iot/test_iot_cloudformation.py
+++ b/tests/test_iot/test_iot_cloudformation.py
@@ -1,6 +1,8 @@
 import json
+from datetime import datetime
 
 import boto3
+from dateutil.tz import tzlocal
 
 from moto import mock_aws
 
@@ -685,3 +687,169 @@ def test_delete_role_alias_with_cloudformation():
     # then check stack
     cfn_conn.delete_stack(StackName=stack_name)
     assert iot_conn.list_role_aliases()["roleAliases"] == []
+
+
+@mock_aws
+def test_create_job_template_with_simple_cloudformation():
+    # given
+    stack_name = "test_stack"
+    job_document = {"field": "value"}
+
+    template = {
+        "AWSTemplateFormatVersion": "2010-09-09",
+        "Description": "IOT JobTemplate CloudFormation",
+        "Resources": {
+            "testJobTemplate": {
+                "Type": "AWS::IoT::JobTemplate",
+                "Properties": {
+                    "JobTemplateId": "JobTemplate",
+                    "Description": "Job template Description",
+                    "Document": json.dumps(job_document),
+                    "DocumentSource": "a document source link",
+                    "PresignedUrlConfig": {
+                        "ExpiresInSec": 123,
+                        "RoleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
+                    },
+                    "TimeoutConfig": {"InProgressTimeoutInMinutes": 30},
+                },
+            },
+        },
+        "Outputs": {
+            "JobTemplateArn": {"Value": {"Fn::GetAtt": ["testJobTemplate", "Arn"]}},
+        },
+    }
+
+    # when
+    cfn_conn = boto3.client("cloudformation", region_name=TEST_REGION)
+    cfn_conn.create_stack(StackName=stack_name, TemplateBody=json.dumps(template))
+
+    # then check list of things
+    iot_conn = boto3.client("iot", region_name=TEST_REGION)
+    assert len(iot_conn.list_job_templates()["jobTemplates"]) == 1
+    assert (
+        iot_conn.list_job_templates()["jobTemplates"][0]["jobTemplateId"]
+        == "JobTemplate"
+    )
+
+    # then check stack
+    stack = cfn_conn.describe_stacks(StackName=stack_name)["Stacks"][0]
+    outputs = {
+        Output["OutputKey"]: Output["OutputValue"] for Output in stack["Outputs"]
+    }
+    assert (
+        outputs["JobTemplateArn"]
+        == "arn:aws:iot:us-west-1:123456789012:jobtemplate/JobTemplate"
+    )
+
+    # and describe it
+    job_template = iot_conn.describe_job_template(jobTemplateId="JobTemplate")
+    assert job_template["jobTemplateId"] == "JobTemplate"
+    assert (
+        job_template["jobTemplateArn"]
+        == "arn:aws:iot:us-west-1:123456789012:jobtemplate/JobTemplate"
+    )
+    assert job_template["description"] == "Job template Description"
+    assert job_template["document"] == '{"field": "value"}'
+    assert job_template["documentSource"] == "a document source link"
+    assert job_template["createdAt"] == datetime(2015, 1, 1, 0, 0, tzinfo=tzlocal())
+    assert job_template["presignedUrlConfig"] == {
+        "roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
+        "expiresInSec": 123,
+    }
+    assert job_template["timeoutConfig"] == {
+        "inProgressTimeoutInMinutes": 30,
+    }
+
+
+@mock_aws
+def test_update_job_template_with_simple_cloudformation():
+    # given
+    stack_name = "test_stack"
+
+    initial_template = {
+        "AWSTemplateFormatVersion": "2010-09-09",
+        "Description": "IOT JobTemplate CloudFormation",
+        "Resources": {
+            "testJobTemplate": {
+                "Type": "AWS::IoT::JobTemplate",
+                "Properties": {
+                    "JobTemplateId": "JobTemplate",
+                    "Description": "Job template Description",
+                    "Document": json.dumps({"field1": "value1"}),
+                },
+            },
+        },
+    }
+    updated_template = {
+        "AWSTemplateFormatVersion": "2010-09-09",
+        "Description": "IOT JobTemplate CloudFormation",
+        "Resources": {
+            "testJobTemplate": {
+                "Type": "AWS::IoT::JobTemplate",
+                "Properties": {
+                    "JobTemplateId": "JobTemplate2",
+                    "Description": "Job template Description",
+                    "Document": json.dumps({"field2": "value2"}),
+                },
+            },
+        },
+    }
+
+    # when
+    cfn_conn = boto3.client("cloudformation", region_name=TEST_REGION)
+    cfn_conn.create_stack(
+        StackName=stack_name, TemplateBody=json.dumps(initial_template)
+    )
+
+    # then check list of things
+    iot_conn = boto3.client("iot", region_name=TEST_REGION)
+    assert len(iot_conn.list_job_templates()["jobTemplates"]) == 1
+    assert (
+        iot_conn.list_job_templates()["jobTemplates"][0]["jobTemplateId"]
+        == "JobTemplate"
+    )
+
+    # then update stack
+    cfn_conn.update_stack(
+        StackName=stack_name, TemplateBody=json.dumps(updated_template)
+    )
+    assert len(iot_conn.list_job_templates()["jobTemplates"]) == 1
+    assert (
+        iot_conn.list_job_templates()["jobTemplates"][0]["jobTemplateId"]
+        == "JobTemplate2"
+    )
+
+
+@mock_aws
+def test_delete_job_template_with_simple_cloudformation():
+    # given
+    stack_name = "test_stack"
+
+    template = {
+        "AWSTemplateFormatVersion": "2010-09-09",
+        "Description": "IOT JobTemplate CloudFormation",
+        "Resources": {
+            "testJobTemplate": {
+                "Type": "AWS::IoT::JobTemplate",
+                "Properties": {
+                    "JobTemplateId": "JobTemplate",
+                    "Description": "Job template Description",
+                    "Document": json.dumps({"field": "value"}),
+                },
+            },
+        },
+    }
+
+    # when
+    cfn_conn = boto3.client("cloudformation", region_name=TEST_REGION)
+    cfn_conn.create_stack(StackName=stack_name, TemplateBody=json.dumps(template))
+
+    # then check list of things
+    iot_conn = boto3.client("iot", region_name=TEST_REGION)
+    assert len(iot_conn.list_job_templates()["jobTemplates"]) == 1
+
+    # then check stack
+    cfn_conn.delete_stack(StackName=stack_name)
+
+    # and
+    assert len(iot_conn.list_job_templates()["jobTemplates"]) == 0
diff --git a/tests/test_iot/test_iot_job_templates.py b/tests/test_iot/test_iot_job_templates.py
new file mode 100644
index 000000000..d94bbc3aa
--- /dev/null
+++ b/tests/test_iot/test_iot_job_templates.py
@@ -0,0 +1,213 @@
+import json
+
+import boto3
+import pytest
+
+from moto import mock_aws
+
+
+@mock_aws
+def test_create_job_template():
+    client = boto3.client("iot", region_name="eu-west-1")
+    job_template_id = "TestJobTemplate"
+
+    job_document = {"field": "value"}
+
+    job_template = client.create_job_template(
+        jobTemplateId=job_template_id,
+        document=json.dumps(job_document),
+        description="Description",
+        presignedUrlConfig={
+            "roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
+            "expiresInSec": 123,
+        },
+        jobExecutionsRolloutConfig={"maximumPerMinute": 10},
+        jobExecutionsRetryConfig={
+            "criteriaList": [{"failureType": "ALL", "numberOfRetries": 10}]
+        },
+        abortConfig={
+            "criteriaList": [
+                {
+                    "action": "CANCEL",
+                    "failureType": "ALL",
+                    "minNumberOfExecutedThings": 1,
+                    "thresholdPercentage": 90,
+                }
+            ]
+        },
+    )
+
+    assert job_template["jobTemplateId"] == job_template_id
+    assert (
+        job_template["jobTemplateArn"]
+        == "arn:aws:iot:eu-west-1:123456789012:jobtemplate/TestJobTemplate"
+    )
+
+
+@mock_aws
+def test_create_job_template_with_invalid_id():
+    client = boto3.client("iot", region_name="eu-west-1")
+    job_template_id = "TestJobTemplate!@#4"
+
+    with pytest.raises(client.exceptions.InvalidRequestException):
+        client.create_job_template(
+            jobTemplateId=job_template_id,
+            document=json.dumps({"field": "value"}),
+            description="Description",
+        )
+
+
+@mock_aws
+def test_create_job_template_with_the_same_id_twice():
+    client = boto3.client("iot", region_name="eu-west-1")
+    job_template_id = "TestJobTemplate"
+
+    client.create_job_template(
+        jobTemplateId=job_template_id,
+        document=json.dumps({"field": "value"}),
+        description="Description",
+    )
+
+    with pytest.raises(client.exceptions.ConflictException):
+        client.create_job_template(
+            jobTemplateId=job_template_id,
+            document=json.dumps({"field": "value"}),
+            description="Description",
+        )
+
+
+@mock_aws
+def test_describe_job_template():
+    client = boto3.client("iot", region_name="eu-west-1")
+    job_template_id = "TestJobTemplate"
+
+    job_document = {"field": "value"}
+
+    client.create_job_template(
+        jobTemplateId=job_template_id,
+        document=json.dumps(job_document),
+        description="Description",
+        presignedUrlConfig={
+            "roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
+            "expiresInSec": 123,
+        },
+        jobExecutionsRolloutConfig={"maximumPerMinute": 10},
+        jobExecutionsRetryConfig={
+            "criteriaList": [{"failureType": "ALL", "numberOfRetries": 10}]
+        },
+        abortConfig={
+            "criteriaList": [
+                {
+                    "action": "CANCEL",
+                    "failureType": "ALL",
+                    "minNumberOfExecutedThings": 1,
+                    "thresholdPercentage": 90,
+                }
+            ]
+        },
+    )
+
+    job_template = client.describe_job_template(jobTemplateId=job_template_id)
+
+    assert job_template["jobTemplateId"] == job_template_id
+    assert (
+        job_template["jobTemplateArn"]
+        == "arn:aws:iot:eu-west-1:123456789012:jobtemplate/TestJobTemplate"
+    )
+    assert job_template["description"] == "Description"
+    assert job_template["presignedUrlConfig"] == {
+        "roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
+        "expiresInSec": 123,
+    }
+    assert job_template["jobExecutionsRolloutConfig"] == {"maximumPerMinute": 10}
+    assert job_template["jobExecutionsRetryConfig"]["criteriaList"] == [
+        {"failureType": "ALL", "numberOfRetries": 10}
+    ]
+
+
+@mock_aws
+def test_describe_nonexistent_job_template():
+    client = boto3.client("iot", region_name="eu-west-1")
+    with pytest.raises(client.exceptions.ResourceNotFoundException):
+        client.describe_job_template(jobTemplateId="nonexistent")
+
+
+@mock_aws
+def test_delete_nonexistent_job_template():
+    client = boto3.client("iot", region_name="eu-west-1")
+    with pytest.raises(client.exceptions.ResourceNotFoundException):
+        client.delete_job_template(jobTemplateId="nonexistent")
+
+
+@mock_aws
+def test_list_job_templates():
+    client = boto3.client("iot", region_name="eu-west-1")
+    job_document = {"field": "value"}
+    job_template_ids = ["TestJobTemplate1", "AnotherJobTemplate"]
+
+    for template_id in job_template_ids:
+        job_template = client.create_job_template(
+            jobTemplateId=template_id,
+            document=json.dumps(job_document),
+            description="Description",
+        )
+
+        assert job_template["jobTemplateId"] == template_id
+
+    list_result = client.list_job_templates(maxResults=100)
+    assert "nextToken" not in list_result
+    assert len(list_result["jobTemplates"]) == 2
+
+
+@mock_aws
+def test_list_job_templates_wht_pagination():
+    client = boto3.client("iot", region_name="eu-west-1")
+    job_document = {"field": "value"}
+    job_template_ids = [
+        "TestJobTemplate1",
+        "AnotherJobTemplate",
+        "YetAnotherJob",
+        "LasttestJob",
+    ]
+
+    for template_id in job_template_ids:
+        job_template = client.create_job_template(
+            jobTemplateId=template_id,
+            document=json.dumps(job_document),
+            description="Description",
+        )
+
+        assert job_template["jobTemplateId"] == template_id
+
+    first_list_result = client.list_job_templates(maxResults=2)
+    assert "nextToken" in first_list_result
+    assert len(first_list_result["jobTemplates"]) == 2
+
+    second_list_result = client.list_job_templates(
+        maxResults=2, nextToken=first_list_result["nextToken"]
+    )
+    assert "nextToken" not in second_list_result
+    assert len(second_list_result["jobTemplates"]) == 2
+
+
+@mock_aws
+def test_delete_job_template():
+    # given
+    client = boto3.client("iot", region_name="eu-west-1")
+    job_template_id = "TestJobTemplate"
+    client.create_job_template(
+        jobTemplateId=job_template_id,
+        document=json.dumps({"field": "value"}),
+        description="Description",
+    )
+    list_result = client.list_job_templates(maxResults=100)
+    assert len(list_result["jobTemplates"]) == 1
+
+    # when
+    client.delete_job_template(
+        jobTemplateId=job_template_id,
+    )
+
+    # then
+    list_result = client.list_job_templates(maxResults=100)
+    assert len(list_result["jobTemplates"]) == 0
diff --git a/tests/test_iot/test_iot_jobs.py b/tests/test_iot/test_iot_jobs.py
index 4a4a2be16..d48347779 100644
--- a/tests/test_iot/test_iot_jobs.py
+++ b/tests/test_iot/test_iot_jobs.py
@@ -32,6 +32,19 @@ def test_create_job():
         },
         targetSelection="CONTINUOUS",
         jobExecutionsRolloutConfig={"maximumPerMinute": 10},
+        jobExecutionsRetryConfig={
+            "criteriaList": [{"failureType": "ALL", "numberOfRetries": 10}]
+        },
+        abortConfig={
+            "criteriaList": [
+                {
+                    "action": "CANCEL",
+                    "failureType": "ALL",
+                    "minNumberOfExecutedThings": 1,
+                    "thresholdPercentage": 90,
+                }
+            ]
+        },
     )
 
     assert job["jobId"] == job_id
@@ -116,6 +129,21 @@ def test_describe_job():
         },
         targetSelection="CONTINUOUS",
         jobExecutionsRolloutConfig={"maximumPerMinute": 10},
+        jobExecutionsRetryConfig={
+            "criteriaList": [{"failureType": "ALL", "numberOfRetries": 10}]
+        },
+        abortConfig={
+            "criteriaList": [
+                {
+                    "action": "CANCEL",
+                    "failureType": "ALL",
+                    "minNumberOfExecutedThings": 1,
+                    "thresholdPercentage": 90,
+                }
+            ]
+        },
+        schedulingConfig={"endBehavior": "FORCE_CANCEL"},
+        timeoutConfig={"inProgressTimeoutInMinutes": 100},
     )
 
     assert job["jobId"] == job_id
@@ -140,6 +168,19 @@ def test_describe_job():
     )
     assert job["presignedUrlConfig"]["expiresInSec"] == 123
     assert job["jobExecutionsRolloutConfig"]["maximumPerMinute"] == 10
+    assert job["jobExecutionsRetryConfig"] == {
+        "criteriaList": [{"failureType": "ALL", "numberOfRetries": 10}]
+    }
+    assert job["schedulingConfig"] == {"endBehavior": "FORCE_CANCEL"}
+    assert job["timeoutConfig"] == {"inProgressTimeoutInMinutes": 100}
+    assert job["abortConfig"]["criteriaList"] == [
+        {
+            "action": "CANCEL",
+            "failureType": "ALL",
+            "minNumberOfExecutedThings": 1,
+            "thresholdPercentage": 90,
+        }
+    ]
 
 
 @mock_aws