diff --git a/tuts/203-dynamodb-batch-operations/README.md b/tuts/203-dynamodb-batch-operations/README.md new file mode 100644 index 0000000..cce0649 --- /dev/null +++ b/tuts/203-dynamodb-batch-operations/README.md @@ -0,0 +1,37 @@ +# Dynamodb Batch Ops + +An AWS CLI tutorial that demonstrates Dynamodb operations. + +## Running + +```bash +bash dynamodb-batch-ops.sh +``` + +To auto-run with cleanup: + +```bash +echo 'y' | bash dynamodb-batch-ops.sh +``` + +## What it does + +1. Creating table"; aws dynamodb create-table --table-name "$T" --key-schema AttributeName=pk,KeyType=HASH --attribute-definitions AttributeName=pk,AttributeType=S --billing-mode PAY_PER_REQUEST > /dev/null; aws dynamodb wait table-exists --table-name "$T +2. Batch write (25 items)"; aws dynamodb batch-write-item --request-items "{\"$T\":[$(for i in $(seq 1 25); do echo -n "{\"PutRequest\":{\"Item\":{\"pk\":{\"S\":\"item-$i\"},\"data\":{\"S\":\"value-$i\"}}}}"; [ $i -lt 25 ] && echo -n ","; done)]} +3. Batch get (5 items)"; aws dynamodb batch-get-item --request-items "{\"$T\":{\"Keys\":[{\"pk\":{\"S\":\"item-1\"}},{\"pk\":{\"S\":\"item-5\"}},{\"pk\":{\"S\":\"item-10\"}},{\"pk\":{\"S\":\"item-15\"}},{\"pk\":{\"S\":\"item-20\"}}]}}" --query "Responses.\"$T\"[].{pk:pk.S,data:data.S} +4. Scan count"; aws dynamodb scan --table-name "$T + +## Resources created + +- Table + +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 dynamodb reference](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/index.html) + diff --git a/tuts/203-dynamodb-batch-operations/REVISION-HISTORY.md b/tuts/203-dynamodb-batch-operations/REVISION-HISTORY.md new file mode 100644 index 0000000..56ef560 --- /dev/null +++ b/tuts/203-dynamodb-batch-operations/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 203-dynamodb-batch-operations + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/203-dynamodb-batch-operations/dynamodb-batch-ops.md b/tuts/203-dynamodb-batch-operations/dynamodb-batch-ops.md new file mode 100644 index 0000000..b366213 --- /dev/null +++ b/tuts/203-dynamodb-batch-operations/dynamodb-batch-ops.md @@ -0,0 +1,27 @@ +# Dynamodb Batch Ops + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Creating table"; aws dynamodb create-table --table-name "$T" --key-schema AttributeName=pk,KeyType=HASH --attribute-definitions AttributeName=pk,AttributeType=S --billing-mode PAY_PER_REQUEST > /dev/null; aws dynamodb wait table-exists --table-name "$T + +The script handles this step automatically. See `dynamodb-batch-ops.sh` for the exact CLI commands. + +## Step 2: Batch write (25 items)"; aws dynamodb batch-write-item --request-items "{\"$T\":[$(for i in $(seq 1 25); do echo -n "{\"PutRequest\":{\"Item\":{\"pk\":{\"S\":\"item-$i\"},\"data\":{\"S\":\"value-$i\"}}}}"; [ $i -lt 25 ] && echo -n ","; done)]} + +The script handles this step automatically. See `dynamodb-batch-ops.sh` for the exact CLI commands. + +## Step 3: Batch get (5 items)"; aws dynamodb batch-get-item --request-items "{\"$T\":{\"Keys\":[{\"pk\":{\"S\":\"item-1\"}},{\"pk\":{\"S\":\"item-5\"}},{\"pk\":{\"S\":\"item-10\"}},{\"pk\":{\"S\":\"item-15\"}},{\"pk\":{\"S\":\"item-20\"}}]}}" --query "Responses.\"$T\"[].{pk:pk.S,data:data.S} + +The script handles this step automatically. See `dynamodb-batch-ops.sh` for the exact CLI commands. + +## Step 4: Scan count"; aws dynamodb scan --table-name "$T + +The script handles this step automatically. See `dynamodb-batch-ops.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/203-dynamodb-batch-operations/dynamodb-batch-ops.sh b/tuts/203-dynamodb-batch-operations/dynamodb-batch-ops.sh new file mode 100644 index 0000000..a1b23ba --- /dev/null +++ b/tuts/203-dynamodb-batch-operations/dynamodb-batch-ops.sh @@ -0,0 +1,11 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/tut.log") 2>&1 +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); T="tut-batch-${RANDOM_ID}" +cleanup() { aws dynamodb delete-table --table-name "$T" > /dev/null 2>&1; rm -rf "$WORK_DIR"; echo "Done."; } +echo "Step 1: Creating table"; aws dynamodb create-table --table-name "$T" --key-schema AttributeName=pk,KeyType=HASH --attribute-definitions AttributeName=pk,AttributeType=S --billing-mode PAY_PER_REQUEST > /dev/null; aws dynamodb wait table-exists --table-name "$T" +echo "Step 2: Batch write (25 items)"; aws dynamodb batch-write-item --request-items "{\"$T\":[$(for i in $(seq 1 25); do echo -n "{\"PutRequest\":{\"Item\":{\"pk\":{\"S\":\"item-$i\"},\"data\":{\"S\":\"value-$i\"}}}}"; [ $i -lt 25 ] && echo -n ","; done)]}" > /dev/null +echo " Wrote 25 items" +echo "Step 3: Batch get (5 items)"; aws dynamodb batch-get-item --request-items "{\"$T\":{\"Keys\":[{\"pk\":{\"S\":\"item-1\"}},{\"pk\":{\"S\":\"item-5\"}},{\"pk\":{\"S\":\"item-10\"}},{\"pk\":{\"S\":\"item-15\"}},{\"pk\":{\"S\":\"item-20\"}}]}}" --query "Responses.\"$T\"[].{pk:pk.S,data:data.S}" --output table +echo "Step 4: Scan count"; aws dynamodb scan --table-name "$T" --select COUNT --query 'Count' --output text +echo "Do you want to clean up? (y/n): "; read -r C; [[ "$C" =~ ^[Yy]$ ]] && cleanup diff --git a/tuts/208-lambda-list-functions/README.md b/tuts/208-lambda-list-functions/README.md new file mode 100644 index 0000000..9a7ddd0 --- /dev/null +++ b/tuts/208-lambda-list-functions/README.md @@ -0,0 +1,27 @@ +# Lambda List Functions + +A read-only script that queries Lambda resources and displays information. + +## Running + +```bash +bash lambda-list-functions.sh +``` + +## What it does + +1. Listing functions +2. Function count by runtime + +## Resources created + +None — this script is read-only. + +## Cost + +No cost. This script only reads existing resources. + +## Related docs + +- [AWS CLI lambda reference](https://docs.aws.amazon.com/cli/latest/reference/lambda/index.html) + diff --git a/tuts/208-lambda-list-functions/REVISION-HISTORY.md b/tuts/208-lambda-list-functions/REVISION-HISTORY.md new file mode 100644 index 0000000..961c592 --- /dev/null +++ b/tuts/208-lambda-list-functions/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 208-lambda-list-functions + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/208-lambda-list-functions/lambda-list-functions.md b/tuts/208-lambda-list-functions/lambda-list-functions.md new file mode 100644 index 0000000..799a9b8 --- /dev/null +++ b/tuts/208-lambda-list-functions/lambda-list-functions.md @@ -0,0 +1,15 @@ +# Lambda List Functions + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Listing functions + +The script handles this step automatically. See `lambda-list-functions.sh` for the exact CLI commands. + +## Step 2: Function count by runtime + +The script handles this step automatically. See `lambda-list-functions.sh` for the exact CLI commands. + diff --git a/tuts/208-lambda-list-functions/lambda-list-functions.sh b/tuts/208-lambda-list-functions/lambda-list-functions.sh new file mode 100644 index 0000000..dc10e6b --- /dev/null +++ b/tuts/208-lambda-list-functions/lambda-list-functions.sh @@ -0,0 +1,6 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/tut.log") 2>&1 +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 functions"; aws lambda list-functions --query 'Functions[:10].{Name:FunctionName,Runtime:Runtime,Size:CodeSize,Modified:LastModified}' --output table +echo "Step 2: Function count by runtime"; aws lambda list-functions --query 'Functions[].Runtime' --output text | tr '\t' '\n' | sort | uniq -c | sort -rn +echo ""; echo "Tutorial complete. Read-only."; rm -rf "$WORK_DIR" diff --git a/tuts/213-ec2-security-group-audit/README.md b/tuts/213-ec2-security-group-audit/README.md new file mode 100644 index 0000000..7008ab2 --- /dev/null +++ b/tuts/213-ec2-security-group-audit/README.md @@ -0,0 +1,27 @@ +# Ec2 Security Group Rules + +A read-only script that queries Ec2 resources and displays information. + +## Running + +```bash +bash ec2-security-group-rules.sh +``` + +## What it does + +1. Listing security groups +2. Finding groups with open SSH + +## Resources created + +None — this script is read-only. + +## Cost + +No cost. This script only reads existing resources. + +## Related docs + +- [AWS CLI ec2 reference](https://docs.aws.amazon.com/cli/latest/reference/ec2/index.html) + diff --git a/tuts/213-ec2-security-group-audit/REVISION-HISTORY.md b/tuts/213-ec2-security-group-audit/REVISION-HISTORY.md new file mode 100644 index 0000000..8708e16 --- /dev/null +++ b/tuts/213-ec2-security-group-audit/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 213-ec2-security-group-audit + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/213-ec2-security-group-audit/ec2-security-group-rules.md b/tuts/213-ec2-security-group-audit/ec2-security-group-rules.md new file mode 100644 index 0000000..ccef657 --- /dev/null +++ b/tuts/213-ec2-security-group-audit/ec2-security-group-rules.md @@ -0,0 +1,15 @@ +# Ec2 Security Group Rules + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Listing security groups + +The script handles this step automatically. See `ec2-security-group-rules.sh` for the exact CLI commands. + +## Step 2: Finding groups with open SSH + +The script handles this step automatically. See `ec2-security-group-rules.sh` for the exact CLI commands. + diff --git a/tuts/213-ec2-security-group-audit/ec2-security-group-rules.sh b/tuts/213-ec2-security-group-audit/ec2-security-group-rules.sh new file mode 100644 index 0000000..18b1971 --- /dev/null +++ b/tuts/213-ec2-security-group-audit/ec2-security-group-rules.sh @@ -0,0 +1,7 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/tut.log") 2>&1 +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 security groups"; aws ec2 describe-security-groups --query 'SecurityGroups[:10].{Id:GroupId,Name:GroupName,VPC:VpcId,InRules:IpPermissions|length(@),OutRules:IpPermissionsEgress|length(@)}' --output table +echo "Step 2: Finding groups with open SSH" +aws ec2 describe-security-groups --filters "Name=ip-permission.from-port,Values=22" "Name=ip-permission.cidr,Values=0.0.0.0/0" --query 'SecurityGroups[].{Id:GroupId,Name:GroupName}' --output table 2>/dev/null || echo " No groups with open SSH" +echo ""; echo "Tutorial complete. Read-only."; rm -rf "$WORK_DIR" diff --git a/tuts/215-lambda-event-invoke-config/README.md b/tuts/215-lambda-event-invoke-config/README.md new file mode 100644 index 0000000..41e7ef9 --- /dev/null +++ b/tuts/215-lambda-event-invoke-config/README.md @@ -0,0 +1,26 @@ +# Lambda Event Invoke Config + +A read-only script that queries Lambda resources and displays information. + +## Running + +```bash +bash lambda-event-invoke-config.sh +``` + +## What it does + +1. Listing functions with event invoke configs + +## Resources created + +None — this script is read-only. + +## Cost + +No cost. This script only reads existing resources. + +## Related docs + +- [AWS CLI lambda reference](https://docs.aws.amazon.com/cli/latest/reference/lambda/index.html) + diff --git a/tuts/215-lambda-event-invoke-config/REVISION-HISTORY.md b/tuts/215-lambda-event-invoke-config/REVISION-HISTORY.md new file mode 100644 index 0000000..1c62b52 --- /dev/null +++ b/tuts/215-lambda-event-invoke-config/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 215-lambda-event-invoke-config + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/215-lambda-event-invoke-config/lambda-event-invoke-config.md b/tuts/215-lambda-event-invoke-config/lambda-event-invoke-config.md new file mode 100644 index 0000000..0f9022d --- /dev/null +++ b/tuts/215-lambda-event-invoke-config/lambda-event-invoke-config.md @@ -0,0 +1,11 @@ +# Lambda Event Invoke Config + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Listing functions with event invoke configs + +The script handles this step automatically. See `lambda-event-invoke-config.sh` for the exact CLI commands. + diff --git a/tuts/215-lambda-event-invoke-config/lambda-event-invoke-config.sh b/tuts/215-lambda-event-invoke-config/lambda-event-invoke-config.sh new file mode 100644 index 0000000..4507255 --- /dev/null +++ b/tuts/215-lambda-event-invoke-config/lambda-event-invoke-config.sh @@ -0,0 +1,10 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/tut.log") 2>&1 +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 functions with event invoke configs" +for F in $(aws lambda list-functions --query 'Functions[:5].FunctionName' --output text 2>/dev/null); do + CONFIG=$(aws lambda get-function-event-invoke-config --function-name "$F" 2>/dev/null) + [ -n "$CONFIG" ] && echo " $F: $(echo $CONFIG | python3 -c 'import sys,json;c=json.load(sys.stdin);print(f"MaxRetry={c.get(\"MaximumRetryAttempts\",\"default\")}, MaxAge={c.get(\"MaximumEventAgeInSeconds\",\"default\")}")')" +done +echo " (Functions without custom config use defaults: 2 retries, 6 hours max age)" +echo ""; echo "Tutorial complete. Read-only."; rm -rf "$WORK_DIR" diff --git a/tuts/216-ec2-cost-optimization/README.md b/tuts/216-ec2-cost-optimization/README.md new file mode 100644 index 0000000..00e1459 --- /dev/null +++ b/tuts/216-ec2-cost-optimization/README.md @@ -0,0 +1,29 @@ +# Ec2 Cost Optimization + +A read-only script that queries Ec2 resources and displays information. + +## Running + +```bash +bash ec2-cost-optimization.sh +``` + +## What it does + +1. Finding stopped instances (still incurring EBS charges) +2. Finding unattached EBS volumes +3. Finding unattached Elastic IPs +4. Finding old snapshots (>90 days) + +## Resources created + +None — this script is read-only. + +## Cost + +No cost. This script only reads existing resources. + +## Related docs + +- [AWS CLI ec2 reference](https://docs.aws.amazon.com/cli/latest/reference/ec2/index.html) + diff --git a/tuts/216-ec2-cost-optimization/REVISION-HISTORY.md b/tuts/216-ec2-cost-optimization/REVISION-HISTORY.md new file mode 100644 index 0000000..a18c6d3 --- /dev/null +++ b/tuts/216-ec2-cost-optimization/REVISION-HISTORY.md @@ -0,0 +1,8 @@ +# Revision History: 216-ec2-cost-optimization + +## Shell (CLI script) + +### 2026-04-14 v1 published +- Type: functional +- Initial version + diff --git a/tuts/216-ec2-cost-optimization/ec2-cost-optimization.md b/tuts/216-ec2-cost-optimization/ec2-cost-optimization.md new file mode 100644 index 0000000..c1f1730 --- /dev/null +++ b/tuts/216-ec2-cost-optimization/ec2-cost-optimization.md @@ -0,0 +1,23 @@ +# Ec2 Cost Optimization + +## Prerequisites + +1. AWS CLI installed and configured (`aws configure`) +2. Appropriate IAM permissions for the AWS services used + +## Step 1: Finding stopped instances (still incurring EBS charges) + +The script handles this step automatically. See `ec2-cost-optimization.sh` for the exact CLI commands. + +## Step 2: Finding unattached EBS volumes + +The script handles this step automatically. See `ec2-cost-optimization.sh` for the exact CLI commands. + +## Step 3: Finding unattached Elastic IPs + +The script handles this step automatically. See `ec2-cost-optimization.sh` for the exact CLI commands. + +## Step 4: Finding old snapshots (>90 days) + +The script handles this step automatically. See `ec2-cost-optimization.sh` for the exact CLI commands. + diff --git a/tuts/216-ec2-cost-optimization/ec2-cost-optimization.sh b/tuts/216-ec2-cost-optimization/ec2-cost-optimization.sh new file mode 100644 index 0000000..b291841 --- /dev/null +++ b/tuts/216-ec2-cost-optimization/ec2-cost-optimization.sh @@ -0,0 +1,13 @@ +#!/bin/bash +WORK_DIR=$(mktemp -d); exec > >(tee -a "$WORK_DIR/tut.log") 2>&1 +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: Finding stopped instances (still incurring EBS charges)" +aws ec2 describe-instances --filters "Name=instance-state-name,Values=stopped" --query 'Reservations[].Instances[].{Id:InstanceId,Type:InstanceType,Stopped:StateTransitionReason}' --output table 2>/dev/null || echo " No stopped instances" +echo "Step 2: Finding unattached EBS volumes" +aws ec2 describe-volumes --filters "Name=status,Values=available" --query 'Volumes[].{Id:VolumeId,Size:Size,Type:VolumeType,Created:CreateTime}' --output table 2>/dev/null || echo " No unattached volumes" +echo "Step 3: Finding unattached Elastic IPs" +aws ec2 describe-addresses --query 'Addresses[?AssociationId==null].{IP:PublicIp,AllocId:AllocationId}' --output table 2>/dev/null || echo " No unattached EIPs" +echo "Step 4: Finding old snapshots (>90 days)" +CUTOFF=$(date -u -d '90 days ago' +%Y-%m-%dT%H:%M:%SZ) +aws ec2 describe-snapshots --owner-ids self --query "Snapshots[?StartTime<'$CUTOFF'][:5].{Id:SnapshotId,Size:VolumeSize,Created:StartTime}" --output table 2>/dev/null || echo " No old snapshots" +echo ""; echo "Tutorial complete. Read-only — identifies cost optimization opportunities."; rm -rf "$WORK_DIR"