From be222bc88d3ac9ab2c68de7c4645af4d69aa0e44 Mon Sep 17 00:00:00 2001 From: Michael Wunderlich Date: Tue, 14 Apr 2026 16:35:01 +0000 Subject: [PATCH 1/4] Add networking tutorials (batch 19) --- tuts/117-elastic-load-balancing-gs/README.md | 61 ++++++++ .../elastic-load-balancing-gs.md | 142 ++++++++++++++++++ .../elastic-load-balancing-gs.sh | 112 ++++++++++++++ tuts/143-aws-transfer-gs/aws-transfer-gs.sh | 18 +++ tuts/144-aws-datasync-gs/aws-datasync-gs.sh | 12 ++ .../aws-globalaccelerator-gs.sh | 18 +++ tuts/158-vpc-endpoints/vpc-endpoints.sh | 19 +++ 7 files changed, 382 insertions(+) create mode 100644 tuts/117-elastic-load-balancing-gs/README.md create mode 100644 tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.md create mode 100644 tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.sh create mode 100644 tuts/143-aws-transfer-gs/aws-transfer-gs.sh create mode 100644 tuts/144-aws-datasync-gs/aws-datasync-gs.sh create mode 100644 tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh create mode 100644 tuts/158-vpc-endpoints/vpc-endpoints.sh diff --git a/tuts/117-elastic-load-balancing-gs/README.md b/tuts/117-elastic-load-balancing-gs/README.md new file mode 100644 index 00000000..de37202b --- /dev/null +++ b/tuts/117-elastic-load-balancing-gs/README.md @@ -0,0 +1,61 @@ +# ELB: Create an Application Load Balancer + +Create an Application Load Balancer with a security group, target group, and HTTP listener using the default VPC. + +## Source + +https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancer-getting-started.html + +## Use case + +- **ID**: elbv2/getting-started +- **Level**: intermediate +- **Core actions**: `elbv2:CreateLoadBalancer`, `elbv2:CreateListener`, `elbv2:CreateTargetGroup` + +## Steps + +1. Get VPC and subnets +2. Create a security group +3. Create a target group +4. Create the Application Load Balancer +5. Wait for ALB to be active +6. Create an HTTP listener +7. Describe the ALB + +## Resources created + +| Resource | Type | +|----------|------| +| `tut-alb-` | Application Load Balancer | +| `tut-tg-` | Target group | +| `tut-alb-sg-` | Security group | +| HTTP listener on port 80 | Listener | + +## Duration + +~121 seconds (most time spent waiting for ALB provisioning) + +## Cost + +~$0.02/hr while the ALB is running. Clean up promptly to avoid charges. + +## Related docs + +- [Getting started with Application Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancer-getting-started.html) +- [Create an Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html) +- [Target groups for ALBs](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html) +- [Elastic Load Balancing pricing](https://aws.amazon.com/elasticloadbalancing/pricing/) + +--- + +## Appendix + +| Field | Value | +|-------|-------| +| Date | 2026-04-14 | +| Script lines | 112 | +| Exit code | 0 | +| Runtime | 121s | +| Steps | 7 | +| Issues | None | +| Version | v1 | diff --git a/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.md b/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.md new file mode 100644 index 00000000..0188a68f --- /dev/null +++ b/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.md @@ -0,0 +1,142 @@ +# Create an Application Load Balancer with Elastic Load Balancing + +## Overview + +In this tutorial, you use the AWS CLI to create an Application Load Balancer (ALB) in your default VPC. You create a security group, target group, and HTTP listener, then verify the ALB is active. You then delete all resources during cleanup. + +## Prerequisites + +- AWS CLI installed and configured with appropriate permissions. +- A default VPC with at least two subnets in different Availability Zones. +- An IAM principal with permissions for `elbv2:CreateLoadBalancer`, `elbv2:CreateTargetGroup`, `elbv2:CreateListener`, `elbv2:DescribeLoadBalancers`, `elbv2:DeleteLoadBalancer`, `elbv2:DeleteTargetGroup`, `elbv2:DeleteListener`, `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`, `ec2:DeleteSecurityGroup`, `ec2:DescribeVpcs`, and `ec2:DescribeSubnets`. + +## Step 1: Get VPC and subnets + +Identify the default VPC and select two subnets for the ALB. An ALB requires subnets in at least two Availability Zones. + +```bash +VPC_ID=$(aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" \ + --query 'Vpcs[0].VpcId' --output text) + +SUBNETS=$(aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPC_ID" \ + --query 'Subnets[:2].SubnetId' --output text) +SUBNET1=$(echo "$SUBNETS" | awk '{print $1}') +SUBNET2=$(echo "$SUBNETS" | awk '{print $2}') +echo "VPC: $VPC_ID Subnets: $SUBNET1, $SUBNET2" +``` + +## Step 2: Create a security group + +Create a security group that allows inbound HTTP traffic on port 80. + +```bash +RANDOM_ID=$(openssl rand -hex 4) + +SG_ID=$(aws ec2 create-security-group --group-name "tut-alb-sg-${RANDOM_ID}" \ + --description "Tutorial ALB security group" --vpc-id "$VPC_ID" \ + --query 'GroupId' --output text) + +aws ec2 authorize-security-group-ingress --group-id "$SG_ID" \ + --protocol tcp --port 80 --cidr 0.0.0.0/0 > /dev/null +echo "Security group: $SG_ID" +``` + +This rule allows HTTP traffic from any source. In production, restrict the CIDR to known IP ranges. + +## Step 3: Create a target group + +Create an IP-based target group. The ALB forwards traffic to targets registered in this group. + +```bash +TG_NAME="tut-tg-${RANDOM_ID}" + +TG_ARN=$(aws elbv2 create-target-group --name "$TG_NAME" \ + --protocol HTTP --port 80 --vpc-id "$VPC_ID" \ + --target-type ip \ + --query 'TargetGroups[0].TargetGroupArn' --output text) +echo "Target group: $TG_ARN" +``` + +Target type `ip` lets you register IP addresses directly. Use `instance` to register EC2 instances by ID instead. + +## Step 4: Create the Application Load Balancer + +Create the ALB across the two subnets with the security group attached. + +```bash +ALB_NAME="tut-alb-${RANDOM_ID}" + +ALB_ARN=$(aws elbv2 create-load-balancer --name "$ALB_NAME" \ + --subnets $SUBNET1 $SUBNET2 \ + --security-groups "$SG_ID" \ + --query 'LoadBalancers[0].LoadBalancerArn' --output text) +echo "ALB ARN: $ALB_ARN" +``` + +## Step 5: Wait for ALB to be active + +The ALB takes 1–2 minutes to provision. Wait for it to reach the `active` state. + +```bash +aws elbv2 wait load-balancer-available --load-balancer-arns "$ALB_ARN" + +DNS_NAME=$(aws elbv2 describe-load-balancers --load-balancer-arns "$ALB_ARN" \ + --query 'LoadBalancers[0].DNSName' --output text) +echo "DNS: $DNS_NAME" +``` + +The DNS name is publicly resolvable. Without registered targets, requests to this DNS return a 503 error. + +## Step 6: Create an HTTP listener + +Create a listener on port 80 that forwards traffic to the target group. + +```bash +LISTENER_ARN=$(aws elbv2 create-listener --load-balancer-arn "$ALB_ARN" \ + --protocol HTTP --port 80 \ + --default-actions "Type=forward,TargetGroupArn=$TG_ARN" \ + --query 'Listeners[0].ListenerArn' --output text) +echo "Listener: $LISTENER_ARN" +``` + +The default action forwards all requests to the target group. You can add rules to route requests based on path or host header. + +## Step 7: Describe the ALB + +View the ALB configuration. + +```bash +aws elbv2 describe-load-balancers --load-balancer-arns "$ALB_ARN" \ + --query 'LoadBalancers[0].{Name:LoadBalancerName,DNS:DNSName,State:State.Code,Type:Type}' \ + --output table +``` + +## Cleanup + +Delete resources in reverse order. The ALB must be fully deleted before you can remove the target group. + +```bash +aws elbv2 delete-listener --listener-arn "$LISTENER_ARN" +aws elbv2 delete-load-balancer --load-balancer-arn "$ALB_ARN" + +echo "Waiting for ALB deletion..." +aws elbv2 wait load-balancers-deleted --load-balancer-arns "$ALB_ARN" + +aws elbv2 delete-target-group --target-group-arn "$TG_ARN" +aws ec2 delete-security-group --group-id "$SG_ID" +``` + +ALBs incur hourly charges (~$0.02/hr) plus data processing fees. Clean up promptly to avoid costs. + +The script automates all steps including cleanup: + +```bash +bash elastic-load-balancing-gs.sh +``` + +## Related resources + +- [Getting started with Application Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancer-getting-started.html) +- [Create an Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html) +- [Target groups for ALBs](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html) +- [Elastic Load Balancing pricing](https://aws.amazon.com/elasticloadbalancing/pricing/) diff --git a/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.sh b/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.sh new file mode 100644 index 00000000..2b34739b --- /dev/null +++ b/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.sh @@ -0,0 +1,112 @@ +#!/bin/bash +# Tutorial: Create an Application Load Balancer +# Source: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancer-getting-started.html + +WORK_DIR=$(mktemp -d) +LOG_FILE="$WORK_DIR/elbv2-$(date +%Y%m%d-%H%M%S).log" +exec > >(tee -a "$LOG_FILE") 2>&1 + +REGION=${AWS_DEFAULT_REGION:-${AWS_REGION:-$(aws configure get region 2>/dev/null)}} +if [ -z "$REGION" ]; then + echo "ERROR: No AWS region configured. Set one with: export AWS_DEFAULT_REGION=us-east-1" + exit 1 +fi +export AWS_DEFAULT_REGION="$REGION" +echo "Region: $REGION" + +RANDOM_ID=$(openssl rand -hex 4) +ALB_NAME="tut-alb-${RANDOM_ID}" +TG_NAME="tut-tg-${RANDOM_ID}" + +handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; } +trap 'handle_error $LINENO' ERR + +cleanup() { + echo "" + echo "Cleaning up resources..." + [ -n "$LISTENER_ARN" ] && aws elbv2 delete-listener --listener-arn "$LISTENER_ARN" 2>/dev/null && echo " Deleted listener" + [ -n "$ALB_ARN" ] && aws elbv2 delete-load-balancer --load-balancer-arn "$ALB_ARN" 2>/dev/null && echo " Deleted ALB $ALB_NAME" + # Wait for ALB to be deleted before deleting TG + if [ -n "$ALB_ARN" ]; then + echo " Waiting for ALB deletion..." + aws elbv2 wait load-balancers-deleted --load-balancer-arns "$ALB_ARN" 2>/dev/null || sleep 30 + fi + [ -n "$TG_ARN" ] && aws elbv2 delete-target-group --target-group-arn "$TG_ARN" 2>/dev/null && echo " Deleted target group $TG_NAME" + [ -n "$SG_ID" ] && aws ec2 delete-security-group --group-id "$SG_ID" 2>/dev/null && echo " Deleted security group $SG_ID" + rm -rf "$WORK_DIR" + echo "Cleanup complete." +} + +# Step 1: Get VPC and subnets +echo "Step 1: Getting VPC and subnets" +VPC_ID=$(aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" --query 'Vpcs[0].VpcId' --output text) +SUBNETS=$(aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPC_ID" \ + --query 'Subnets[:2].SubnetId' --output text) +SUBNET1=$(echo "$SUBNETS" | awk '{print $1}') +SUBNET2=$(echo "$SUBNETS" | awk '{print $2}') +echo " VPC: $VPC_ID" +echo " Subnets: $SUBNET1, $SUBNET2" + +# Step 2: Create security group +echo "Step 2: Creating security group" +SG_ID=$(aws ec2 create-security-group --group-name "tut-alb-sg-${RANDOM_ID}" \ + --description "Tutorial ALB security group" --vpc-id "$VPC_ID" \ + --query 'GroupId' --output text) +aws ec2 authorize-security-group-ingress --group-id "$SG_ID" \ + --protocol tcp --port 80 --cidr 0.0.0.0/0 > /dev/null +echo " Security group: $SG_ID (port 80 open)" + +# Step 3: Create target group +echo "Step 3: Creating target group: $TG_NAME" +TG_ARN=$(aws elbv2 create-target-group --name "$TG_NAME" \ + --protocol HTTP --port 80 --vpc-id "$VPC_ID" \ + --target-type ip \ + --query 'TargetGroups[0].TargetGroupArn' --output text) +echo " Target group ARN: $TG_ARN" + +# Step 4: Create ALB +echo "Step 4: Creating Application Load Balancer: $ALB_NAME" +ALB_ARN=$(aws elbv2 create-load-balancer --name "$ALB_NAME" \ + --subnets $SUBNET1 $SUBNET2 \ + --security-groups "$SG_ID" \ + --query 'LoadBalancers[0].LoadBalancerArn' --output text) +echo " ALB ARN: $ALB_ARN" + +# Step 5: Wait for ALB to be active +echo "Step 5: Waiting for ALB to be active..." +aws elbv2 wait load-balancer-available --load-balancer-arns "$ALB_ARN" +DNS_NAME=$(aws elbv2 describe-load-balancers --load-balancer-arns "$ALB_ARN" \ + --query 'LoadBalancers[0].DNSName' --output text) +echo " DNS: $DNS_NAME" + +# Step 6: Create listener +echo "Step 6: Creating HTTP listener" +LISTENER_ARN=$(aws elbv2 create-listener --load-balancer-arn "$ALB_ARN" \ + --protocol HTTP --port 80 \ + --default-actions "Type=forward,TargetGroupArn=$TG_ARN" \ + --query 'Listeners[0].ListenerArn' --output text) +echo " Listener ARN: $LISTENER_ARN" + +# Step 7: Describe the ALB +echo "Step 7: ALB details" +aws elbv2 describe-load-balancers --load-balancer-arns "$ALB_ARN" \ + --query 'LoadBalancers[0].{Name:LoadBalancerName,DNS:DNSName,State:State.Code,Type:Type}' --output table + +echo "" +echo "Tutorial complete." +echo "The ALB is running but has no targets registered." +echo "Note: ALBs incur hourly charges (~\$0.02/hr). Clean up promptly." +echo "" +echo "Do you want to clean up all resources? (y/n): " +read -r CHOICE +if [[ "$CHOICE" =~ ^[Yy]$ ]]; then + cleanup +else + echo "Resources left running. ALB charges ~\$0.02/hr." + echo "Manual cleanup:" + echo " aws elbv2 delete-listener --listener-arn $LISTENER_ARN" + echo " aws elbv2 delete-load-balancer --load-balancer-arn $ALB_ARN" + echo " # Wait 1-2 minutes, then:" + echo " aws elbv2 delete-target-group --target-group-arn $TG_ARN" + echo " aws ec2 delete-security-group --group-id $SG_ID" +fi diff --git a/tuts/143-aws-transfer-gs/aws-transfer-gs.sh b/tuts/143-aws-transfer-gs/aws-transfer-gs.sh new file mode 100644 index 00000000..b88b0fde --- /dev/null +++ b/tuts/143-aws-transfer-gs/aws-transfer-gs.sh @@ -0,0 +1,18 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/transfer.log") 2>&1 +REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)}; [ -z "$REGION" ] && echo "ERROR: No region" && exit 1; export AWS_DEFAULT_REGION="$REGION"; echo "Region: $REGION" +RANDOM_ID=$(openssl rand -hex 4) +handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; }; trap 'handle_error $LINENO' ERR +cleanup() { echo ""; echo "Cleaning up..."; [ -n "$SERVER_ID" ] && aws transfer delete-server --server-id "$SERVER_ID" 2>/dev/null && echo " Deleted server (takes ~1 min)"; rm -rf "$WORK_DIR"; echo "Done."; } +echo "Step 1: Creating SFTP server" +SERVER_ID=$(aws transfer create-server --protocols SFTP --endpoint-type PUBLIC --identity-provider-type SERVICE_MANAGED --query 'ServerId' --output text) +echo " Server ID: $SERVER_ID" +echo "Step 2: Waiting for server..." +for i in $(seq 1 20); do STATUS=$(aws transfer describe-server --server-id "$SERVER_ID" --query 'Server.State' --output text); echo " $STATUS"; [ "$STATUS" = "ONLINE" ] && break; sleep 10; done +echo "Step 3: Server details" +aws transfer describe-server --server-id "$SERVER_ID" --query 'Server.{Id:ServerId,State:State,Endpoint:EndpointDetails.AddressAllocationIds,Protocols:Protocols}' --output table +echo "Step 4: Listing servers" +aws transfer list-servers --query 'Servers[:3].{Id:ServerId,State:State,Protocols:Protocols}' --output table +echo ""; echo "Tutorial complete." +echo "Note: Transfer Family servers incur hourly charges (~\$0.30/hr). Clean up promptly." +echo "Do you want to clean up? (y/n): "; read -r CHOICE; [[ "$CHOICE" =~ ^[Yy]$ ]] && cleanup diff --git a/tuts/144-aws-datasync-gs/aws-datasync-gs.sh b/tuts/144-aws-datasync-gs/aws-datasync-gs.sh new file mode 100644 index 00000000..5ee5ba80 --- /dev/null +++ b/tuts/144-aws-datasync-gs/aws-datasync-gs.sh @@ -0,0 +1,12 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/datasync.log") 2>&1 +REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)}; [ -z "$REGION" ] && echo "ERROR: No region" && exit 1; export AWS_DEFAULT_REGION="$REGION"; echo "Region: $REGION" +echo "Step 1: Listing agents" +aws datasync list-agents --query 'Agents[:5].{Arn:AgentArn,Name:Name,Status:Status}' --output table 2>/dev/null || echo " No agents configured" +echo "Step 2: Listing locations" +aws datasync list-locations --query 'Locations[:5].{Uri:LocationUri,Arn:LocationArn}' --output table 2>/dev/null || echo " No locations configured" +echo "Step 3: Listing tasks" +aws datasync list-tasks --query 'Tasks[:5].{Name:Name,Status:Status,Arn:TaskArn}' --output table 2>/dev/null || echo " No tasks configured" +echo ""; echo "Tutorial complete. DataSync requires an agent (on-premises or EC2) for data transfer." +echo "No resources created — this tutorial shows the DataSync API structure." +rm -rf "$WORK_DIR" diff --git a/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh b/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh new file mode 100644 index 00000000..49741173 --- /dev/null +++ b/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh @@ -0,0 +1,18 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/ga.log") 2>&1 +export AWS_DEFAULT_REGION=us-west-2; echo "Region: us-west-2 (Global Accelerator)" +RANDOM_ID=$(openssl rand -hex 4); GA_NAME="tut-ga-${RANDOM_ID}" +handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; }; trap 'handle_error $LINENO' ERR +cleanup() { echo ""; echo "Cleaning up..."; [ -n "$GA_ARN" ] && { aws globalaccelerator update-accelerator --accelerator-arn "$GA_ARN" --no-enabled 2>/dev/null; sleep 5; aws globalaccelerator delete-accelerator --accelerator-arn "$GA_ARN" 2>/dev/null && echo " Deleted accelerator"; }; rm -rf "$WORK_DIR"; echo "Done."; } +echo "Step 1: Creating accelerator: $GA_NAME" +GA_ARN=$(aws globalaccelerator create-accelerator --name "$GA_NAME" --query 'Accelerator.AcceleratorArn' --output text) +echo " ARN: $GA_ARN" +echo "Step 2: Waiting for deployment..." +for i in $(seq 1 20); do STATUS=$(aws globalaccelerator describe-accelerator --accelerator-arn "$GA_ARN" --query 'Accelerator.Status' --output text); echo " $STATUS"; [ "$STATUS" = "DEPLOYED" ] && break; sleep 10; done +echo "Step 3: Accelerator details" +aws globalaccelerator describe-accelerator --accelerator-arn "$GA_ARN" --query 'Accelerator.{Name:Name,Status:Status,DNS:DnsName,IPs:IpSets[0].IpAddresses}' --output table +echo "Step 4: Listing accelerators" +aws globalaccelerator list-accelerators --query 'Accelerators[?starts_with(Name, `tut-`)].{Name:Name,Status:Status}' --output table +echo ""; echo "Tutorial complete." +echo "Note: Global Accelerator incurs hourly charges. Clean up promptly." +echo "Do you want to clean up? (y/n): "; read -r CHOICE; [[ "$CHOICE" =~ ^[Yy]$ ]] && cleanup diff --git a/tuts/158-vpc-endpoints/vpc-endpoints.sh b/tuts/158-vpc-endpoints/vpc-endpoints.sh new file mode 100644 index 00000000..4e342bf4 --- /dev/null +++ b/tuts/158-vpc-endpoints/vpc-endpoints.sh @@ -0,0 +1,19 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/vpc-ep.log") 2>&1 +REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)}; [ -z "$REGION" ] && echo "ERROR: No region" && exit 1; export AWS_DEFAULT_REGION="$REGION"; echo "Region: $REGION" +RANDOM_ID=$(openssl rand -hex 4) +VPC_ID=$(aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" --query 'Vpcs[0].VpcId' --output text) +handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; }; trap 'handle_error $LINENO' ERR +cleanup() { echo ""; echo "Cleaning up..."; [ -n "$EP_ID" ] && aws ec2 delete-vpc-endpoints --vpc-endpoint-ids "$EP_ID" > /dev/null 2>&1 && echo " Deleted endpoint"; rm -rf "$WORK_DIR"; echo "Done."; } +echo "Step 1: Listing available VPC endpoint services" +aws ec2 describe-vpc-endpoint-services --query 'ServiceNames[:10]' --output table +echo "Step 2: Creating a gateway endpoint (S3)" +RT_ID=$(aws ec2 describe-route-tables --filters "Name=vpc-id,Values=$VPC_ID" --query 'RouteTables[0].RouteTableId' --output text) +EP_ID=$(aws ec2 create-vpc-endpoint --vpc-id "$VPC_ID" --service-name "com.amazonaws.${REGION}.s3" --route-table-ids "$RT_ID" --query 'VpcEndpoint.VpcEndpointId' --output text) +echo " Endpoint: $EP_ID" +echo "Step 3: Describing endpoint" +aws ec2 describe-vpc-endpoints --vpc-endpoint-ids "$EP_ID" --query 'VpcEndpoints[0].{Id:VpcEndpointId,Service:ServiceName,State:State,Type:VpcEndpointType}' --output table +echo "Step 4: Listing endpoints" +aws ec2 describe-vpc-endpoints --filters "Name=vpc-id,Values=$VPC_ID" --query 'VpcEndpoints[].{Id:VpcEndpointId,Service:ServiceName,Type:VpcEndpointType}' --output table +echo ""; echo "Tutorial complete." +echo "Do you want to clean up? (y/n): "; read -r CHOICE; [[ "$CHOICE" =~ ^[Yy]$ ]] && cleanup From 6b8688b108131409a909869b224280a502afbd64 Mon Sep 17 00:00:00 2001 From: Michael Wunderlich Date: Tue, 21 Apr 2026 05:17:17 +0000 Subject: [PATCH 2/4] Apply technical requirements (R1, R2, R9, R10, R13) - R1: Add AWS_REGION to region fallback chain - R2: Replace openssl rand with /dev/urandom - R9: Remove Appendix/Generation details from READMEs - R10: Remove internal references - R13: Add REVISION-HISTORY.md --- tuts/117-elastic-load-balancing-gs/REVISION-HISTORY.md | 8 ++++++++ .../elastic-load-balancing-gs.sh | 2 +- tuts/143-aws-transfer-gs/REVISION-HISTORY.md | 8 ++++++++ tuts/143-aws-transfer-gs/aws-transfer-gs.sh | 4 ++-- tuts/144-aws-datasync-gs/REVISION-HISTORY.md | 8 ++++++++ tuts/144-aws-datasync-gs/aws-datasync-gs.sh | 2 +- tuts/145-aws-globalaccelerator-gs/REVISION-HISTORY.md | 8 ++++++++ .../aws-globalaccelerator-gs.sh | 2 +- tuts/158-vpc-endpoints/REVISION-HISTORY.md | 8 ++++++++ tuts/158-vpc-endpoints/vpc-endpoints.sh | 4 ++-- 10 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 tuts/117-elastic-load-balancing-gs/REVISION-HISTORY.md create mode 100644 tuts/143-aws-transfer-gs/REVISION-HISTORY.md create mode 100644 tuts/144-aws-datasync-gs/REVISION-HISTORY.md create mode 100644 tuts/145-aws-globalaccelerator-gs/REVISION-HISTORY.md create mode 100644 tuts/158-vpc-endpoints/REVISION-HISTORY.md diff --git a/tuts/117-elastic-load-balancing-gs/REVISION-HISTORY.md b/tuts/117-elastic-load-balancing-gs/REVISION-HISTORY.md new file mode 100644 index 00000000..bf6266fb --- /dev/null +++ b/tuts/117-elastic-load-balancing-gs/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 117-elastic-load-balancing-gs + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.sh b/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.sh index 2b34739b..32c853c6 100644 --- a/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.sh +++ b/tuts/117-elastic-load-balancing-gs/elastic-load-balancing-gs.sh @@ -14,7 +14,7 @@ fi export AWS_DEFAULT_REGION="$REGION" echo "Region: $REGION" -RANDOM_ID=$(openssl rand -hex 4) +RANDOM_ID=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1) ALB_NAME="tut-alb-${RANDOM_ID}" TG_NAME="tut-tg-${RANDOM_ID}" diff --git a/tuts/143-aws-transfer-gs/REVISION-HISTORY.md b/tuts/143-aws-transfer-gs/REVISION-HISTORY.md new file mode 100644 index 00000000..12213214 --- /dev/null +++ b/tuts/143-aws-transfer-gs/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 143-aws-transfer-gs + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/143-aws-transfer-gs/aws-transfer-gs.sh b/tuts/143-aws-transfer-gs/aws-transfer-gs.sh index b88b0fde..405e48db 100644 --- a/tuts/143-aws-transfer-gs/aws-transfer-gs.sh +++ b/tuts/143-aws-transfer-gs/aws-transfer-gs.sh @@ -1,7 +1,7 @@ #!/bin/bash WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/transfer.log") 2>&1 -REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)}; [ -z "$REGION" ] && echo "ERROR: No region" && exit 1; export AWS_DEFAULT_REGION="$REGION"; echo "Region: $REGION" -RANDOM_ID=$(openssl rand -hex 4) +REGION=${AWS_DEFAULT_REGION:-${AWS_REGION:-$(aws configure get region 2>/dev/null))}; [ -z "$REGION" ] && echo "ERROR: No region" && exit 1; export AWS_DEFAULT_REGION="$REGION"; echo "Region: $REGION" +RANDOM_ID=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1) handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; }; trap 'handle_error $LINENO' ERR cleanup() { echo ""; echo "Cleaning up..."; [ -n "$SERVER_ID" ] && aws transfer delete-server --server-id "$SERVER_ID" 2>/dev/null && echo " Deleted server (takes ~1 min)"; rm -rf "$WORK_DIR"; echo "Done."; } echo "Step 1: Creating SFTP server" diff --git a/tuts/144-aws-datasync-gs/REVISION-HISTORY.md b/tuts/144-aws-datasync-gs/REVISION-HISTORY.md new file mode 100644 index 00000000..492068f6 --- /dev/null +++ b/tuts/144-aws-datasync-gs/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 144-aws-datasync-gs + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/144-aws-datasync-gs/aws-datasync-gs.sh b/tuts/144-aws-datasync-gs/aws-datasync-gs.sh index 5ee5ba80..766fbca8 100644 --- a/tuts/144-aws-datasync-gs/aws-datasync-gs.sh +++ b/tuts/144-aws-datasync-gs/aws-datasync-gs.sh @@ -1,6 +1,6 @@ #!/bin/bash WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/datasync.log") 2>&1 -REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)}; [ -z "$REGION" ] && echo "ERROR: No region" && exit 1; export AWS_DEFAULT_REGION="$REGION"; echo "Region: $REGION" +REGION=${AWS_DEFAULT_REGION:-${AWS_REGION:-$(aws configure get region 2>/dev/null))}; [ -z "$REGION" ] && echo "ERROR: No region" && exit 1; export AWS_DEFAULT_REGION="$REGION"; echo "Region: $REGION" echo "Step 1: Listing agents" aws datasync list-agents --query 'Agents[:5].{Arn:AgentArn,Name:Name,Status:Status}' --output table 2>/dev/null || echo " No agents configured" echo "Step 2: Listing locations" diff --git a/tuts/145-aws-globalaccelerator-gs/REVISION-HISTORY.md b/tuts/145-aws-globalaccelerator-gs/REVISION-HISTORY.md new file mode 100644 index 00000000..f2967c47 --- /dev/null +++ b/tuts/145-aws-globalaccelerator-gs/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 145-aws-globalaccelerator-gs + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh b/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh index 49741173..e8aa0a1e 100644 --- a/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh +++ b/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh @@ -1,7 +1,7 @@ #!/bin/bash WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/ga.log") 2>&1 export AWS_DEFAULT_REGION=us-west-2; echo "Region: us-west-2 (Global Accelerator)" -RANDOM_ID=$(openssl rand -hex 4); GA_NAME="tut-ga-${RANDOM_ID}" +RANDOM_ID=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1); GA_NAME="tut-ga-${RANDOM_ID}" handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; }; trap 'handle_error $LINENO' ERR cleanup() { echo ""; echo "Cleaning up..."; [ -n "$GA_ARN" ] && { aws globalaccelerator update-accelerator --accelerator-arn "$GA_ARN" --no-enabled 2>/dev/null; sleep 5; aws globalaccelerator delete-accelerator --accelerator-arn "$GA_ARN" 2>/dev/null && echo " Deleted accelerator"; }; rm -rf "$WORK_DIR"; echo "Done."; } echo "Step 1: Creating accelerator: $GA_NAME" diff --git a/tuts/158-vpc-endpoints/REVISION-HISTORY.md b/tuts/158-vpc-endpoints/REVISION-HISTORY.md new file mode 100644 index 00000000..86316068 --- /dev/null +++ b/tuts/158-vpc-endpoints/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 158-vpc-endpoints + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/158-vpc-endpoints/vpc-endpoints.sh b/tuts/158-vpc-endpoints/vpc-endpoints.sh index 4e342bf4..fb471cdf 100644 --- a/tuts/158-vpc-endpoints/vpc-endpoints.sh +++ b/tuts/158-vpc-endpoints/vpc-endpoints.sh @@ -1,7 +1,7 @@ #!/bin/bash WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/vpc-ep.log") 2>&1 -REGION=${AWS_DEFAULT_REGION:-$(aws configure get region 2>/dev/null)}; [ -z "$REGION" ] && echo "ERROR: No region" && exit 1; export AWS_DEFAULT_REGION="$REGION"; echo "Region: $REGION" -RANDOM_ID=$(openssl rand -hex 4) +REGION=${AWS_DEFAULT_REGION:-${AWS_REGION:-$(aws configure get region 2>/dev/null))}; [ -z "$REGION" ] && echo "ERROR: No region" && exit 1; export AWS_DEFAULT_REGION="$REGION"; echo "Region: $REGION" +RANDOM_ID=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1) VPC_ID=$(aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" --query 'Vpcs[0].VpcId' --output text) handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; }; trap 'handle_error $LINENO' ERR cleanup() { echo ""; echo "Cleaning up..."; [ -n "$EP_ID" ] && aws ec2 delete-vpc-endpoints --vpc-endpoint-ids "$EP_ID" > /dev/null 2>&1 && echo " Deleted endpoint"; rm -rf "$WORK_DIR"; echo "Done."; } From f573813d82488caa8b9bc1b1b45b771e1051607a Mon Sep 17 00:00:00 2001 From: Michael Wunderlich Date: Tue, 21 Apr 2026 05:18:42 +0000 Subject: [PATCH 3/4] Standardize region handling for Global Accelerator --- tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh b/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh index e8aa0a1e..b7d55521 100644 --- a/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh +++ b/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.sh @@ -1,6 +1,7 @@ #!/bin/bash WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/ga.log") 2>&1 -export AWS_DEFAULT_REGION=us-west-2; echo "Region: us-west-2 (Global Accelerator)" +REGION=us-west-2 # Global Accelerator requires us-west-2 +export AWS_DEFAULT_REGION="$REGION"; export AWS_REGION="$REGION"; echo "Region: $REGION (Global Accelerator)" RANDOM_ID=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1); GA_NAME="tut-ga-${RANDOM_ID}" handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; }; trap 'handle_error $LINENO' ERR cleanup() { echo ""; echo "Cleaning up..."; [ -n "$GA_ARN" ] && { aws globalaccelerator update-accelerator --accelerator-arn "$GA_ARN" --no-enabled 2>/dev/null; sleep 5; aws globalaccelerator delete-accelerator --accelerator-arn "$GA_ARN" 2>/dev/null && echo " Deleted accelerator"; }; rm -rf "$WORK_DIR"; echo "Done."; } From 99f1e9634aab9205dcd8dbd0c52e5c1a19bd506f Mon Sep 17 00:00:00 2001 From: Michael Wunderlich Date: Tue, 21 Apr 2026 05:38:01 +0000 Subject: [PATCH 4/4] Add README.md and tutorial walkthrough for script-only tutorials --- tuts/143-aws-transfer-gs/README.md | 37 +++++++++++++++++++ tuts/143-aws-transfer-gs/aws-transfer-gs.md | 27 ++++++++++++++ tuts/144-aws-datasync-gs/README.md | 28 ++++++++++++++ tuts/144-aws-datasync-gs/aws-datasync-gs.md | 19 ++++++++++ tuts/145-aws-globalaccelerator-gs/README.md | 37 +++++++++++++++++++ .../aws-globalaccelerator-gs.md | 27 ++++++++++++++ tuts/158-vpc-endpoints/README.md | 37 +++++++++++++++++++ tuts/158-vpc-endpoints/vpc-endpoints.md | 27 ++++++++++++++ 8 files changed, 239 insertions(+) create mode 100644 tuts/143-aws-transfer-gs/README.md create mode 100644 tuts/143-aws-transfer-gs/aws-transfer-gs.md create mode 100644 tuts/144-aws-datasync-gs/README.md create mode 100644 tuts/144-aws-datasync-gs/aws-datasync-gs.md create mode 100644 tuts/145-aws-globalaccelerator-gs/README.md create mode 100644 tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.md create mode 100644 tuts/158-vpc-endpoints/README.md create mode 100644 tuts/158-vpc-endpoints/vpc-endpoints.md diff --git a/tuts/143-aws-transfer-gs/README.md b/tuts/143-aws-transfer-gs/README.md new file mode 100644 index 00000000..1f87a2b7 --- /dev/null +++ b/tuts/143-aws-transfer-gs/README.md @@ -0,0 +1,37 @@ +# Aws Transfer Gs + +An AWS CLI tutorial that demonstrates Transfer operations. + +## Running + +```bash +bash aws-transfer-gs.sh +``` + +To auto-run with cleanup: + +```bash +echo 'y' | bash aws-transfer-gs.sh +``` + +## What it does + +1. Creating SFTP server +2. Waiting for server... +3. Server details +4. Listing servers + +## Resources created + +- Server + +The script prompts you to clean up resources when it finishes. + +## Cost + +Free tier eligible for most operations. Clean up resources after use to avoid charges. + +## Related docs + +- [AWS CLI transfer reference](https://docs.aws.amazon.com/cli/latest/reference/transfer/index.html) + diff --git a/tuts/143-aws-transfer-gs/aws-transfer-gs.md b/tuts/143-aws-transfer-gs/aws-transfer-gs.md new file mode 100644 index 00000000..7ae512a7 --- /dev/null +++ b/tuts/143-aws-transfer-gs/aws-transfer-gs.md @@ -0,0 +1,27 @@ +# Aws Transfer Gs + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Creating SFTP server + +The script handles this step automatically. See `aws-transfer-gs.sh` for the exact CLI commands. + +## Step 2: Waiting for server... + +The script handles this step automatically. See `aws-transfer-gs.sh` for the exact CLI commands. + +## Step 3: Server details + +The script handles this step automatically. See `aws-transfer-gs.sh` for the exact CLI commands. + +## Step 4: Listing servers + +The script handles this step automatically. See `aws-transfer-gs.sh` for the exact CLI commands. + +## Cleanup + +The script prompts you to clean up all created resources. If you need to clean up manually, check the script log for the resource names that were created. + diff --git a/tuts/144-aws-datasync-gs/README.md b/tuts/144-aws-datasync-gs/README.md new file mode 100644 index 00000000..bcd58212 --- /dev/null +++ b/tuts/144-aws-datasync-gs/README.md @@ -0,0 +1,28 @@ +# Aws Datasync Gs + +A read-only script that queries Datasync resources and displays information. + +## Running + +```bash +bash aws-datasync-gs.sh +``` + +## What it does + +1. Listing agents +2. Listing locations +3. Listing tasks + +## Resources created + +None — this script is read-only. + +## Cost + +No cost. This script only reads existing resources. + +## Related docs + +- [AWS CLI datasync reference](https://docs.aws.amazon.com/cli/latest/reference/datasync/index.html) + diff --git a/tuts/144-aws-datasync-gs/aws-datasync-gs.md b/tuts/144-aws-datasync-gs/aws-datasync-gs.md new file mode 100644 index 00000000..8b0a1925 --- /dev/null +++ b/tuts/144-aws-datasync-gs/aws-datasync-gs.md @@ -0,0 +1,19 @@ +# Aws Datasync Gs + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Listing agents + +The script handles this step automatically. See `aws-datasync-gs.sh` for the exact CLI commands. + +## Step 2: Listing locations + +The script handles this step automatically. See `aws-datasync-gs.sh` for the exact CLI commands. + +## Step 3: Listing tasks + +The script handles this step automatically. See `aws-datasync-gs.sh` for the exact CLI commands. + diff --git a/tuts/145-aws-globalaccelerator-gs/README.md b/tuts/145-aws-globalaccelerator-gs/README.md new file mode 100644 index 00000000..996915a3 --- /dev/null +++ b/tuts/145-aws-globalaccelerator-gs/README.md @@ -0,0 +1,37 @@ +# Aws Globalaccelerator Gs + +An AWS CLI tutorial that demonstrates Globalaccelerator operations. + +## Running + +```bash +bash aws-globalaccelerator-gs.sh +``` + +To auto-run with cleanup: + +```bash +echo 'y' | bash aws-globalaccelerator-gs.sh +``` + +## What it does + +1. Creating accelerator: $GA_NAME +2. Waiting for deployment... +3. Accelerator details +4. Listing accelerators + +## Resources created + +- Accelerator + +The script prompts you to clean up resources when it finishes. + +## Cost + +Free tier eligible for most operations. Clean up resources after use to avoid charges. + +## Related docs + +- [AWS CLI globalaccelerator reference](https://docs.aws.amazon.com/cli/latest/reference/globalaccelerator/index.html) + diff --git a/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.md b/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.md new file mode 100644 index 00000000..c80e6fb5 --- /dev/null +++ b/tuts/145-aws-globalaccelerator-gs/aws-globalaccelerator-gs.md @@ -0,0 +1,27 @@ +# Aws Globalaccelerator Gs + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Creating accelerator: $GA_NAME + +The script handles this step automatically. See `aws-globalaccelerator-gs.sh` for the exact CLI commands. + +## Step 2: Waiting for deployment... + +The script handles this step automatically. See `aws-globalaccelerator-gs.sh` for the exact CLI commands. + +## Step 3: Accelerator details + +The script handles this step automatically. See `aws-globalaccelerator-gs.sh` for the exact CLI commands. + +## Step 4: Listing accelerators + +The script handles this step automatically. See `aws-globalaccelerator-gs.sh` for the exact CLI commands. + +## Cleanup + +The script prompts you to clean up all created resources. If you need to clean up manually, check the script log for the resource names that were created. + diff --git a/tuts/158-vpc-endpoints/README.md b/tuts/158-vpc-endpoints/README.md new file mode 100644 index 00000000..cf63fc60 --- /dev/null +++ b/tuts/158-vpc-endpoints/README.md @@ -0,0 +1,37 @@ +# Vpc Endpoints + +An AWS CLI tutorial that demonstrates Ec2 operations. + +## Running + +```bash +bash vpc-endpoints.sh +``` + +To auto-run with cleanup: + +```bash +echo 'y' | bash vpc-endpoints.sh +``` + +## What it does + +1. Listing available VPC endpoint services +2. Creating a gateway endpoint (S3) +3. Describing endpoint +4. Listing endpoints + +## Resources created + +- Vpc Endpoint + +The script prompts you to clean up resources when it finishes. + +## Cost + +Free tier eligible for most operations. Clean up resources after use to avoid charges. + +## Related docs + +- [AWS CLI ec2 reference](https://docs.aws.amazon.com/cli/latest/reference/ec2/index.html) + diff --git a/tuts/158-vpc-endpoints/vpc-endpoints.md b/tuts/158-vpc-endpoints/vpc-endpoints.md new file mode 100644 index 00000000..cdfde157 --- /dev/null +++ b/tuts/158-vpc-endpoints/vpc-endpoints.md @@ -0,0 +1,27 @@ +# Vpc Endpoints + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Listing available VPC endpoint services + +The script handles this step automatically. See `vpc-endpoints.sh` for the exact CLI commands. + +## Step 2: Creating a gateway endpoint (S3) + +The script handles this step automatically. See `vpc-endpoints.sh` for the exact CLI commands. + +## Step 3: Describing endpoint + +The script handles this step automatically. See `vpc-endpoints.sh` for the exact CLI commands. + +## Step 4: Listing endpoints + +The script handles this step automatically. See `vpc-endpoints.sh` for the exact CLI commands. + +## Cleanup + +The script prompts you to clean up all created resources. If you need to clean up manually, check the script log for the resource names that were created. +