* [PATCH v4 2/8] terraform/aws: Add scripts to gather provider resource information
2025-09-17 0:34 [PATCH v4 0/8] aws: add dynamic kconfig support Luis Chamberlain
2025-09-17 0:34 ` [PATCH v4 1/8] aws: prevent SSH key conflicts across multiple kdevops directories Luis Chamberlain
@ 2025-09-17 0:34 ` Luis Chamberlain
2025-09-17 0:34 ` [PATCH v4 3/8] aws: add optimized Kconfig generator using Chuck's scripts Luis Chamberlain
` (5 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Luis Chamberlain @ 2025-09-17 0:34 UTC (permalink / raw)
To: Chuck Lever, Daniel Gomez, kdevops; +Cc: Chuck Lever, Luis Chamberlain
From: Chuck Lever <chuck.lever@oracle.com>
Luis suggested I try my hand... so here goes.
I prompted Claude for a few ideas about how to grab information
about AMIs, instance types, and regions/AVs. The script output is
either JSON, a human-readable table, or CSV. Additional scripts
(not provided here) would then capture this output and convert it
to Kconfig menus.
This is not at all complete. Just another way to approach these
tasks, for comparison. I learned why the region information is
needed for querying instance types, and that it looks like we
won't get clear and reliable pricing information from AWS, for
various reasons.
I would say that this code works and has a pleasant UX but is
still more complex than we might want to carry in kdevops in the
long run. I'm interested in seeing some human or AI effort to
simplifying these scripts further.
And note that the instance type information is always based on
what's available in the queried region and what the credentialed
user has permission to see. Therefore:
- out of the shrink-wrap, kdevops might provide some sensible
generic default menu selections
- a power user might need to run this before selecting the cloud
resources they want to use
So it better be damn simple and damn reliable. :-) And we probably
need to be very careful before changing the in-tree menus that
are committed to the kdevops repo... They might need to continue
to be hand-rolled. Or we just have some fixed JSON source that
generates the sensible default menus.
Posting this for thoughts and opinions.
Generated-by: Claude Sonnet 4
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
terraform/aws/scripts/aws_ami_info.py | 771 +++++++++++++++++++++
terraform/aws/scripts/aws_regions_info.py | 371 ++++++++++
terraform/aws/scripts/ec2_instance_info.py | 540 +++++++++++++++
3 files changed, 1682 insertions(+)
create mode 100755 terraform/aws/scripts/aws_ami_info.py
create mode 100755 terraform/aws/scripts/aws_regions_info.py
create mode 100755 terraform/aws/scripts/ec2_instance_info.py
diff --git a/terraform/aws/scripts/aws_ami_info.py b/terraform/aws/scripts/aws_ami_info.py
new file mode 100755
index 00000000..d9ea8bea
--- /dev/null
+++ b/terraform/aws/scripts/aws_ami_info.py
@@ -0,0 +1,771 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: MIT
+
+import boto3
+import json
+import sys
+import argparse
+import os
+import re
+from collections import defaultdict
+from configparser import ConfigParser
+from botocore.exceptions import ClientError, NoCredentialsError
+
+
+def get_aws_default_region():
+ """
+ Get the default AWS region from ~/.aws/config file.
+
+ Returns:
+ str: Default region or 'us-east-1' if not found
+ """
+ config_path = os.path.expanduser("~/.aws/config")
+
+ if os.path.exists(config_path):
+ try:
+ config = ConfigParser()
+ config.read(config_path)
+
+ # Check for default profile region
+ if "default" in config:
+ return config["default"].get("region", "us-east-1")
+
+ # Check for profile default section
+ if "profile default" in config:
+ return config["profile default"].get("region", "us-east-1")
+
+ except Exception as e:
+ print(f"Warning: Error reading AWS config file: {e}", file=sys.stderr)
+
+ return "us-east-1"
+
+
+def get_known_ami_owners():
+ """
+ Get dictionary of well-known AMI owners that provide Linux images.
+
+ Returns:
+ dict: Dictionary of owner information
+ """
+ return {
+ "amazon": {
+ "owner_id": "137112412989",
+ "owner_name": "Amazon",
+ "description": "Amazon Linux AMIs",
+ "search_patterns": [
+ r"al2023-ami-.*", # Amazon Linux 2023
+ r"amzn2-ami-.*", # Amazon Linux 2
+ r"amzn-ami-.*", # Amazon Linux 1
+ ],
+ },
+ "ubuntu": {
+ "owner_id": "099720109477",
+ "owner_name": "Canonical",
+ "description": "Ubuntu AMIs",
+ "search_patterns": [
+ r"ubuntu/images/.*ubuntu-.*", # All Ubuntu images
+ ],
+ },
+ "redhat": {
+ "owner_id": "309956199498",
+ "owner_name": "Red Hat",
+ "description": "Red Hat Enterprise Linux AMIs",
+ "search_patterns": [
+ r"RHEL-.*", # All RHEL versions
+ ],
+ },
+ "suse": {
+ "owner_id": "013907871322",
+ "owner_name": "SUSE",
+ "description": "SUSE Linux Enterprise AMIs",
+ "search_patterns": [
+ r"suse-sles-.*",
+ r"suse-sle-.*",
+ ],
+ },
+ "debian": {
+ "owner_id": "136693071363",
+ "owner_name": "Debian",
+ "description": "Debian GNU/Linux AMIs",
+ "search_patterns": [
+ r"debian-.*",
+ ],
+ },
+ "centos": {
+ "owner_id": "125523088429",
+ "owner_name": "CentOS",
+ "description": "CentOS Linux AMIs (Legacy)",
+ "search_patterns": [
+ r"CentOS.*",
+ ],
+ },
+ "rocky": {
+ "owner_id": "792107900819",
+ "owner_name": "Rocky Linux",
+ "description": "Rocky Linux AMIs",
+ "search_patterns": [
+ r"Rocky-.*",
+ ],
+ },
+ "almalinux": {
+ "owner_id": "764336703387",
+ "owner_name": "AlmaLinux",
+ "description": "AlmaLinux AMIs",
+ "search_patterns": [
+ r"AlmaLinux.*",
+ ],
+ },
+ "fedora": {
+ "owner_id": "125523088429",
+ "owner_name": "Fedora Project",
+ "description": "Fedora Linux Cloud AMIs",
+ "search_patterns": [
+ r"Fedora-Cloud-.*",
+ r"Fedora-.*",
+ ],
+ },
+ "oracle": {
+ "owner_id": "131827586825",
+ "owner_name": "Oracle",
+ "description": "Oracle Linux AMIs",
+ "search_patterns": [
+ r"OL.*-.*",
+ ],
+ },
+ }
+
+
+def discover_ami_patterns(
+ owner_id,
+ owner_name,
+ search_patterns,
+ region="us-east-1",
+ quiet=False,
+ max_results=1000,
+):
+ """
+ Dynamically discover AMI patterns by scanning available AMIs for an owner.
+
+ Args:
+ owner_id (str): AWS owner account ID
+ owner_name (str): Human readable owner name
+ search_patterns (list): Regex patterns to filter AMI names
+ region (str): AWS region to query
+ quiet (bool): Suppress debug messages
+ max_results (int): Maximum AMIs to scan
+
+ Returns:
+ dict: Dictionary of discovered AMI patterns and examples
+ """
+ try:
+ if not quiet:
+ print(
+ f"Discovering AMI patterns for {owner_name} in {region}...",
+ file=sys.stderr,
+ )
+
+ ec2_client = boto3.client("ec2", region_name=region)
+
+ # Get all AMIs from this owner
+ all_amis = []
+ paginator = ec2_client.get_paginator("describe_images")
+
+ for page in paginator.paginate(
+ Owners=[owner_id],
+ Filters=[
+ {"Name": "state", "Values": ["available"]},
+ {"Name": "image-type", "Values": ["machine"]},
+ ],
+ ):
+ all_amis.extend(page["Images"])
+ if len(all_amis) >= max_results:
+ all_amis = all_amis[:max_results]
+ break
+
+ if not quiet:
+ print(f"Found {len(all_amis)} total AMIs for {owner_name}", file=sys.stderr)
+
+ # Filter AMIs by search patterns
+ matching_amis = []
+ for ami in all_amis:
+ ami_name = ami.get("Name", "")
+ for pattern in search_patterns:
+ if re.match(pattern, ami_name, re.IGNORECASE):
+ matching_amis.append(ami)
+ break
+
+ if not quiet:
+ print(
+ f"Found {len(matching_amis)} matching AMIs after pattern filtering",
+ file=sys.stderr,
+ )
+
+ # Group AMIs by detected patterns
+ pattern_groups = defaultdict(list)
+
+ for ami in matching_amis:
+ ami_name = ami.get("Name", "")
+ group_key = classify_ami_name(ami_name, owner_name)
+
+ ami_info = {
+ "ami_id": ami["ImageId"],
+ "name": ami_name,
+ "description": ami.get("Description", ""),
+ "creation_date": ami["CreationDate"],
+ "architecture": ami.get("Architecture", "Unknown"),
+ "virtualization_type": ami.get("VirtualizationType", "Unknown"),
+ "root_device_type": ami.get("RootDeviceType", "Unknown"),
+ "platform_details": ami.get("PlatformDetails", "Unknown"),
+ }
+
+ pattern_groups[group_key].append(ami_info)
+
+ # Sort each group by creation date (newest first) and generate patterns
+ discovered_patterns = {}
+ for group_key, amis in pattern_groups.items():
+ # Sort by creation date, newest first
+ sorted_amis = sorted(amis, key=lambda x: x["creation_date"], reverse=True)
+
+ # Generate Terraform-compatible filter pattern
+ terraform_pattern = generate_terraform_pattern(
+ group_key, sorted_amis[:5]
+ ) # Use top 5 for pattern analysis
+
+ discovered_patterns[group_key] = {
+ "display_name": group_key,
+ "ami_count": len(sorted_amis),
+ "latest_ami": sorted_amis[0] if sorted_amis else None,
+ "sample_amis": sorted_amis[:3], # Show 3 most recent
+ "terraform_filter": terraform_pattern,
+ "terraform_example": generate_terraform_example(
+ group_key, terraform_pattern, owner_id
+ ),
+ }
+
+ return discovered_patterns
+
+ except NoCredentialsError:
+ print(
+ "Error: AWS credentials not found. Please configure your credentials.",
+ file=sys.stderr,
+ )
+ return {}
+ except ClientError as e:
+ print(f"AWS API Error: {e}", file=sys.stderr)
+ return {}
+ except Exception as e:
+ print(f"Unexpected error: {e}", file=sys.stderr)
+ return {}
+
+
+def classify_ami_name(ami_name, owner_name):
+ """
+ Classify an AMI name into a logical group for pattern generation.
+
+ Args:
+ ami_name (str): AMI name
+ owner_name (str): Owner name for context
+
+ Returns:
+ str: Classification key
+ """
+ ami_lower = ami_name.lower()
+
+ # Amazon Linux patterns
+ if "al2023" in ami_lower:
+ return "Amazon Linux 2023"
+ elif "amzn2" in ami_lower:
+ return "Amazon Linux 2"
+ elif "amzn-ami" in ami_lower:
+ return "Amazon Linux 1"
+
+ # Ubuntu patterns
+ elif "ubuntu" in ami_lower:
+ if "noble" in ami_lower or "24.04" in ami_lower:
+ return "Ubuntu 24.04 LTS (Noble)"
+ elif "jammy" in ami_lower or "22.04" in ami_lower:
+ return "Ubuntu 22.04 LTS (Jammy)"
+ elif "focal" in ami_lower or "20.04" in ami_lower:
+ return "Ubuntu 20.04 LTS (Focal)"
+ elif "bionic" in ami_lower or "18.04" in ami_lower:
+ return "Ubuntu 18.04 LTS (Bionic)"
+ else:
+ # Extract version number if available
+ version_match = re.search(r"(\d+\.\d+)", ami_name)
+ if version_match:
+ return f"Ubuntu {version_match.group(1)}"
+ return "Ubuntu (Other)"
+
+ # RHEL patterns
+ elif "rhel" in ami_lower:
+ if re.search(r"rhel-?10", ami_lower):
+ return "RHEL 10"
+ elif re.search(r"rhel-?9", ami_lower):
+ return "RHEL 9"
+ elif re.search(r"rhel-?8", ami_lower):
+ return "RHEL 8"
+ elif re.search(r"rhel-?7", ami_lower):
+ return "RHEL 7"
+ else:
+ version_match = re.search(r"rhel-?(\d+)", ami_lower)
+ if version_match:
+ return f"RHEL {version_match.group(1)}"
+ return "RHEL (Other)"
+
+ # Rocky Linux patterns
+ elif "rocky" in ami_lower:
+ version_match = re.search(r"rocky-(\d+)", ami_lower)
+ if version_match:
+ return f"Rocky Linux {version_match.group(1)}"
+ return "Rocky Linux"
+
+ # AlmaLinux patterns
+ elif "almalinux" in ami_lower:
+ version_match = re.search(r"(\d+)", ami_name)
+ if version_match:
+ return f"AlmaLinux {version_match.group(1)}"
+ return "AlmaLinux"
+
+ # Debian patterns
+ elif "debian" in ami_lower:
+ if re.search(r"debian-?12", ami_lower) or "bookworm" in ami_lower:
+ return "Debian 12 (Bookworm)"
+ elif re.search(r"debian-?11", ami_lower) or "bullseye" in ami_lower:
+ return "Debian 11 (Bullseye)"
+ elif re.search(r"debian-?10", ami_lower) or "buster" in ami_lower:
+ return "Debian 10 (Buster)"
+ else:
+ version_match = re.search(r"debian-?(\d+)", ami_lower)
+ if version_match:
+ return f"Debian {version_match.group(1)}"
+ return "Debian (Other)"
+
+ # SUSE patterns
+ elif "suse" in ami_lower or "sles" in ami_lower:
+ version_match = re.search(r"(\d+)", ami_name)
+ if version_match:
+ return f"SUSE Linux Enterprise {version_match.group(1)}"
+ return "SUSE Linux Enterprise"
+
+ # CentOS patterns
+ elif "centos" in ami_lower:
+ version_match = re.search(r"(\d+)", ami_name)
+ if version_match:
+ return f"CentOS {version_match.group(1)}"
+ return "CentOS"
+
+ # Fedora patterns
+ elif "fedora" in ami_lower:
+ version_match = re.search(r"fedora-.*?(\d+)", ami_lower)
+ if version_match:
+ return f"Fedora {version_match.group(1)}"
+ return "Fedora"
+
+ # Oracle Linux patterns
+ elif ami_lower.startswith("ol"):
+ version_match = re.search(r"ol(\d+)", ami_lower)
+ if version_match:
+ return f"Oracle Linux {version_match.group(1)}"
+ return "Oracle Linux"
+
+ # Default: use the owner name
+ return f"{owner_name} (Other)"
+
+
+def generate_terraform_pattern(group_key, sample_amis):
+ """
+ Generate a Terraform-compatible filter pattern from sample AMIs.
+
+ Args:
+ group_key (str): Classification key
+ sample_amis (list): List of sample AMI info
+
+ Returns:
+ str: Terraform filter pattern
+ """
+ if not sample_amis:
+ return ""
+
+ # Analyze common patterns in AMI names
+ names = [ami["name"] for ami in sample_amis]
+
+ # Find the longest common prefix and suffix patterns
+ if len(names) == 1:
+ # Single AMI - create a pattern that matches similar names
+ name = names[0]
+ # Replace specific dates/versions with wildcards
+ pattern = re.sub(r"\d{4}-\d{2}-\d{2}", "*", name) # Replace dates
+ pattern = re.sub(r"-\d+\.\d+\.\d+", "-*", pattern) # Replace version numbers
+ pattern = re.sub(
+ r"_\d+\.\d+\.\d+", "_*", pattern
+ ) # Replace version numbers with underscores
+ return pattern
+
+ # Multiple AMIs - find common pattern
+ common_parts = []
+ min_len = min(len(name) for name in names)
+
+ # Find common prefix
+ prefix_len = 0
+ for i in range(min_len):
+ chars = set(name[i] for name in names)
+ if len(chars) == 1:
+ prefix_len = i + 1
+ else:
+ break
+
+ if prefix_len > 0:
+ prefix = names[0][:prefix_len]
+ return f"{prefix}*"
+
+ # If no common prefix, try to extract the base pattern
+ first_name = names[0]
+ # Replace numbers and dates with wildcards
+ pattern = re.sub(r"\d{8}", "*", first_name) # Replace 8-digit dates
+ pattern = re.sub(r"\d{4}-\d{2}-\d{2}", "*", pattern) # Replace ISO dates
+ pattern = re.sub(r"-\d+\.\d+\.\d+", "-*", pattern) # Replace version numbers
+ pattern = re.sub(
+ r"_\d+\.\d+\.\d+", "_*", pattern
+ ) # Replace version numbers with underscores
+
+ return pattern
+
+
+def generate_terraform_example(group_key, filter_pattern, owner_id):
+ """
+ Generate a complete Terraform example.
+
+ Args:
+ group_key (str): Classification key
+ filter_pattern (str): Filter pattern
+ owner_id (str): AWS owner account ID
+
+ Returns:
+ str: Complete Terraform data source example
+ """
+ # Create a safe resource name
+ resource_name = re.sub(r"[^a-zA-Z0-9_]", "_", group_key.lower())
+ resource_name = re.sub(r"_+", "_", resource_name) # Remove multiple underscores
+ resource_name = resource_name.strip("_") # Remove leading/trailing underscores
+
+ if not filter_pattern:
+ filter_pattern = "*"
+
+ terraform_code = f"""data "aws_ami" "{resource_name}" {{
+ most_recent = true
+ owners = ["{owner_id}"]
+ filter {{
+ name = "name"
+ values = ["{filter_pattern}"]
+ }}
+ filter {{
+ name = "architecture"
+ values = ["x86_64"]
+ }}
+ filter {{
+ name = "virtualization-type"
+ values = ["hvm"]
+ }}
+ filter {{
+ name = "state"
+ values = ["available"]
+ }}
+}}"""
+
+ return terraform_code
+
+
+def get_owner_ami_info(owner_key, region="us-east-1", quiet=False):
+ """
+ Get comprehensive AMI information for a specific owner.
+
+ Args:
+ owner_key (str): Owner key (e.g., 'amazon', 'ubuntu')
+ region (str): AWS region to query
+ quiet (bool): Suppress debug messages
+
+ Returns:
+ dict: Owner information with discovered AMI patterns
+ """
+ known_owners = get_known_ami_owners()
+
+ if owner_key not in known_owners:
+ return None
+
+ owner_info = known_owners[owner_key].copy()
+
+ # Discover actual AMI patterns
+ discovered_patterns = discover_ami_patterns(
+ owner_info["owner_id"],
+ owner_info["owner_name"],
+ owner_info["search_patterns"],
+ region,
+ quiet,
+ )
+
+ owner_info["discovered_patterns"] = discovered_patterns
+ owner_info["total_pattern_count"] = len(discovered_patterns)
+
+ return owner_info
+
+
+def parse_arguments():
+ """Parse command line arguments."""
+ parser = argparse.ArgumentParser(
+ description="Get AWS AMI owner information and Terraform filter examples",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog="""
+Examples:
+ python %(prog)s --owners
+ python %(prog)s amazon
+ python %(prog)s ubuntu --format json
+ python %(prog)s --owners --format csv
+ python %(prog)s redhat --region eu-west-1
+ """,
+ )
+
+ parser.add_argument(
+ "owner_key",
+ nargs="?", # Make owner_key optional when using --owners
+ help="AMI owner key (e.g., amazon, ubuntu, redhat, debian, suse, centos, rocky, almalinux)",
+ )
+
+ parser.add_argument(
+ "--region", "-r", help="AWS region (default: from ~/.aws/config or us-east-1)"
+ )
+
+ parser.add_argument(
+ "--format",
+ "-f",
+ choices=["table", "json", "csv", "terraform"],
+ default="table",
+ help="Output format (default: table)",
+ )
+
+ parser.add_argument(
+ "--quiet", "-q", action="store_true", help="Suppress informational messages"
+ )
+
+ parser.add_argument(
+ "--debug", "-d", action="store_true", help="Enable debug output"
+ )
+
+ parser.add_argument(
+ "--owners", action="store_true", help="List all known AMI owners"
+ )
+
+ parser.add_argument(
+ "--max-results",
+ type=int,
+ default=1000,
+ help="Maximum number of AMIs to scan per owner (default: 1000)",
+ )
+
+ return parser.parse_args()
+
+
+def output_owners_table(owners, quiet=False):
+ """Output AMI owners in table format."""
+ if not quiet:
+ print(f"Known Linux AMI owners ({len(owners)}):\n")
+
+ # Print header
+ print(f"{'Owner Key':<12} {'Owner Name':<15} {'Owner ID':<15} {'Description':<30}")
+ print("-" * 75)
+
+ # Sort owners by key
+ for owner_key in sorted(owners.keys()):
+ owner = owners[owner_key]
+ print(
+ f"{owner_key:<12} "
+ f"{owner['owner_name']:<15} "
+ f"{owner['owner_id']:<15} "
+ f"{owner['description']:<30}"
+ )
+
+
+def output_owners_json(owners):
+ """Output owners in JSON format."""
+ print(json.dumps(owners, indent=2))
+
+
+def output_owners_csv(owners):
+ """Output owners in CSV format."""
+ print("owner_key,owner_name,owner_id,description")
+
+ for owner_key in sorted(owners.keys()):
+ owner = owners[owner_key]
+ description = owner["description"].replace(",", ";") # Avoid CSV issues
+ print(f"{owner_key},{owner['owner_name']},{owner['owner_id']},{description}")
+
+
+def output_owner_table(owner_info, quiet=False):
+ """Output owner AMI information in table format."""
+ if not quiet:
+ print(
+ f"AMI Information for {owner_info['owner_name']} (Owner ID: {owner_info['owner_id']})"
+ )
+ print(f"Description: {owner_info['description']}")
+ print(f"Found {owner_info['total_pattern_count']} AMI pattern groups\n")
+
+ if not owner_info["discovered_patterns"]:
+ print("No AMI patterns discovered for this owner in the specified region.")
+ return
+
+ for pattern_name, pattern_info in sorted(owner_info["discovered_patterns"].items()):
+ print(f"Pattern: {pattern_name}")
+ print(f" AMI Count: {pattern_info['ami_count']}")
+ print(f" Filter Pattern: {pattern_info['terraform_filter']}")
+
+ # Show latest AMI
+ if pattern_info["latest_ami"]:
+ latest = pattern_info["latest_ami"]
+ print(f" Latest AMI: {latest['ami_id']} ({latest['creation_date'][:10]})")
+ print(f" Architecture: {latest['architecture']}")
+
+ # Show sample AMIs
+ if pattern_info["sample_amis"]:
+ print(f" Sample AMIs:")
+ for ami in pattern_info["sample_amis"]:
+ print(
+ f" {ami['ami_id']} - {ami['name'][:60]}{'...' if len(ami['name']) > 60 else ''}"
+ )
+ print(
+ f" Created: {ami['creation_date'][:10]} | Arch: {ami['architecture']} | Virt: {ami['virtualization_type']}"
+ )
+
+ print() # Empty line between patterns
+
+
+def output_owner_json(owner_info):
+ """Output owner information in JSON format."""
+
+ # Convert datetime objects to strings for JSON serialization
+ def json_serializer(obj):
+ if hasattr(obj, "isoformat"):
+ return obj.isoformat()
+ return str(obj)
+
+ print(json.dumps(owner_info, indent=2, default=json_serializer))
+
+
+def output_owner_csv(owner_info):
+ """Output owner information in CSV format."""
+ print(
+ "pattern_name,ami_count,filter_pattern,latest_ami_id,latest_ami_name,creation_date,architecture"
+ )
+
+ for pattern_name, pattern_info in sorted(owner_info["discovered_patterns"].items()):
+ latest = pattern_info.get("latest_ami", {})
+ ami_id = latest.get("ami_id", "")
+ ami_name = latest.get("name", "").replace(",", ";") # Avoid CSV issues
+ creation_date = (
+ latest.get("creation_date", "")[:10] if latest.get("creation_date") else ""
+ )
+ architecture = latest.get("architecture", "")
+
+ print(
+ f"{pattern_name},{pattern_info['ami_count']},{pattern_info['terraform_filter']},{ami_id},{ami_name},{creation_date},{architecture}"
+ )
+
+
+def output_owner_terraform(owner_info):
+ """Output owner information as Terraform examples."""
+ print(f"# Terraform aws_ami data source examples for {owner_info['owner_name']}")
+ print(f"# Owner ID: {owner_info['owner_id']}")
+ print(f"# {owner_info['description']}")
+ print(f"# Found {owner_info['total_pattern_count']} AMI pattern groups")
+ print()
+
+ for pattern_name, pattern_info in sorted(owner_info["discovered_patterns"].items()):
+ print(f"# {pattern_name} ({pattern_info['ami_count']} AMIs available)")
+ if pattern_info["latest_ami"]:
+ print(
+ f"# Latest: {pattern_info['latest_ami']['ami_id']} ({pattern_info['latest_ami']['creation_date'][:10]})"
+ )
+ print(pattern_info["terraform_example"])
+ print()
+
+
+def main():
+ """Main function to run the program."""
+ args = parse_arguments()
+
+ # Determine region
+ if args.region:
+ region = args.region
+ else:
+ region = get_aws_default_region()
+
+ # Handle --owners option
+ if args.owners:
+ owners = get_known_ami_owners()
+ if args.format == "json":
+ output_owners_json(owners)
+ elif args.format == "csv":
+ output_owners_csv(owners)
+ else: # table format (terraform not applicable for owners list)
+ output_owners_table(owners, args.quiet)
+ return
+
+ # Require owner_key if not using --owners
+ if not args.owner_key:
+ print(
+ "Error: owner_key is required unless using --owners option", file=sys.stderr
+ )
+ print("Use --owners to list all available AMI owners", file=sys.stderr)
+ sys.exit(1)
+
+ # Validate owner key
+ known_owners = get_known_ami_owners()
+ if args.owner_key not in known_owners:
+ print(f"Error: Unknown owner key '{args.owner_key}'", file=sys.stderr)
+ print(
+ f"Available owners: {', '.join(sorted(known_owners.keys()))}",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ if not args.quiet:
+ print(
+ f"Discovering AMI patterns for {args.owner_key} in {region}...",
+ file=sys.stderr,
+ )
+ print(f"This may take a moment as we scan available AMIs...", file=sys.stderr)
+
+ # Get owner information with dynamic discovery
+ owner_info = get_owner_ami_info(
+ args.owner_key, region, args.quiet or not args.debug
+ )
+
+ if not owner_info:
+ print(
+ f"Could not retrieve AMI information for owner '{args.owner_key}'.",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ if not owner_info.get("discovered_patterns"):
+ print(
+ f"No AMI patterns discovered for owner '{args.owner_key}' in region {region}.",
+ file=sys.stderr,
+ )
+ print(
+ "This may be because the owner has no AMIs in this region or the search patterns need adjustment.",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ # Output results in specified format
+ if args.format == "json":
+ output_owner_json(owner_info)
+ elif args.format == "csv":
+ output_owner_csv(owner_info)
+ elif args.format == "terraform":
+ output_owner_terraform(owner_info)
+ else: # table format
+ output_owner_table(owner_info, args.quiet)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/terraform/aws/scripts/aws_regions_info.py b/terraform/aws/scripts/aws_regions_info.py
new file mode 100755
index 00000000..00b88e0a
--- /dev/null
+++ b/terraform/aws/scripts/aws_regions_info.py
@@ -0,0 +1,371 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: MIT
+
+import boto3
+import json
+import sys
+import argparse
+import os
+from configparser import ConfigParser
+from botocore.exceptions import ClientError, NoCredentialsError
+
+
+def get_aws_default_region():
+ """
+ Get the default AWS region from ~/.aws/config file.
+
+ Returns:
+ str: Default region or 'us-east-1' if not found
+ """
+ config_path = os.path.expanduser("~/.aws/config")
+
+ if os.path.exists(config_path):
+ try:
+ config = ConfigParser()
+ config.read(config_path)
+
+ # Check for default profile region
+ if "default" in config:
+ return config["default"].get("region", "us-east-1")
+
+ # Check for profile default section
+ if "profile default" in config:
+ return config["profile default"].get("region", "us-east-1")
+
+ except Exception as e:
+ print(f"Warning: Error reading AWS config file: {e}", file=sys.stderr)
+
+ return "us-east-1"
+
+
+def get_all_regions():
+ """
+ Get all available AWS regions with their descriptions.
+
+ Returns:
+ dict: Dictionary of region information
+ """
+ try:
+ # Use a default region to get the list of all regions
+ ec2_client = boto3.client("ec2", region_name="us-east-1")
+ response = ec2_client.describe_regions(AllRegions=True)
+
+ regions = {}
+ for region in response["Regions"]:
+ region_name = region["RegionName"]
+ regions[region_name] = {
+ "region_name": region_name,
+ "region_description": region.get("RegionName", region_name),
+ "opt_in_status": region.get("OptInStatus", "Unknown"),
+ "availability_zones": [],
+ }
+
+ return regions
+
+ except Exception as e:
+ print(f"Error retrieving AWS regions: {e}", file=sys.stderr)
+ return {}
+
+
+def get_region_info(region_name, quiet=False):
+ """
+ Get detailed information about a specific region including availability zones.
+
+ Args:
+ region_name (str): AWS region name (e.g., 'us-east-1', 'eu-west-1')
+ quiet (bool): Suppress debug messages
+
+ Returns:
+ dict: Dictionary containing region information and availability zones
+ """
+ try:
+ if not quiet:
+ print(f"Querying information for region {region_name}...", file=sys.stderr)
+
+ # Initialize EC2 client for the specific region
+ ec2_client = boto3.client("ec2", region_name=region_name)
+
+ # Get region information
+ regions_response = ec2_client.describe_regions(
+ Filters=[{"Name": "region-name", "Values": [region_name]}]
+ )
+
+ if not regions_response["Regions"]:
+ if not quiet:
+ print(f"Region {region_name} not found", file=sys.stderr)
+ return None
+
+ region_info = regions_response["Regions"][0]
+
+ # Get availability zones for the region
+ az_response = ec2_client.describe_availability_zones()
+
+ availability_zones = []
+ for az in az_response["AvailabilityZones"]:
+ zone_info = {
+ "zone_id": az["ZoneId"],
+ "zone_name": az["ZoneName"],
+ "zone_type": az.get("ZoneType", "availability-zone"),
+ "parent_zone_id": az.get("ParentZoneId", ""),
+ "parent_zone_name": az.get("ParentZoneName", ""),
+ "state": az["State"],
+ "messages": [],
+ }
+
+ # Add any messages about the zone
+ if "Messages" in az:
+ zone_info["messages"] = [
+ msg.get("Message", "") for msg in az["Messages"]
+ ]
+
+ availability_zones.append(zone_info)
+
+ # Get network border group information if available
+ try:
+ zone_details = {}
+ for az in az_response["AvailabilityZones"]:
+ if "NetworkBorderGroup" in az:
+ zone_details[az["ZoneName"]] = az["NetworkBorderGroup"]
+ except:
+ zone_details = {}
+
+ result = {
+ "region_name": region_info["RegionName"],
+ "endpoint": region_info.get("Endpoint", f"ec2.{region_name}.amazonaws.com"),
+ "opt_in_status": region_info.get("OptInStatus", "opt-in-not-required"),
+ "availability_zone_count": len(availability_zones),
+ "availability_zones": sorted(
+ availability_zones, key=lambda x: x["zone_name"]
+ ),
+ }
+
+ if not quiet:
+ print(
+ f"Found {len(availability_zones)} availability zones in {region_name}",
+ file=sys.stderr,
+ )
+
+ return result
+
+ except NoCredentialsError:
+ print(
+ "Error: AWS credentials not found. Please configure your credentials.",
+ file=sys.stderr,
+ )
+ return None
+ except ClientError as e:
+ error_code = e.response.get("Error", {}).get("Code", "Unknown")
+ if error_code in ["UnauthorizedOperation", "InvalidRegion"]:
+ print(
+ f"Error: Cannot access region {region_name}. Check region name and permissions.",
+ file=sys.stderr,
+ )
+ else:
+ print(f"AWS API Error: {e}", file=sys.stderr)
+ return None
+ except Exception as e:
+ print(f"Unexpected error: {e}", file=sys.stderr)
+ return None
+
+
+def parse_arguments():
+ """Parse command line arguments."""
+ parser = argparse.ArgumentParser(
+ description="Get AWS region and availability zone information",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog="""
+Examples:
+ python %(prog)s --regions
+ python %(prog)s us-east-1
+ python %(prog)s eu-west-1 --format json
+ python %(prog)s --regions --format csv
+ python %(prog)s ap-southeast-1 --quiet
+ """,
+ )
+
+ parser.add_argument(
+ "region_name",
+ nargs="?", # Make region_name optional when using --regions
+ help="AWS region name (e.g., us-east-1, eu-west-1, ap-southeast-1)",
+ )
+
+ parser.add_argument(
+ "--format",
+ "-f",
+ choices=["table", "json", "csv"],
+ default="table",
+ help="Output format (default: table)",
+ )
+
+ parser.add_argument(
+ "--quiet", "-q", action="store_true", help="Suppress informational messages"
+ )
+
+ parser.add_argument(
+ "--debug", "-d", action="store_true", help="Enable debug output"
+ )
+
+ parser.add_argument(
+ "--regions", action="store_true", help="List all available AWS regions"
+ )
+
+ return parser.parse_args()
+
+
+def output_regions_table(regions, quiet=False):
+ """Output available regions in table format."""
+ if not quiet:
+ print(f"Available AWS regions ({len(regions)}):\n")
+
+ # Print header
+ print(f"{'Region Name':<20} {'Opt-in Status':<20}")
+ print("-" * 42)
+
+ # Sort regions by name
+ sorted_regions = sorted(regions.values(), key=lambda x: x["region_name"])
+
+ for region in sorted_regions:
+ opt_in_status = region.get("opt_in_status", "Unknown")
+ print(f"{region['region_name']:<20} {opt_in_status:<20}")
+
+
+def output_regions_json(regions):
+ """Output regions in JSON format."""
+ # Convert to list for JSON output
+ regions_list = sorted(regions.values(), key=lambda x: x["region_name"])
+ print(json.dumps(regions_list, indent=2))
+
+
+def output_regions_csv(regions):
+ """Output regions in CSV format."""
+ if regions:
+ # Print header
+ print("region_name,opt_in_status")
+
+ # Sort regions by name
+ sorted_regions = sorted(regions.values(), key=lambda x: x["region_name"])
+
+ # Print data
+ for region in sorted_regions:
+ opt_in_status = region.get("opt_in_status", "Unknown")
+ print(f"{region['region_name']},{opt_in_status}")
+
+
+def output_region_table(region_info, quiet=False):
+ """Output region information in table format."""
+ if not quiet:
+ print(f"Region: {region_info['region_name']}\n")
+ print(f"Endpoint: {region_info['endpoint']}")
+ print(f"Opt-in Status: {region_info['opt_in_status']}")
+ print(f"Availability Zones: {region_info['availability_zone_count']}\n")
+
+ # Print availability zones table
+ print(
+ f"{'Zone Name':<15} {'Zone ID':<15} {'Zone Type':<18} {'State':<12} {'Parent Zone':<15}"
+ )
+ print("-" * 80)
+
+ for az in region_info["availability_zones"]:
+ parent_zone = az.get("parent_zone_name", "") or az.get("parent_zone_id", "")
+ zone_type = az.get("zone_type", "availability-zone")
+
+ print(
+ f"{az['zone_name']:<15} "
+ f"{az['zone_id']:<15} "
+ f"{zone_type:<18} "
+ f"{az['state']:<12} "
+ f"{parent_zone:<15}"
+ )
+
+ # Show messages if any zones have them
+ zones_with_messages = [
+ az for az in region_info["availability_zones"] if az.get("messages")
+ ]
+ if zones_with_messages and not quiet:
+ print("\nZone Messages:")
+ for az in zones_with_messages:
+ for message in az["messages"]:
+ print(f" {az['zone_name']}: {message}")
+
+
+def output_region_json(region_info):
+ """Output region information in JSON format."""
+ print(json.dumps(region_info, indent=2))
+
+
+def output_region_csv(region_info):
+ """Output region information in CSV format."""
+ # First output region info
+ print("type,region_name,endpoint,opt_in_status,availability_zone_count")
+ print(
+ f"region,{region_info['region_name']},{region_info['endpoint']},{region_info['opt_in_status']},{region_info['availability_zone_count']}"
+ )
+
+ # Then output availability zones
+ print("\ntype,zone_name,zone_id,zone_type,state,parent_zone_name,parent_zone_id")
+ for az in region_info["availability_zones"]:
+ parent_zone_name = az.get("parent_zone_name", "")
+ parent_zone_id = az.get("parent_zone_id", "")
+ zone_type = az.get("zone_type", "availability-zone")
+
+ print(
+ f"availability_zone,{az['zone_name']},{az['zone_id']},{zone_type},{az['state']},{parent_zone_name},{parent_zone_id}"
+ )
+
+
+def main():
+ """Main function to run the program."""
+ args = parse_arguments()
+
+ # Handle --regions option
+ if args.regions:
+ if not args.quiet:
+ print("Fetching list of all AWS regions...", file=sys.stderr)
+
+ regions = get_all_regions()
+ if regions:
+ if args.format == "json":
+ output_regions_json(regions)
+ elif args.format == "csv":
+ output_regions_csv(regions)
+ else: # table format
+ output_regions_table(regions, args.quiet)
+ else:
+ print("Could not retrieve AWS regions.", file=sys.stderr)
+ sys.exit(1)
+ return
+
+ # Require region_name if not using --regions
+ if not args.region_name:
+ print(
+ "Error: region_name is required unless using --regions option",
+ file=sys.stderr,
+ )
+ print("Use --regions to list all available regions", file=sys.stderr)
+ sys.exit(1)
+
+ if not args.quiet:
+ print(f"Fetching information for region {args.region_name}...", file=sys.stderr)
+
+ # Get region information
+ region_info = get_region_info(args.region_name, args.quiet or not args.debug)
+
+ if not region_info:
+ print(
+ f"Could not retrieve information for region '{args.region_name}'.",
+ file=sys.stderr,
+ )
+ print(f"Try running with --regions to see available regions.", file=sys.stderr)
+ sys.exit(1)
+
+ # Output results in specified format
+ if args.format == "json":
+ output_region_json(region_info)
+ elif args.format == "csv":
+ output_region_csv(region_info)
+ else: # table format
+ output_region_table(region_info, args.quiet)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/terraform/aws/scripts/ec2_instance_info.py b/terraform/aws/scripts/ec2_instance_info.py
new file mode 100755
index 00000000..4dcbc6c9
--- /dev/null
+++ b/terraform/aws/scripts/ec2_instance_info.py
@@ -0,0 +1,540 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: MIT
+
+import boto3
+import json
+import sys
+import argparse
+import os
+from configparser import ConfigParser
+from botocore.exceptions import ClientError, NoCredentialsError
+
+
+def get_aws_default_region():
+ """
+ Get the default AWS region from ~/.aws/config file.
+
+ Returns:
+ str: Default region or 'us-east-1' if not found
+ """
+ config_path = os.path.expanduser("~/.aws/config")
+
+ if os.path.exists(config_path):
+ try:
+ config = ConfigParser()
+ config.read(config_path)
+
+ # Check for default profile region
+ if "default" in config:
+ return config["default"].get("region", "us-east-1")
+
+ # Check for profile default section
+ if "profile default" in config:
+ return config["profile default"].get("region", "us-east-1")
+
+ except Exception as e:
+ print(f"Warning: Error reading AWS config file: {e}", file=sys.stderr)
+
+ return "us-east-1"
+
+
+def get_available_families(region="us-east-1"):
+ """
+ Get all available instance families in the specified region.
+
+ Args:
+ region (str): AWS region to query
+
+ Returns:
+ dict: Dictionary with family info including count of instances per family
+ """
+ try:
+ ec2_client = boto3.client("ec2", region_name=region)
+ response = ec2_client.describe_instance_types()
+
+ families = {}
+ for instance_type in response["InstanceTypes"]:
+ instance_name = instance_type["InstanceType"]
+ family = instance_name.split(".")[0]
+
+ if family not in families:
+ families[family] = {
+ "family_name": family,
+ "instance_count": 0,
+ "has_gpu": False,
+ "architectures": set(),
+ }
+
+ families[family]["instance_count"] += 1
+
+ # Check for GPU
+ if "GpuInfo" in instance_type:
+ families[family]["has_gpu"] = True
+
+ # Get architectures
+ cpu_architectures = instance_type.get("ProcessorInfo", {}).get(
+ "SupportedArchitectures", []
+ )
+ families[family]["architectures"].update(cpu_architectures)
+
+ # Convert architecture sets to sorted lists for JSON serialization
+ for family in families.values():
+ family["architectures"] = sorted(list(family["architectures"]))
+
+ return families
+
+ except Exception as e:
+ print(f"Error retrieving instance families: {e}", file=sys.stderr)
+ return {}
+
+
+def get_gpu_info(instance_type):
+ """
+ Extract GPU information from instance type data.
+
+ Args:
+ instance_type (dict): Instance type data from AWS API
+
+ Returns:
+ str: Formatted GPU information string
+ """
+ if "GpuInfo" not in instance_type:
+ return "None"
+
+ gpu_info = instance_type["GpuInfo"]
+ total_gpu_memory = gpu_info.get("TotalGpuMemoryInMiB", 0)
+ gpus = gpu_info.get("Gpus", [])
+
+ if not gpus:
+ return "GPU present (details unavailable)"
+
+ gpu_details = []
+ for gpu in gpus:
+ gpu_name = gpu.get("Name", "Unknown GPU")
+ gpu_count = gpu.get("Count", 1)
+ gpu_memory = gpu.get("MemoryInfo", {}).get("SizeInMiB", 0)
+
+ if gpu_count > 1:
+ detail = f"{gpu_count}x {gpu_name}"
+ else:
+ detail = gpu_name
+
+ if gpu_memory > 0:
+ detail += f" ({gpu_memory // 1024}GB)"
+
+ gpu_details.append(detail)
+
+ return ", ".join(gpu_details)
+
+
+def get_instance_family_info(family_name, region="us-east-1", quiet=False):
+ """
+ Get instance types, pricing, and hardware info for an AWS instance family.
+
+ Args:
+ family_name (str): Instance family name (e.g., 'm5', 't3', 'c5')
+ region (str): AWS region to query (default: us-east-1)
+ quiet (bool): Suppress debug messages
+
+ Returns:
+ list: List of dictionaries containing instance information
+ """
+ try:
+ # Initialize AWS clients
+ ec2_client = boto3.client("ec2", region_name=region)
+ pricing_client = boto3.client(
+ "pricing", region_name="us-east-1"
+ ) # Pricing API only in us-east-1
+
+ if not quiet:
+ print(
+ f"Querying EC2 API for instances starting with '{family_name}'...",
+ file=sys.stderr,
+ )
+
+ # Get ALL instance types first, then filter
+ response = ec2_client.describe_instance_types()
+
+ # Filter instances that belong to the specified family
+ family_instances = []
+ for instance_type in response["InstanceTypes"]:
+ instance_name = instance_type["InstanceType"]
+ # More flexible matching - check if instance name starts with family name
+ if instance_name.startswith(family_name + ".") or instance_name.startswith(
+ family_name
+ ):
+ family_instances.append(instance_type)
+
+ if not family_instances:
+ if not quiet:
+ print(
+ f"No instances found starting with '{family_name}'. Trying broader search...",
+ file=sys.stderr,
+ )
+
+ # Try a broader search - maybe the family name is part of the instance type
+ family_instances = []
+ for instance_type in response["InstanceTypes"]:
+ instance_name = instance_type["InstanceType"]
+ if family_name.lower() in instance_name.lower():
+ family_instances.append(instance_type)
+
+ if not family_instances:
+ if not quiet:
+ # Show available families to help debug
+ families = get_available_families(region)
+ family_names = sorted([f["family_name"] for f in families.values()])
+ print(f"Available instance families: {family_names}", file=sys.stderr)
+ return []
+
+ if not quiet:
+ print(
+ f"Found {len(family_instances)} instances in family '{family_name}'",
+ file=sys.stderr,
+ )
+
+ instance_info = []
+
+ for instance_type in family_instances:
+ instance_name = instance_type["InstanceType"]
+
+ if not quiet:
+ print(f"Processing {instance_name}...", file=sys.stderr)
+
+ # Extract CPU architecture information
+ cpu_architectures = instance_type.get("ProcessorInfo", {}).get(
+ "SupportedArchitectures", ["Unknown"]
+ )
+ cpu_isa = ", ".join(cpu_architectures) if cpu_architectures else "Unknown"
+
+ # Extract GPU information
+ gpu_info = get_gpu_info(instance_type)
+
+ # Extract hardware specifications
+ hardware_info = {
+ "instance_type": instance_name,
+ "vcpus": instance_type["VCpuInfo"]["DefaultVCpus"],
+ "memory_gb": instance_type["MemoryInfo"]["SizeInMiB"] / 1024,
+ "cpu_isa": cpu_isa,
+ "gpu": gpu_info,
+ "network_performance": instance_type.get("NetworkInfo", {}).get(
+ "NetworkPerformance", "Not specified"
+ ),
+ "storage": "EBS-only",
+ }
+
+ # Check for instance storage
+ if "InstanceStorageInfo" in instance_type:
+ storage_info = instance_type["InstanceStorageInfo"]
+ total_storage = storage_info.get("TotalSizeInGB", 0)
+ storage_type = storage_info.get("Disks", [{}])[0].get("Type", "Unknown")
+ hardware_info["storage"] = f"{total_storage} GB {storage_type}"
+
+ # Get pricing information (note: this often fails due to AWS Pricing API limitations)
+ try:
+ pricing_response = pricing_client.get_products(
+ ServiceCode="AmazonEC2",
+ Filters=[
+ {
+ "Type": "TERM_MATCH",
+ "Field": "instanceType",
+ "Value": instance_name,
+ },
+ {
+ "Type": "TERM_MATCH",
+ "Field": "location",
+ "Value": get_location_name(region),
+ },
+ {"Type": "TERM_MATCH", "Field": "tenancy", "Value": "Shared"},
+ {
+ "Type": "TERM_MATCH",
+ "Field": "operating-system",
+ "Value": "Linux",
+ },
+ {
+ "Type": "TERM_MATCH",
+ "Field": "preInstalledSw",
+ "Value": "NA",
+ },
+ {
+ "Type": "TERM_MATCH",
+ "Field": "capacitystatus",
+ "Value": "Used",
+ },
+ ],
+ )
+
+ if pricing_response["PriceList"]:
+ price_data = json.loads(pricing_response["PriceList"][0])
+ terms = price_data["terms"]["OnDemand"]
+
+ # Extract the hourly price
+ for term_key in terms:
+ price_dimensions = terms[term_key]["priceDimensions"]
+ for price_key in price_dimensions:
+ price_per_hour = price_dimensions[price_key][
+ "pricePerUnit"
+ ]["USD"]
+ hardware_info["price_per_hour_usd"] = f"${price_per_hour}"
+ break
+ break
+ else:
+ hardware_info["price_per_hour_usd"] = "Not available"
+
+ except Exception as e:
+ if not quiet:
+ print(
+ f"Warning: Could not fetch pricing for {instance_name}: {str(e)}",
+ file=sys.stderr,
+ )
+ hardware_info["price_per_hour_usd"] = "Not available"
+
+ instance_info.append(hardware_info)
+
+ return sorted(instance_info, key=lambda x: x["instance_type"])
+
+ except NoCredentialsError:
+ print(
+ "Error: AWS credentials not found. Please configure your credentials.",
+ file=sys.stderr,
+ )
+ return []
+ except ClientError as e:
+ print(f"AWS API Error: {e}", file=sys.stderr)
+ return []
+ except Exception as e:
+ print(f"Unexpected error: {e}", file=sys.stderr)
+ return []
+
+
+def get_location_name(region):
+ """Convert AWS region to location name for pricing API."""
+ region_mapping = {
+ "us-east-1": "US East (N. Virginia)",
+ "us-east-2": "US East (Ohio)",
+ "us-west-1": "US West (N. California)",
+ "us-west-2": "US West (Oregon)",
+ "us-west-2-lax-1": "US West (Los Angeles)",
+ "ca-central-1": "Canada (Central)",
+ "eu-west-1": "Europe (Ireland)",
+ "eu-west-2": "Europe (London)",
+ "eu-west-3": "Europe (Paris)",
+ "eu-central-1": "Europe (Frankfurt)",
+ "eu-north-1": "Europe (Stockholm)",
+ "ap-southeast-1": "Asia Pacific (Singapore)",
+ "ap-southeast-2": "Asia Pacific (Sydney)",
+ "ap-northeast-1": "Asia Pacific (Tokyo)",
+ "ap-northeast-2": "Asia Pacific (Seoul)",
+ "ap-south-1": "Asia Pacific (Mumbai)",
+ "sa-east-1": "South America (Sao Paulo)",
+ }
+ return region_mapping.get(region, "US East (N. Virginia)")
+
+
+def parse_arguments():
+ """Parse command line arguments."""
+ parser = argparse.ArgumentParser(
+ description="Get AWS EC2 instance family information including pricing and hardware specs",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog="""
+Examples:
+ python %(prog)s m5
+ python %(prog)s t3 --region us-west-2
+ python %(prog)s c5 --format json
+ python %(prog)s r5 --quiet
+ python %(prog)s --families
+ python %(prog)s --families --format json
+ """,
+ )
+
+ parser.add_argument(
+ "family_name",
+ nargs="?", # Make family_name optional when using --families
+ help="Instance family name (e.g., m5, t3, c5, r5)",
+ )
+
+ parser.add_argument(
+ "--region", "-r", help="AWS region (default: from ~/.aws/config or us-east-1)"
+ )
+
+ parser.add_argument(
+ "--format",
+ "-f",
+ choices=["table", "json", "csv"],
+ default="table",
+ help="Output format (default: table)",
+ )
+
+ parser.add_argument(
+ "--quiet", "-q", action="store_true", help="Suppress informational messages"
+ )
+
+ parser.add_argument(
+ "--debug", "-d", action="store_true", help="Enable debug output"
+ )
+
+ parser.add_argument(
+ "--families",
+ action="store_true",
+ help="List all available instance families in the region",
+ )
+
+ return parser.parse_args()
+
+
+def output_families_table(families, region, quiet=False):
+ """Output available instance families in table format."""
+ if not quiet:
+ print(f"Available instance families in {region}:\n")
+
+ # Print header
+ print(f"{'Family':<10} {'Count':<6} {'GPU':<5} {'Architectures':<20}")
+ print("-" * 45)
+
+ # Sort families by name
+ sorted_families = sorted(families.values(), key=lambda x: x["family_name"])
+
+ for family in sorted_families:
+ gpu_indicator = "Yes" if family["has_gpu"] else "No"
+ architectures = ", ".join(family["architectures"])
+
+ print(
+ f"{family['family_name']:<10} "
+ f"{family['instance_count']:<6} "
+ f"{gpu_indicator:<5} "
+ f"{architectures:<20}"
+ )
+
+
+def output_families_json(families):
+ """Output families in JSON format."""
+ # Convert to list for JSON output
+ families_list = sorted(families.values(), key=lambda x: x["family_name"])
+ print(json.dumps(families_list, indent=2))
+
+
+def output_families_csv(families):
+ """Output families in CSV format."""
+ if families:
+ # Print header
+ print("family_name,instance_count,has_gpu,architectures")
+
+ # Sort families by name
+ sorted_families = sorted(families.values(), key=lambda x: x["family_name"])
+
+ # Print data
+ for family in sorted_families:
+ architectures = ";".join(
+ family["architectures"]
+ ) # Use semicolon to avoid CSV issues
+ print(
+ f"{family['family_name']},{family['instance_count']},{family['has_gpu']},{architectures}"
+ )
+
+
+def output_table(instances, quiet=False):
+ """Output results in table format."""
+ if not quiet:
+ print(f"Found {len(instances)} instance types:\n")
+
+ # Print header - adjusted for GPU column
+ print(
+ f"{'Instance Type':<15} {'vCPUs':<6} {'Memory (GB)':<12} {'CPU ISA':<10} {'GPU':<25} {'Storage':<20} {'Network':<15} {'Price/Hour':<12}"
+ )
+ print("-" * 130)
+
+ # Print instance details
+ for instance in instances:
+ print(
+ f"{instance['instance_type']:<15} "
+ f"{instance['vcpus']:<6} "
+ f"{instance['memory_gb']:<12.1f} "
+ f"{instance['cpu_isa']:<10} "
+ f"{instance['gpu']:<25} "
+ f"{instance['storage']:<20} "
+ f"{instance['network_performance']:<15} "
+ f"{instance['price_per_hour_usd']:<12}"
+ )
+
+
+def output_json(instances):
+ """Output results in JSON format."""
+ print(json.dumps(instances, indent=2))
+
+
+def output_csv(instances):
+ """Output results in CSV format."""
+ if instances:
+ # Print header
+ headers = instances[0].keys()
+ print(",".join(headers))
+
+ # Print data
+ for instance in instances:
+ values = [str(instance[header]).replace(",", ";") for header in headers]
+ print(",".join(values))
+
+
+def main():
+ """Main function to run the program."""
+ args = parse_arguments()
+
+ # Determine region
+ if args.region:
+ region = args.region
+ else:
+ region = get_aws_default_region()
+
+ # Handle --families option
+ if args.families:
+ families = get_available_families(region)
+ if families:
+ if args.format == "json":
+ output_families_json(families)
+ elif args.format == "csv":
+ output_families_csv(families)
+ else: # table format
+ output_families_table(families, region, args.quiet)
+ else:
+ print("Could not retrieve instance families.", file=sys.stderr)
+ sys.exit(1)
+ return
+
+ # Require family_name if not using --families
+ if not args.family_name:
+ print(
+ "Error: family_name is required unless using --families option",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ if not args.quiet:
+ print(
+ f"Fetching information for {args.family_name} family in {region}...",
+ file=sys.stderr,
+ )
+
+ # Get instance information
+ instances = get_instance_family_info(
+ args.family_name, region, args.quiet or not args.debug
+ )
+
+ if not instances:
+ print(f"No instances found for family '{args.family_name}'.", file=sys.stderr)
+ print(
+ f"Try running with --families to see available instance families.",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ # Output results in specified format
+ if args.format == "json":
+ output_json(instances)
+ elif args.format == "csv":
+ output_csv(instances)
+ else: # table format
+ output_table(instances, args.quiet)
+
+
+if __name__ == "__main__":
+ main()
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v4 6/8] aws: replace static Kconfig files with dynamically generated ones
2025-09-17 0:34 [PATCH v4 0/8] aws: add dynamic kconfig support Luis Chamberlain
` (4 preceding siblings ...)
2025-09-17 0:34 ` [PATCH v4 5/8] aws: add cloud billing support with make cloud-bill Luis Chamberlain
@ 2025-09-17 0:34 ` Luis Chamberlain
2025-09-17 0:34 ` [PATCH v4 7/8] aws: add GPU instance defconfigs for AI/ML workloads Luis Chamberlain
2025-09-17 0:34 ` [PATCH v4 8/8] docs: add documentation for dynamic cloud configuration Luis Chamberlain
7 siblings, 0 replies; 13+ messages in thread
From: Luis Chamberlain @ 2025-09-17 0:34 UTC (permalink / raw)
To: Chuck Lever, Daniel Gomez, kdevops; +Cc: Luis Chamberlain
Remove old static AWS Kconfig files and update the configuration to
use dynamically generated files instead. This change:
- Removes 8 static Kconfig files (compute, location, and 6 instance types)
- Updates terraform/aws/Kconfig to source the .generated files
- Fixes Kconfig symbol generation to handle dashes in instance names
- Filters instance families to prevent mixing related families
The dynamic files now provide:
- 146 instance family configurations (vs 6 static ones)
- 34 AWS regions (vs static subset)
- 900+ instance types with current specs
Also fixes generator to:
- Convert dashes to underscores in Kconfig symbols (e.g., metal-24xl)
- Filter instances to exact family matches (r8g vs r8gd/r8gn)
- Ensure valid Kconfig syntax for all generated files
Generated-by: Claude AI
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
terraform/aws/Kconfig | 4 +-
terraform/aws/kconfigs/Kconfig.compute | 118 ---
terraform/aws/kconfigs/Kconfig.location | 679 ------------------
.../aws/kconfigs/instance-types/Kconfig.c7a | 28 -
.../aws/kconfigs/instance-types/Kconfig.i4i | 33 -
.../aws/kconfigs/instance-types/Kconfig.im4gn | 25 -
.../kconfigs/instance-types/Kconfig.is4gen | 25 -
.../aws/kconfigs/instance-types/Kconfig.m5 | 48 --
.../aws/kconfigs/instance-types/Kconfig.m7a | 57 --
terraform/aws/scripts/generate_aws_kconfig.py | 20 +-
10 files changed, 18 insertions(+), 1019 deletions(-)
delete mode 100644 terraform/aws/kconfigs/Kconfig.compute
delete mode 100644 terraform/aws/kconfigs/Kconfig.location
delete mode 100644 terraform/aws/kconfigs/instance-types/Kconfig.c7a
delete mode 100644 terraform/aws/kconfigs/instance-types/Kconfig.i4i
delete mode 100644 terraform/aws/kconfigs/instance-types/Kconfig.im4gn
delete mode 100644 terraform/aws/kconfigs/instance-types/Kconfig.is4gen
delete mode 100644 terraform/aws/kconfigs/instance-types/Kconfig.m5
delete mode 100644 terraform/aws/kconfigs/instance-types/Kconfig.m7a
diff --git a/terraform/aws/Kconfig b/terraform/aws/Kconfig
index d4015cda..de8bc028 100644
--- a/terraform/aws/Kconfig
+++ b/terraform/aws/Kconfig
@@ -1,10 +1,10 @@
if TERRAFORM_AWS
menu "Resource Location"
-source "terraform/aws/kconfigs/Kconfig.location"
+source "terraform/aws/kconfigs/Kconfig.location.generated"
endmenu
menu "Compute"
-source "terraform/aws/kconfigs/Kconfig.compute"
+source "terraform/aws/kconfigs/Kconfig.compute.generated"
endmenu
menu "Storage"
source "terraform/aws/kconfigs/Kconfig.storage"
diff --git a/terraform/aws/kconfigs/Kconfig.compute b/terraform/aws/kconfigs/Kconfig.compute
deleted file mode 100644
index 4b9c6efb..00000000
--- a/terraform/aws/kconfigs/Kconfig.compute
+++ /dev/null
@@ -1,118 +0,0 @@
-choice
- prompt "AWS instance types"
- help
- Instance types comprise varying combinations of hardware
- platform, CPU count, memory size, storage, and networking
- capacity. Select the type that provides an appropriate mix
- of resources for your preferred workflows.
-
- Some instance types are region- and capacity-limited.
-
- See https://aws.amazon.com/ec2/instance-types/ for
- details.
-
-config TERRAFORM_AWS_INSTANCE_TYPE_M5
- bool "M5"
- depends on TARGET_ARCH_X86_64
- help
- This is a general purpose type powered by Intel Xeon®
- Platinum 8175M or 8259CL processors (Skylake or Cascade
- Lake).
-
- See https://aws.amazon.com/ec2/instance-types/m5/ for
- details.
-
-config TERRAFORM_AWS_INSTANCE_TYPE_M7A
- bool "M7a"
- depends on TARGET_ARCH_X86_64
- help
- This is a general purpose type powered by 4th Generation
- AMD EPYC processors.
-
- See https://aws.amazon.com/ec2/instance-types/m7a/ for
- details.
-
-config TERRAFORM_AWS_INSTANCE_TYPE_I4I
- bool "I4i"
- depends on TARGET_ARCH_X86_64
- help
- This is a storage-optimized type powered by 3rd generation
- Intel Xeon Scalable processors (Ice Lake) and use AWS Nitro
- NVMe SSDs.
-
- See https://aws.amazon.com/ec2/instance-types/i4i/ for
- details.
-
-config TERRAFORM_AWS_INSTANCE_TYPE_IS4GEN
- bool "Is4gen"
- depends on TARGET_ARCH_ARM64
- help
- This is a Storage-optimized type powered by AWS Graviton2
- processors.
-
- See https://aws.amazon.com/ec2/instance-types/i4g/ for
- details.
-
-config TERRAFORM_AWS_INSTANCE_TYPE_IM4GN
- bool "Im4gn"
- depends on TARGET_ARCH_ARM64
- help
- This is a storage-optimized type powered by AWS Graviton2
- processors.
-
- See https://aws.amazon.com/ec2/instance-types/i4g/ for
- details.
-
-config TERRAFORM_AWS_INSTANCE_TYPE_C7A
- depends on TARGET_ARCH_X86_64
- bool "c7a"
- help
- This is a compute-optimized type powered by 4th generation
- AMD EPYC processors.
-
- See https://aws.amazon.com/ec2/instance-types/c7a/ for
- details.
-
-endchoice
-
-source "terraform/aws/kconfigs/instance-types/Kconfig.m5"
-source "terraform/aws/kconfigs/instance-types/Kconfig.m7a"
-source "terraform/aws/kconfigs/instance-types/Kconfig.i4i"
-source "terraform/aws/kconfigs/instance-types/Kconfig.is4gen"
-source "terraform/aws/kconfigs/instance-types/Kconfig.im4gn"
-source "terraform/aws/kconfigs/instance-types/Kconfig.c7a"
-
-choice
- prompt "Linux distribution"
- default TERRAFORM_AWS_DISTRO_DEBIAN
- help
- Select a popular Linux distribution to install on your
- instances, or use the "Custom AMI image" selection to
- choose an image that is off the beaten path.
-
-config TERRAFORM_AWS_DISTRO_AMAZON
- bool "Amazon Linux"
-
-config TERRAFORM_AWS_DISTRO_DEBIAN
- bool "Debian"
-
-config TERRAFORM_AWS_DISTRO_FEDORA
- bool "Fedora Core"
-
-config TERRAFORM_AWS_DISTRO_RHEL
- bool "Red Hat Enterprise Linux"
-
-config TERRAFORM_AWS_DISTRO_SLES
- bool "Suse Linux Enterprise Server"
-
-config TERRAFORM_AWS_DISTRO_CUSTOM
- bool "Custom AMI image"
-
-endchoice
-
-source "terraform/aws/kconfigs/distros/Kconfig.amazon"
-source "terraform/aws/kconfigs/distros/Kconfig.debian"
-source "terraform/aws/kconfigs/distros/Kconfig.fedora"
-source "terraform/aws/kconfigs/distros/Kconfig.rhel"
-source "terraform/aws/kconfigs/distros/Kconfig.sles"
-source "terraform/aws/kconfigs/distros/Kconfig.custom"
diff --git a/terraform/aws/kconfigs/Kconfig.location b/terraform/aws/kconfigs/Kconfig.location
deleted file mode 100644
index e5dacb9d..00000000
--- a/terraform/aws/kconfigs/Kconfig.location
+++ /dev/null
@@ -1,679 +0,0 @@
-choice
- prompt "AWS region"
- default TERRAFORM_AWS_REGION_US_WEST_2
- help
- Use this option to select the AWS region that hosts your
- compute and storage resources. If you do not explicitly
- specify a region, the US West (Oregon) region is the
- default.
-
- Once selected, you can stick with the default AV zone
- chosen by kdevops, or use:
-
- aws ec2 describe-availability-zones --region <region-name>
-
- to list the Availability Zones that are enabled for your
- AWS account. Enter your selection from this list using the
- TERRAFORM_AWS_AV_ZONE menu.
-
- If you wish to expand on the region list, send a patch after
- reading this list:
-
- https://docs.aws.amazon.com/general/latest/gr/rande.html
-
- Note that if you change region the AMI may change as well even
- for the same distribution. At least that applies to Amazon EC2
- optimized images. Use the AWS console, to set that up it will
- ask you for your credentials and then a region. Before adding
- an entry for ami image be sure you are on the region and then
- query with something like:
-
- aws ec2 describe-images --image-ids ami-0efa651876de2a5ce
-
- For instance, this AMI belongs to us-west-2 only. us-east* have
- other AMIs for the same Amazon 2023 EC2 image. The output from
- here tells me:
-
- "OwnerId": "137112412989"
-
- And that is what value to use for ami-0efa651876de2a5ce
- for the TERRAFORM_AWS_AMI_OWNER. To get the ami-* for your regions
- just go to your EC2 console, that console will be associated with
- a region already. You have to change regions if you want to look
- for AMIs in other regions. There are for example two different
- ami-* values for Amazon Linux 2023 for different regions. However
- they values can be same. For example below are the us-west-2 queries
- for Amazon Linux 2023 for x86_64 and then for ARM64.
-
- aws ec2 describe-images --image-ids ami-0efa651876de2a5ce | grep OwnerId
- "OwnerId": "137112412989",
- aws ec2 describe-images --image-ids ami-0699f753302dd8b00 | grep OwnerId
- "OwnerId": "137112412989",
-
-config TERRAFORM_AWS_REGION_AP_NORTHEAST_1
- bool "ap-northeast-1 - Tokyo"
- help
- This option specifies the Asia-Pacific northeast-1 region.
- The data center is located in Tokyo, Japan.
-
-config TERRAFORM_AWS_REGION_AP_NORTHEAST_2
- bool "ap-northeast-2 - Seoul"
- help
- This option specifies the Asia-Pacific northeast-2 region.
- The data center is located in Seoul, South Korea.
-
-config TERRAFORM_AWS_REGION_AP_NORTHEAST_3
- bool "ap-northeast-3 - Osaka"
- help
- This option specifies the Asia-Pacific northeast-3 region.
- The data center is located in Osaka, Japan.
-
-config TERRAFORM_AWS_REGION_AP_SOUTH_1
- bool "ap-south-1 - Mumbai"
- help
- This option specifies the Asia-Pacific south-1 region.
- The data center is located in Mumbai, India.
-
-config TERRAFORM_AWS_REGION_AP_SOUTHEAST_1
- bool "ap-southeast-1 - Singapore"
- help
- This option specifies the Asia-Pacific southeast-1 region.
- The data center is located in the Republic of Singapore.
-
-config TERRAFORM_AWS_REGION_AP_SOUTHEAST_2
- bool "ap-southeast-1 - Sydney"
- help
- This option specifies the Asia-Pacific southeast-2 region.
- The data center is located in Sydney, Australia.
-
-config TERRAFORM_AWS_REGION_CA_CENTRAL_1
- bool "ca-central-1 - Central"
- help
- This option specifies the Canada central-1 region.
- The data center is located in Montreal, Quebec.
-
-config TERRAFORM_AWS_REGION_EU_CENTRAL_1
- bool "eu-central-1 - Frankfurt"
- help
- This option specifies the European Union central-1 region.
- The data center is located in Frankfurt, Germany.
-
-config TERRAFORM_AWS_REGION_EU_NORTH_1
- bool "eu-north-1 - Stockholm"
- help
- This option specifies the European Union north-1 region.
- The data center is located in Stockholm, Sweden.
-
-config TERRAFORM_AWS_REGION_EU_WEST_1
- bool "eu-west-1 - Ireland"
- help
- This option specifies the European Union west-1 region.
- The data center is located in Dublin, Republic of Ireland.
-
-config TERRAFORM_AWS_REGION_EU_WEST_2
- bool "eu-west-2 - London"
- help
- This option specifies the European Union west-2 region.
- The data center is located in London, United Kingdom.
-
-config TERRAFORM_AWS_REGION_EU_WEST_3
- bool "eu-west-3 - Paris"
- help
- This option specifies the European Union west-3 region.
- The data center is located in Paris, France.
-
-config TERRAFORM_AWS_REGION_SA_EAST_1
- bool "sa-east-1 - Sao Paulo"
- help
- This option specifies the South America east-1 region.
- The data center is located in São Paulo, Brazil.
-
-config TERRAFORM_AWS_REGION_US_EAST_1
- bool "us-east-1 - N. Virginia"
- help
- This option specifies the United States east-1 region.
- Multiple data centers are located in the US state of
- Virginia.
-
-config TERRAFORM_AWS_REGION_US_EAST_2
- bool "us-east-2 - Ohio"
- help
- This option specifies the United States east-2 region.
- The data center is located in Columbus, Ohio, US.
-
-config TERRAFORM_AWS_REGION_US_WEST_1
- bool "us-west-1 - North California"
- help
- This option specifies the United States west-1 region.
- The data center is located in San Francisco, California,
- US.
-
-config TERRAFORM_AWS_REGION_US_WEST_2
- bool "us-west-2 - Oregon"
- help
- This option specifies the United States west-2 region.
- Multiple data centers are located in the US state of
- Oregon.
-
-endchoice
-
-config TERRAFORM_AWS_REGION
- string
- output yaml
- default "ap-northeast-1" if TERRAFORM_AWS_REGION_AP_NORTHEAST_1
- default "ap-northeast-2" if TERRAFORM_AWS_REGION_AP_NORTHEAST_2
- default "ap-northeast-3" if TERRAFORM_AWS_REGION_AP_NORTHEAST_3
- default "ap-south-1" if TERRAFORM_AWS_REGION_AP_SOUTH_1
- default "ap-southeast-1" if TERRAFORM_AWS_REGION_AP_SOUTHEAST_1
- default "ap-southeast-2" if TERRAFORM_AWS_REGION_AP_SOUTHEAST_2
- default "ca-central-1" if TERRAFORM_AWS_REGION_CA_CENTRAL_1
- default "eu-central-1" if TERRAFORM_AWS_REGION_EU_CENTRAL_1
- default "eu-north-1" if TERRAFORM_AWS_REGION_EU_NORTH_1
- default "eu-west-1" if TERRAFORM_AWS_REGION_EU_WEST_1
- default "eu-west-2" if TERRAFORM_AWS_REGION_EU_WEST_2
- default "eu-west-3" if TERRAFORM_AWS_REGION_EU_WEST_3
- default "sa-east-1" if TERRAFORM_AWS_REGION_SA_EAST_1
- default "us-east-1" if TERRAFORM_AWS_REGION_US_EAST_1
- default "us-east-2" if TERRAFORM_AWS_REGION_US_EAST_2
- default "us-west-1" if TERRAFORM_AWS_REGION_US_WEST_1
- default "us-west-2" if TERRAFORM_AWS_REGION_US_WEST_2
-
-if TERRAFORM_AWS_REGION_AP_NORTHEAST_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_1A
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_1A
- bool "ap-northeast-1a"
- help
- This option selects the ap-northeast-1a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_1C
- bool "ap-northeast-1c"
- help
- This option selects the ap-northeast-1c availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_1D
- bool "ap-northeast-1d"
- help
- This option selects the ap-northeast-1d availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_AP_NORTHEAST_1
-
-if TERRAFORM_AWS_REGION_AP_NORTHEAST_2
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_2A
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_2A
- bool "ap-northeast-2a"
- help
- This option selects the ap-northeast-2a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_2B
- bool "ap-northeast-2b"
- help
- This option selects the ap-northeast-2b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_2C
- bool "ap-northeast-2c"
- help
- This option selects the ap-northeast-2c availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_2D
- bool "ap-northeast-2d"
- help
- This option selects the ap-northeast-2d availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_AP_NORTHEAST_2
-
-if TERRAFORM_AWS_REGION_AP_NORTHEAST_3
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_3A
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_3A
- bool "ap-northeast-3a"
- help
- This option selects the ap-northeast-3a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_3B
- bool "ap-northeast-3b"
- help
- This option selects the ap-northeast-3b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_3C
- bool "ap-northeast-3c"
- help
- This option selects the ap-northeast-3c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_AP_NORTHEAST_3
-
-if TERRAFORM_AWS_REGION_AP_SOUTH_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_AP_SOUTH_1A
-
-config TERRAFORM_AWS_AV_ZONE_AP_SOUTH_1A
- bool "ap-south-1a"
- help
- This option selects the ap-south-1a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_SOUTH_1B
- bool "ap-south-1b"
- help
- This option selects the ap-south-1b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_SOUTH_1C
- bool "ap-south-1c"
- help
- This option selects the ap-south-1c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_AP_SOUTH_1
-
-if TERRAFORM_AWS_REGION_AP_SOUTHEAST_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_1A
-
-config TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_1A
- bool "ap-southeast-1a"
- help
- This option selects the ap-southeast-1a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_1B
- bool "ap-southeast-1b"
- help
- This option selects the ap-southeast-1b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_1C
- bool "ap-southeast-1c"
- help
- This option selects the ap-southeast-1c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_AP_SOUTHEAST_1
-
-if TERRAFORM_AWS_REGION_AP_SOUTHEAST_2
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_2A
-
-config TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_2A
- bool "ap-southeast-2a"
- help
- This option selects the ap-southeast-2a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_2B
- bool "ap-southeast-2b"
- help
- This option selects the ap-southeast-2b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_2C
- bool "ap-southeast-2c"
- help
- This option selects the ap-southeast-2c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_AP_SOUTHEAST_2
-
-if TERRAFORM_AWS_REGION_CA_CENTRAL_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_CA_CENTRAL_1A
-
-config TERRAFORM_AWS_AV_ZONE_CA_CENTRAL_1A
- bool "ca-central-1a"
- help
- This option selects the ca-central-1a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_CA_CENTRAL_1B
- bool "ca-central-1b"
- help
- This option selects the ca-central-1b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_CA_CENTRAL_1D
- bool "ca-central-1d"
- help
- This option selects the ca-central-1d availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_CA_CENTRAL_1
-
-if TERRAFORM_AWS_REGION_EU_CENTRAL_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_EU_CENTRAL_1A
-
-config TERRAFORM_AWS_AV_ZONE_EU_CENTRAL_1A
- bool "eu-central-1a"
- help
- This option selects the eu-central-1a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_CENTRAL_1B
- bool "eu-central-1b"
- help
- This option selects the eu-central-1b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_CENTRAL_1C
- bool "eu-central-1c"
- help
- This option selects the eu-central-1c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_EU_CENTRAL_1
-
-if TERRAFORM_AWS_REGION_EU_NORTH_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_EU_NORTH_1A
-
-config TERRAFORM_AWS_AV_ZONE_EU_NORTH_1A
- bool "eu-north-1a"
- help
- This option selects the eu-north-1a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_NORTH_1B
- bool "eu-north-1b"
- help
- This option selects the eu-north-1b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_NORTH_1C
- bool "eu-north-1c"
- help
- This option selects the eu-north-1c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_EU_NORTH_1
-
-if TERRAFORM_AWS_REGION_EU_WEST_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_EU_WEST_1A
-
-config TERRAFORM_AWS_AV_ZONE_EU_WEST_1A
- bool "eu-west-1a"
- help
- This option selects the eu-west-1a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_WEST_1B
- bool "eu-west-1b"
- help
- This option selects the eu-west-1b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_WEST_1C
- bool "eu-west-1c"
- help
- This option selects the eu-west-1c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_EU_WEST_1
-
-if TERRAFORM_AWS_REGION_EU_WEST_2
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_EU_WEST_2A
-
-config TERRAFORM_AWS_AV_ZONE_EU_WEST_2A
- bool "eu-west-2a"
- help
- This option selects the eu-west-2a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_WEST_2B
- bool "eu-west-2b"
- help
- This option selects the eu-west-2b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_WEST_2C
- bool "eu-west-2c"
- help
- This option selects the eu-west-2c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_EU_WEST_2
-
-if TERRAFORM_AWS_REGION_EU_WEST_3
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_EU_WEST_3A
-
-config TERRAFORM_AWS_AV_ZONE_EU_WEST_3A
- bool "eu-west-3a"
- help
- This option selects the eu-west-3a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_WEST_3B
- bool "eu-west-3b"
- help
- This option selects the eu-west-3b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_EU_WEST_3C
- bool "eu-west-3c"
- help
- This option selects the eu-west-3c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_EU_WEST_3
-
-if TERRAFORM_AWS_REGION_SA_EAST_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_SA_EAST_1A
-
-config TERRAFORM_AWS_AV_ZONE_SA_EAST_1A
- bool "sa-east-1a"
- help
- This option selects the sa-east-1a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_SA_EAST_1B
- bool "sa-east-1b"
- help
- This option selects the sa-east-1b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_SA_EAST_1C
- bool "sa-east-1c"
- help
- This option selects the sa-east-1c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_SA_EAST_1
-
-if TERRAFORM_AWS_REGION_US_EAST_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_US_EAST_1A
-
-config TERRAFORM_AWS_AV_ZONE_US_EAST_1A
- bool "us-east-1a"
- help
- This option selects the us-east-1a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_US_EAST_1B
- bool "us-east-1b"
- help
- This option selects the us-east-1b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_US_EAST_1C
- bool "us-east-1c"
- help
- This option selects the us-east-1c availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_US_EAST_1D
- bool "us-east-1d"
- help
- This option selects the us-east-1d availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_US_EAST_1E
- bool "us-east-1e"
- help
- This option selects the us-east-1e availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_US_EAST_1F
- bool "us-east-1f"
- help
- This option selects the us-east-1f availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_US_EAST_1
-
-if TERRAFORM_AWS_REGION_US_EAST_2
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_US_EAST_2A
-
-config TERRAFORM_AWS_AV_ZONE_US_EAST_2A
- bool "us-east-2a"
- help
- This option selects the us-east-2a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_US_EAST_2B
- bool "us-east-2b"
- help
- This option selects the us-east-2a availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_US_EAST_2C
- bool "us-east-2c"
- help
- This option selects the us-east-2c availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_US_EAST_2
-
-if TERRAFORM_AWS_REGION_US_WEST_1
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_US_WEST_1B
- help
- This option sets the AWS availablity zone to the specified value.
- If you wish to expand on this list send a patch after reading this
- list:
-
- https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html
- https://gist.github.com/neilstuartcraig/0ccefcf0887f29b7f240
-
-config TERRAFORM_AWS_AV_ZONE_US_WEST_1B
- bool "us-west-1b"
- help
- This option selects the us-west-1b availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_US_WEST_1
-
-if TERRAFORM_AWS_REGION_US_WEST_2
-
-choice
- prompt "AWS availability zone"
- default TERRAFORM_AWS_AV_ZONE_US_WEST_2B
- help
- This option sets the AWS availablity zone to the specified value.
- If you wish to expand on this list send a patch after reading this
- list:
-
- https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html
- https://gist.github.com/neilstuartcraig/0ccefcf0887f29b7f240
-
-config TERRAFORM_AWS_AV_ZONE_US_WEST_2B
- bool "us-west-2b"
- help
- This option selects the us-west-2b availability zone.
-
-config TERRAFORM_AWS_AV_ZONE_US_WEST_2D
- bool "us-west-2d"
- help
- This option selects the us-west-2d availability zone.
-
-endchoice
-
-endif # TERRAFORM_AWS_REGION_US_WEST_2
-
-config TERRAFORM_AWS_AV_ZONE
- string
- output yaml
- default "ap-northeast-1a" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_1A
- default "ap-northeast-1c" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_1C
- default "ap-northeast-1d" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_1D
- default "ap-northeast-2a" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_2A
- default "ap-northeast-2b" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_2B
- default "ap-northeast-2c" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_2C
- default "ap-northeast-2d" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_2D
- default "ap-northeast-3a" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_3A
- default "ap-northeast-3b" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_3B
- default "ap-northeast-3c" if TERRAFORM_AWS_AV_ZONE_AP_NORTHEAST_3C
- default "ap-south-1a" if TERRAFORM_AWS_AV_ZONE_AP_SOUTH_1A
- default "ap-south-1b" if TERRAFORM_AWS_AV_ZONE_AP_SOUTH_1B
- default "ap-south-1c" if TERRAFORM_AWS_AV_ZONE_AP_SOUTH_1C
- default "ap-southeast-1a" if TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_1A
- default "ap-southeast-1b" if TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_1B
- default "ap-southeast-1c" if TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_1C
- default "ap-southeast-2a" if TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_2A
- default "ap-southeast-2b" if TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_2B
- default "ap-southeast-2c" if TERRAFORM_AWS_AV_ZONE_AP_SOUTHEAST_2C
- default "ca-central-1a" if TERRAFORM_AWS_AV_ZONE_CA_CENTRAL_1A
- default "ca-central-1b" if TERRAFORM_AWS_AV_ZONE_CA_CENTRAL_1B
- default "ca-central-1d" if TERRAFORM_AWS_AV_ZONE_CA_CENTRAL_1D
- default "eu-central-1a" if TERRAFORM_AWS_AV_ZONE_EU_CENTRAL_1A
- default "eu-central-1b" if TERRAFORM_AWS_AV_ZONE_EU_CENTRAL_1B
- default "eu-central-1c" if TERRAFORM_AWS_AV_ZONE_EU_CENTRAL_1C
- default "eu-north-1a" if TERRAFORM_AWS_AV_ZONE_EU_NORTH_1A
- default "eu-north-1b" if TERRAFORM_AWS_AV_ZONE_EU_NORTH_1B
- default "eu-north-1c" if TERRAFORM_AWS_AV_ZONE_EU_NORTH_1C
- default "eu-west-1a" if TERRAFORM_AWS_AV_ZONE_EU_WEST_1A
- default "eu-west-1b" if TERRAFORM_AWS_AV_ZONE_EU_WEST_1B
- default "eu-west-1c" if TERRAFORM_AWS_AV_ZONE_EU_WEST_1C
- default "eu-west-2a" if TERRAFORM_AWS_AV_ZONE_EU_WEST_2A
- default "eu-west-2b" if TERRAFORM_AWS_AV_ZONE_EU_WEST_2B
- default "eu-west-2c" if TERRAFORM_AWS_AV_ZONE_EU_WEST_2C
- default "eu-west-3a" if TERRAFORM_AWS_AV_ZONE_EU_WEST_3A
- default "eu-west-3b" if TERRAFORM_AWS_AV_ZONE_EU_WEST_3B
- default "eu-west-3c" if TERRAFORM_AWS_AV_ZONE_EU_WEST_3C
- default "sa-east-1a" if TERRAFORM_AWS_AV_ZONE_SA_EAST_1A
- default "sa-east-1b" if TERRAFORM_AWS_AV_ZONE_SA_EAST_1B
- default "sa-east-1c" if TERRAFORM_AWS_AV_ZONE_SA_EAST_1C
- default "us-east-1a" if TERRAFORM_AWS_AV_ZONE_US_EAST_1A
- default "us-east-1b" if TERRAFORM_AWS_AV_ZONE_US_EAST_1B
- default "us-east-1c" if TERRAFORM_AWS_AV_ZONE_US_EAST_1C
- default "us-east-1d" if TERRAFORM_AWS_AV_ZONE_US_EAST_1D
- default "us-east-1e" if TERRAFORM_AWS_AV_ZONE_US_EAST_1E
- default "us-east-1f" if TERRAFORM_AWS_AV_ZONE_US_EAST_1F
- default "us-east-2a" if TERRAFORM_AWS_AV_ZONE_US_EAST_2A
- default "us-east-2b" if TERRAFORM_AWS_AV_ZONE_US_EAST_2B
- default "us-east-2c" if TERRAFORM_AWS_AV_ZONE_US_EAST_2C
- default "us-west-1b" if TERRAFORM_AWS_AV_ZONE_US_WEST_1B
- default "us-west-2b" if TERRAFORM_AWS_AV_ZONE_US_WEST_2B
- default "us-west-2d" if TERRAFORM_AWS_AV_ZONE_US_WEST_2D
diff --git a/terraform/aws/kconfigs/instance-types/Kconfig.c7a b/terraform/aws/kconfigs/instance-types/Kconfig.c7a
deleted file mode 100644
index 147999d9..00000000
--- a/terraform/aws/kconfigs/instance-types/Kconfig.c7a
+++ /dev/null
@@ -1,28 +0,0 @@
-if TERRAFORM_AWS_INSTANCE_TYPE_C7A
-
-choice
- prompt "AWS instance size"
- default TERRAFORM_AWS_INSTANCE_SIZE_C7A_8XLARGE
- help
- Add storage by increasing the number of EBS volumes per
- instance.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_C7A_8XLARGE
- bool "c7a.8xlarge"
- help
- 32 core, 64 GiB RAM, EBS drives.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_C7A_METAL_48XL
- bool "c7a.metal-48xl"
- help
- 192 core, 384 GiB RAM, EBS drive.
-
-endchoice
-
-config TERRAFORM_AWS_INSTANCE_TYPE
- string
- output yaml
- default "c7a.8xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_C7A_8XLARGE
- default "c7a.metal-48xl" if TERRAFORM_AWS_INSTANCE_SIZE_C7A_METAL_48XL
-
-endif # TERRAFORM_AWS_INSTANCE_TYPE_C7A
diff --git a/terraform/aws/kconfigs/instance-types/Kconfig.i4i b/terraform/aws/kconfigs/instance-types/Kconfig.i4i
deleted file mode 100644
index 3f7b2218..00000000
--- a/terraform/aws/kconfigs/instance-types/Kconfig.i4i
+++ /dev/null
@@ -1,33 +0,0 @@
-if TERRAFORM_AWS_INSTANCE_TYPE_I4I
-
-choice
- prompt "AWS instance type"
- default TERRAFORM_AWS_INSTANCE_SIZE_I4I_4XLARGE
-
-config TERRAFORM_AWS_INSTANCE_SIZE_I4I_LARGE
- bool "i4i.large"
- help
- 16 GiB RAM, 2 vcpus, 1 x 468 AWS Nitro SSD, 10 Gbps Net, 10 Gbps EBS.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_I4I_4XLARGE
- bool "i4i.4xlarge"
- help
- 128 GiB RAM, 16 vcpus, 1 x 3,750 AWS Nitro SSD, 25 Gbps Net,
- 10 Gbps EBS.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_I4I_METAL
- bool "i4i.metal"
- help
- 1024 GiB RAM, 128 real cpus?, 8 x 3,750 AWS Nitro SSD,
- 75 Gbps Net, 40 Gbps EBS. The bees' knees I guess.
-
-endchoice
-
-config TERRAFORM_AWS_INSTANCE_TYPE
- string
- output yaml
- default "i4i.large" if TERRAFORM_AWS_INSTANCE_SIZE_I4I_LARGE
- default "i4i.4xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_I4I_4XLARGE
- default "i4i.metal" if TERRAFORM_AWS_INSTANCE_SIZE_I4I_METAL
-
-endif # TERRAFORM_AWS_INSTANCE_TYPE_I4I
diff --git a/terraform/aws/kconfigs/instance-types/Kconfig.im4gn b/terraform/aws/kconfigs/instance-types/Kconfig.im4gn
deleted file mode 100644
index e224bdca..00000000
--- a/terraform/aws/kconfigs/instance-types/Kconfig.im4gn
+++ /dev/null
@@ -1,25 +0,0 @@
-if TERRAFORM_AWS_INSTANCE_TYPE_IM4GN
-
-choice
- prompt "AWS instance size"
- default TERRAFORM_AWS_INSTANCE_SIZE_IM4GN_LARGE
-
-config TERRAFORM_AWS_INSTANCE_SIZE_IM4GN_LARGE
- bool "im4gn.large"
- help
- 8 GiB RAM, 2vCPUs, 1 x 937 GiB NVMe SSD, 25 Gbps Net, 9.5 Gbps EBS.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_IM4GN_4XLARGE
- bool "im4gn.4xlarge"
- help
- 64 GiB RAM, 16 vcpus, 1 x 7500 NVMe SSD, 25 Gbps Net, 9.5 Gbps EBS.
-
-endchoice
-
-config TERRAFORM_AWS_INSTANCE_TYPE
- string
- output yaml
- default "im4gn.large" if TERRAFORM_AWS_INSTANCE_SIZE_IM4GN_LARGE
- default "im4gn.4xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_IM4GN_4XLARGE
-
-endif # TERRAFORM_AWS_INSTANCE_TYPE_IM4GN
diff --git a/terraform/aws/kconfigs/instance-types/Kconfig.is4gen b/terraform/aws/kconfigs/instance-types/Kconfig.is4gen
deleted file mode 100644
index 4fdca17b..00000000
--- a/terraform/aws/kconfigs/instance-types/Kconfig.is4gen
+++ /dev/null
@@ -1,25 +0,0 @@
-if TERRAFORM_AWS_INSTANCE_TYPE_IS4GEN
-
-choice
- prompt "AWS instance size"
- default TERRAFORM_AWS_INSTANCE_SIZE_IS4GEN_MEDIUM
-
-config TERRAFORM_AWS_INSTANCE_SIZE_IS4GEN_MEDIUM
- bool "is4gen.medium"
- help
- 6 GiB RAM, 1vCPU, 1 x 937 GiB NVMe SSD, 25 Gbps Net, 9.6 Gbps EBS.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_IS4GEN_8XLARGE
- bool "is4gen.8xlarge"
- help
- 192 GiB RAM, 32 vCPUs, 4 x 7500 NVMe SSD, 50 Gbps Net, 19 Gbps EBS.
-
-endchoice
-
-config TERRAFORM_AWS_INSTANCE_TYPE
- string
- output yaml
- default "is4gen.medium" if TERRAFORM_AWS_INSTANCE_SIZE_IS4GEN_MEDIUM
- default "is4gen.8xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_IS4GEN_8XLARGE
-
-endif # TERRAFORM_AWS_INSTANCE_TYPE_IS4GEN
diff --git a/terraform/aws/kconfigs/instance-types/Kconfig.m5 b/terraform/aws/kconfigs/instance-types/Kconfig.m5
deleted file mode 100644
index 534a20e7..00000000
--- a/terraform/aws/kconfigs/instance-types/Kconfig.m5
+++ /dev/null
@@ -1,48 +0,0 @@
-if TERRAFORM_AWS_INSTANCE_TYPE_M5
-
-choice
- prompt "AWS instance type"
- default TERRAFORM_AWS_INSTANCE_SIZE_M5AD_4XLARGE
- help
- Add storage by increasing the number of EBS volumes per
- instance.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_M5AD_LARGE
- bool "m5ad.large"
- depends on TARGET_ARCH_X86_64
- help
- 8 GiB RAM, 2 AMD vcpus, 1 10 GiB main drive, up to 10 Gbps
- network speed, and one 75 GiB NVMe drive.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_M5AD_XLARGE
- bool "m5ad.xlarge"
- depends on TARGET_ARCH_X86_64
- help
- 16 GiB RAM, 4 AMD vcpus, 1 10 GiB main drive, up to 10 Gbps
- network speed, and one 150 GiB NVMe drive.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_M5AD_2XLARGE
- bool "m5ad.2xlarge"
- depends on TARGET_ARCH_X86_64
- help
- 32 GiB RAM, 8 AMD vcpus, 1 10 GiB main drive, up to 10 Gbps
- network speed, and one 300 GiB NVMe drive.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_M5AD_4XLARGE
- bool "m5ad.4xlarge"
- depends on TARGET_ARCH_X86_64
- help
- 64 GiB RAM, 16 AMD vcpus, 1 10 GiB main drive, up to 10 Gbps
- and two 300 GiB NVMe drives.
-
-endchoice
-
-config TERRAFORM_AWS_INSTANCE_TYPE
- string
- output yaml
- default "m5ad.large" if TERRAFORM_AWS_INSTANCE_SIZE_M5AD_LARGE
- default "m5ad.xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_M5AD_XLARGE
- default "m5ad.2xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_M5AD_2XLARGE
- default "m5ad.4xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_M5AD_4XLARGE
-
-endif # TERRAFORM_AWS_INSTANCE_TYPE_M5
diff --git a/terraform/aws/kconfigs/instance-types/Kconfig.m7a b/terraform/aws/kconfigs/instance-types/Kconfig.m7a
deleted file mode 100644
index fd7bd6f4..00000000
--- a/terraform/aws/kconfigs/instance-types/Kconfig.m7a
+++ /dev/null
@@ -1,57 +0,0 @@
-if TERRAFORM_AWS_INSTANCE_TYPE_M7A
-
-choice
- prompt "AWS instance type"
- default TERRAFORM_AWS_INSTANCE_SIZE_M7A_XLARGE
- help
- Add storage by increasing the number of EBS volumes per
- instance.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_M7A_MEDIUM
- bool "m7a.medium"
- depends on TARGET_ARCH_X86_64
- help
- 4 GiB RAM, 1 AMD Ryzen vcpu, 1 10 GiB main drive, and up to
- 12.5 Gbs network speed.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_M7A_LARGE
- bool "m7a.large"
- depends on TARGET_ARCH_X86_64
- help
- 8 GiB RAM, 2 AMD Ryzen vcpus, 1 10 GiB main drive, and up to
- 12.5 Gbs network speed.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_M7A_XLARGE
- bool "m7a.xlarge"
- depends on TARGET_ARCH_X86_64
- help
- 16 GiB RAM, 4 AMD Ryzen vcpus, 1 10 GiB main drive, and up to
- 12.5 Gbs network speed.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_M7A_2XLARGE
- bool "m7a.2xlarge"
- depends on TARGET_ARCH_X86_64
- help
- 32 GiB RAM, 8 AMD Ryzen vcpus, 1 10 GiB main drive, and up to
- 12.5 Gbs network speed.
-
-config TERRAFORM_AWS_INSTANCE_SIZE_M7A_4XLARGE
- bool "m7a.4xlarge"
- depends on TARGET_ARCH_X86_64
- help
- 64 GiB RAM, 16 AMD Ryzen vcpus, 1 10 GiB main drive, and up to
- 12.5 Gbs network speed.
-
-endchoice
-
-config TERRAFORM_AWS_INSTANCE_TYPE
- string
- output yaml
- default "m7a.medium" if TERRAFORM_AWS_INSTANCE_SIZE_M7A_MEDIUM
- default "m7a.large" if TERRAFORM_AWS_INSTANCE_SIZE_M7A_LARGE
- default "m7a.xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_M7A_XLARGE
- default "m7a.xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_M7A_XLARGE
- default "m7a.2xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_M7A_2XLARGE
- default "m7a.4xlarge" if TERRAFORM_AWS_INSTANCE_SIZE_M7A_4XLARGE
-
-endif # TERRAFORM_AWS_INSTANCE_TYPE_M7A
diff --git a/terraform/aws/scripts/generate_aws_kconfig.py b/terraform/aws/scripts/generate_aws_kconfig.py
index c6a60a83..a8f25b4e 100755
--- a/terraform/aws/scripts/generate_aws_kconfig.py
+++ b/terraform/aws/scripts/generate_aws_kconfig.py
@@ -221,8 +221,19 @@ def generate_family_kconfig(family: str, instances: List[Dict]) -> str:
"""Generate Kconfig content for a single family."""
content = [f"# AWS {family.upper()} instance sizes (dynamically generated)", ""]
+ # Filter instances to only include the exact family (not related families)
+ # e.g., for "r8g" family, exclude "r8gd" and "r8gn" instances
+ filtered_instances = [
+ inst for inst in instances
+ if inst['instance_type'].split('.')[0] == family
+ ]
+
+ if not filtered_instances:
+ # If no exact matches, use all instances (backward compatibility)
+ filtered_instances = instances
+
# Sort instances by a logical order
- sorted_instances = sorted(instances, key=lambda x: (
+ sorted_instances = sorted(filtered_instances, key=lambda x: (
'metal' not in x['instance_type'], # metal instances last
x.get('vcpus', 0), # then by vCPUs
x.get('memory_gb', 0) # then by memory
@@ -238,14 +249,15 @@ def generate_family_kconfig(family: str, instances: List[Dict]) -> str:
# Generate choice block
content.append("choice")
content.append(f'\tprompt "Instance size for {family.upper()} family"')
- content.append(f'\tdefault TERRAFORM_AWS_INSTANCE_{default.replace(".", "_").upper()}')
+ content.append(f'\tdefault TERRAFORM_AWS_INSTANCE_{default.replace(".", "_").replace("-", "_").upper()}')
content.append("\thelp")
content.append(f"\t Select the specific instance size within the {family.upper()} family.")
content.append("")
# Generate config entries
for inst in sorted_instances:
- type_upper = inst['instance_type'].replace('.', '_').upper()
+ # Replace both dots and dashes with underscores for valid Kconfig symbols
+ type_upper = inst['instance_type'].replace('.', '_').replace('-', '_').upper()
content.append(f"config TERRAFORM_AWS_INSTANCE_{type_upper}")
content.append(f'\tbool "{inst["instance_type"]}"')
content.append("\thelp")
@@ -262,7 +274,7 @@ def generate_family_kconfig(family: str, instances: List[Dict]) -> str:
content.append("\tstring")
for inst in sorted_instances:
- type_upper = inst['instance_type'].replace('.', '_').upper()
+ type_upper = inst['instance_type'].replace('.', '_').replace('-', '_').upper()
content.append(f'\tdefault "{inst["instance_type"]}" if TERRAFORM_AWS_INSTANCE_{type_upper}')
content.append(f'\tdefault "{default}"')
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread