Kanji
・Cloud Engineer / Freelance ・Geboren 1993 ・Aus Ehime / Wohnhaft in Shibuya, Tokio ・5 Jahre AWS-Erfahrung Profildetails
Inhaltsverzeichnis
LocalStack ist ein Tool zum Emulieren von AWS-Cloud-Diensten in einer lokalen Umgebung. Durch die lokale Nachahmung von AWS-Diensten können Entwickler die AWS CLI und SDKs zum Testen ohne Internetverbindung verwenden.
Mit dem kostenlosen Plan können Sie einige AWS-Dienste lokal emulieren, es sind jedoch nicht alle Dienste verfügbar. Wichtige Dienste wie EC2, VPC, Lambda, S3, DynamoDB, SNS und SQS werden unterstützt.
LocalStack wird als Docker-Container bereitgestellt, was die Einrichtung mit Docker vereinfacht.
Former2 ist ein Tool zum Generieren von AWS CloudFormation-Vorlagen. Mithilfe von IAM-Benutzer- oder STS-Anmeldeinformationen werden Ressourcen in Ihrem AWS-Konto gescannt und IaC-Vorlagen (Infrastructure as Code) für CloudFormation, CDK, Terraform, Pulumi und mehr generiert. Es unterstützt auch Draw.io (Beta), aber meiner Erfahrung nach hat es bei der VPC- und EC2-Erstellung nicht funktioniert.
Former2 ist wie LocalStack als Docker-Container verfügbar und kann einfach mit Docker eingerichtet werden.
– Referenz: iann0036/former2: Generieren Sie CloudFormation-/Terraform-/Troposphere-Vorlagen aus Ihren vorhandenen AWS-Ressourcen.
In diesem Artikel wird ein LocalStack + Former2-Setup mit den folgenden drei Schlüsselpunkten vorgestellt:
Für LocalStack-Konten gilt ein 14-tägiger Testzeitraum, in dem Sie den LocalStack-Ressourcenbrowser verwenden können, um AWS-Ressourcen über eine GUI anzuzeigen. Nach der Testversion benötigen Sie einen kostenpflichtigen Plan, um die GUI nutzen zu können. Durch die Verwendung von Former2 können Sie AWS-Ressourcenzustände visualisieren und überprüfen, ohne sich Gedanken über den Testzeitraum machen zu müssen.
Während Former2 als Webservice verfügbar ist, wird die Open-Source-Version als Docker-Container bereitgestellt, der mithilfe von Docker Compose mit LocalStack orchestriert werden kann.
Sie können das GitHub-Repository klonen und es wie unten gezeigt mit Docker Compose starten:
Das Klonen des Repositorys oder das Erstellen einer Docker Compose-Datei ist nicht schwierig, aber in diesem Artikel wird eine Methode vorgestellt, die DinD (Docker-in-Docker) verwendet, um Docker-Befehle in einem einzelnen Container zu erstellen und auszuführen.
Former2 speichert die Einstellungen im lokalen Speicher des Browsers. Wenn Sie also den Browser-Cache leeren, werden Ihre Einstellungen gelöscht. Selbst bei der Ausführung in einem Docker-Container gibt es keine Standardmethode zum Beibehalten von Einstellungen. Daher müssen Sie sie manuell neu konfigurieren, wenn sie zurückgesetzt werden. In diesem Artikel wird eine Problemumgehung vorgestellt: Former2-Einstellungen in eine JavaScript-Datei schreiben und sie beim Containerstart anwenden.
Bevor Sie fortfahren, beachten Sie bitte Folgendes: LocalStack verhält sich möglicherweise anders als tatsächliche AWS-Umgebungen und wird daher nur für Selbstlernzwecke empfohlen.
Hier sind einige Verhaltensweisen, die ich beobachtet habe:
Auch wenn die Bereitstellung in LocalStack funktioniert, können bei der Bereitstellung in der Produktion Probleme auftreten. Verwenden Sie diese Umgebung zum Erlernen von AWS CLI oder CloudFormation oder für interne Workshops, um diese Einschränkungen zu verstehen.
In diesem Artikel werden folgende Voraussetzungen vorausgesetzt:
Erstellen Sie zunächst die folgenden drei Dateien in Ihrem Arbeitsverzeichnis:
${WORK_DIRECTORY}/ ${WORK_DIRECTORY}/docker-compose.yml ${WORK_DIRECTORY}/Dockerfile ${WORK_DIRECTORY}/setting.js # Example directory structure localstack-with-former2/ localstack-with-former2/docker-compose.yml localstack-with-former2/Dockerfile localstack-with-former2/setting.js
Sie können das Arbeitsverzeichnis überall erstellen. Zum Beispiel:
WORK_DIRECTORY=$(pwd)/localstack-with-former2 mkdir -p ${WORK_DIRECTORY} cd ${WORK_DIRECTORY}
Erstellen Sie die „Dockerfile“ mit folgendem Inhalt. Kernpunkte:
# REF: https://hub.docker.com/r/docker/compose FROM docker/compose:alpine-1.29.1 WORKDIR /root RUN apk add --no-cache git RUN git clone https://github.com/iann0036/former2.git COPY docker-compose.yml . # WORKAROUND: https://stackoverflow.com/questions/37013947/force-a-docker-build-to-rebuild-a-single-step ARG SETTING_TIMESTAMP=YYYYMMDDHHMMSS COPY setting.js . RUN cp setting.js former2/lib/setting.js && \ sed -i '/<\/head>/i <script src="lib/setting.js"></script>' former2/index.html CMD cp -R /root/former2 /volume && \ docker-compose up
Erstellen Sie die Datei „docker-compose.yml“ wie folgt. Kernpunkte:
# REF: https://docs.docker.jp/compose/compose-file/compose-versioning.html version: "3.8" services: former2: container_name: former2 image: nginx:stable-alpine ports: - "127.0.0.1:8089:80" volumes: - ${WORK_DIRECTORY}/volume/former2:/usr/share/nginx/html - "/var/run/docker.sock:/var/run/docker.sock" # REF: https://docs.localstack.cloud/getting-started/installation/#starting-localstack-with-docker localstack: container_name: localstack image: localstack/localstack ports: - "4566:4566" - "4510-4559:4510-4559" environment: - DEBUG=${DEBUG-} - DOCKER_HOST=unix:///var/run/docker.sock # REF: https://github.com/iann0036/former2 - EXTRA_CORS_ALLOWED_ORIGINS=chrome-extension://fhejmeojlbhfhjndnkkleooeejklmigi volumes: - ${WORK_DIRECTORY}/volume/localstack:/var/lib/localstack - "/var/run/docker.sock:/var/run/docker.sock"
Erstellen Sie die Datei „setting.js“ wie folgt. Diese Einstellungen basieren auf former2/js/app.js at master · iann0036/former2 . Hier werden nur die Standardregion, die CloudFormation-Vorlageneinrückung und die LocalStack-Endpunktnutzung festgelegt.
window.localStorage.setItem('region', "ap-northeast-1"); window.localStorage.setItem('cfnspacing',"2"); window.localStorage.setItem('uselocalstackendpoint', "true"); window.localStorage.setItem('logicalidstrategy', "longtypeprefixoptionalindexsuffix"); // default window.localStorage.setItem('defaultoutput', "cloudformation"); // default window.localStorage.setItem('iaclangselect', "typescript"); // default window.localStorage.setItem('skipirrelevantresources', "true"); // default window.localStorage.setItem('relatedresourcessetting', ""); // default window.localStorage.setItem('includedefaultresources', ""); // default
Erstellen Sie mit den Dateien aus „Vorbereitungsschritt 1“ das Docker-Image:
– Die Option „–platform=linux/amd64“ erstellt für die x86_64-Architektur (erforderlich für ARM-basierte Macs/Windows). – „–build-arg SETTING_TIMESTAMP=$(date +%Y%m%d%H%M%S)“ legt das Build-Argument fest, um Neuerstellungen auszulösen, wenn sich die Konfiguration ändert.
docker build \ --platform=linux/amd64 \ --build-arg SETTING_TIMESTAMP=$(date +%Y%m%d%H%M%S) \ -t localstack-with-former2:latest \ .
Starten Sie LocalStack und Former2 mit:
docker run \ --name localstack-with-former2 \ --platform=linux/amd64 \ --privileged \ --detach \ --rm \ -it \ -e WORK_DIRECTORY=$(pwd) \ -v /var/run/docker.sock:/var/run/docker.sock \ -v $(pwd)/volume:/volume \ localstack-with-former2:latest
Hinweis: Führen Sie diese Befehle in dem Verzeichnis aus, in dem Sie das Docker-Image erstellt haben.
In „docker-compose.yml“ mountet der Former2-Container „ W O R K D I R E C T O R Y / v o l u m e / f o r m e r 2 : / u s r / s h a r e / n g i n x / h t m l “ . D a „ d o c k e r − c o m p o s e u p “ i n n e r h a l b d e s C o n t a i n e r s a u s g e f ü h r t w i r d , k ö n n t e m a n e r w a r t e n , d a s s „ {WORK_DIRECTORY}/volume/former2“ innerhalb des Containers gemountet wird, aber tatsächlich ist die Quelle das Hostverzeichnis. Daher ist das Mounten von „/root/former2“ (das nur innerhalb des Containers existiert) nicht möglich. Siehe: Linux – Docker in Docker kann kein Volume bereitstellen – Stack Overflow
Somit ist der Prozess:
Konfigurieren Sie zunächst die AWS CLI für die Verwendung von LocalStack.
Sie können Umgebungsvariablen oder ein AWS CLI-Profil verwenden. Bei Umgebungsvariablen müssen Sie diese jedes Mal festlegen. Bei einem Profil konfigurieren Sie es einmal und geben das Profil für Befehle an.
aws configure set aws_access_key_id localstack --profile localstack aws configure set aws_secret_access_key localstack --profile localstack aws configure set region ap-northeast-1 --profile localstack aws configure set aws_endpoint_url http://localhost:4566 --profile localstack
export AWS_ACCESS_KEY_ID=localstack export AWS_SECRET_ACCESS_KEY=localstack export AWS_REGION=ap-northeast-1 export AWS_ENDPOINT_URL=http://localhost:4566
Vorausgesetzt, Sie haben die AWS CLI mit der Profilmethode konfiguriert, können Sie, sobald LocalStack ausgeführt wird, die AWS CLI verwenden, um mit Ressourcen zu interagieren.
Überprüfen Sie zunächst den AWS CLI-Zugriff auf LocalStack:
aws sts \ get-caller-identity \ --profile localstack
Wenn Sie eine Antwort wie unten sehen, ist Ihre Konfiguration korrekt (die Konto-ID lautet „000000000000“):
# Example output % aws sts get-caller-identity \ --profile localstack { "UserId": "AKIAIOSFODNN7EXAMPLE", "Account": "000000000000", "Arn": "arn:aws:iam::000000000000:root" }
Erstellen Sie als Nächstes einen Beispiel-S3-Bucket (Bucket-Name muss nicht global eindeutig sein):
aws s3api \ create-bucket \ --bucket hoge-foo-bar \ --create-bucket-configuration LocationConstraint=ap-northeast-1 \ --profile localstack
# Example output % aws s3api \ create-bucket \ --bucket hoge-foo-bar \ --create-bucket-configuration LocationConstraint=ap-northeast-1 \ --profile localstack { "Location": "http://hoge-foo-bar.s3.localhost.localstack.cloud:4566/" }
Hinweis: Ressourcen werden gelöscht, wenn Sie den Container stoppen.Um Ressourcen zu erhalten, lassen Sie den Container laufen.
Überprüfen Sie den Bucket, den Sie mit Former2 erstellt haben. Greifen Sie auf http://127.0.0.1:8089/ zu und gehen Sie dann zu „Speicher“ -> „S3“ -> „Buckets“. Ihr Bucket sollte wie folgt angezeigt werden.
Für Konfigurationswerte, die in Former2 nicht sichtbar sind, verwenden Sie die AWS CLI. Um beispielsweise den Status eines CloudFormation-Stacks zu überprüfen, verwenden Sie die AWS CLI. Unten finden Sie ein Befehlsbeispiel für einen Stack mit dem Namen „sample-vpc-stack“.Die Ausgabe wird mit jq in eine Tabelle formatiert.
# Stack List aws cloudformation describe-stacks \ --profile localstack \ --query "Stacks[].{StackName: StackName, StackStatus: StackStatus, CreationTime: CreationTime, LastUpdatedTime: LastUpdatedTime}" \ --output json \ | jq -r '["StackName","StackStatus","CreationTime","LastUpdatedTime"], (.[] | [.StackName, .StackStatus, .CreationTime, .LastUpdatedTime]) | @tsv' \ | column -t -s $'\t' # List of Stack Resources stack_name="sample-vpc-stack" aws cloudformation list-stack-resources \ --stack-name "${stack_name}" \ --profile localstack \ --output json \ | jq -r '["LogicalResourceId","PhysicalResourceId","ResourceType","ResourceStatus"], (.StackResourceSummaries[] | [.LogicalResourceId, .PhysicalResourceId, .ResourceType, .ResourceStatus]) | @tsv' \ | column -t -s $'\t' # Stack Events List stack_name="sample-vpc-stack" aws cloudformation describe-stack-events \ --stack-name "${stack_name}" \ --query "StackEvents[].{Timestamp: Timestamp, LogicalResourceId: LogicalResourceId, ResourceType: ResourceType, ResourceStatus: ResourceStatus, ResourceStatusReason: ResourceStatusReason}" \ --profile localstack \ --output json \ | jq -r '["Timestamp","LogicalResourceId","ResourceType","ResourceStatus","ResourceStatusReason"], (.[] | [.Timestamp, .LogicalResourceId, .ResourceType, .ResourceStatus, .ResourceStatusReason]) | @tsv' \ | column -t -s $'\t' # Stack Outputs List stack_name="sample-vpc-stack" aws cloudformation describe-stacks \ --stack-name "${stack_name}" \ --query "Stacks[].Outputs[].{OutputKey: OutputKey, OutputValue: OutputValue, ExportName: ExportName}" \ --profile localstack \ --output json \ | jq -r '["OutputKey","OutputValue"], (.[] | [.OutputKey, .OutputValue, .ExportName]) | @tsv' \ | column -t -s $'\t'
Nachfolgend finden Sie ein Beispiel für die Ausführungsergebnisse.Die in diesem Beispiel verwendete CloudFormation-Vorlage für die VPC wird in einem separaten Artikel vorgestellt.
# Execution Result - Stack List % aws cloudformation describe-stacks \ --profile localstack \ --query "Stacks[].{StackName: StackName, StackStatus: StackStatus, CreationTime: CreationTime, LastUpdatedTime: LastUpdatedTime}" \ --output json \ | jq -r '["StackName","StackStatus","CreationTime","LastUpdatedTime"], (.[] | [.StackName, .StackStatus, .CreationTime, .LastUpdatedTime]) | @tsv' \ | column -t -s $'\t' StackName StackStatus CreationTime LastUpdatedTime sample-vpc-stack CREATE_COMPLETE 2025-05-25T01:49:43.238000+00:00 2025-05-25T01:49:43.238000+00:00 # Execution Result - Stack Resource List % stack_name="sample-vpc-stack" aws cloudformation list-stack-resources \ --stack-name "${stack_name}" \ --profile localstack \ --output json \ | jq -r '["LogicalResourceId","PhysicalResourceId","ResourceType","ResourceStatus"], (.StackResourceSummaries[] | [.LogicalResourceId, .PhysicalResourceId, .ResourceType, .ResourceStatus]) | @tsv' \ | column -t -s $'\t' LogicalResourceId PhysicalResourceId ResourceType ResourceStatus VPC1 vpc-4bd2b9a09d788f172 AWS::EC2::VPC CREATE_COMPLETE InternetGateway igw-9bbb17a1eaf64992b AWS::EC2::InternetGateway CREATE_COMPLETE FlowLogsIAMRole AWS::IAM::Role CREATE_COMPLETE PublicSubnet1 subnet-c0c96c0f53f7f1cd7 AWS::EC2::Subnet CREATE_COMPLETE PublicSubnet2 subnet-836137197cc3767a2 AWS::EC2::Subnet CREATE_COMPLETE PrivateSubnet1 subnet-197c985876fcbfdac AWS::EC2::Subnet CREATE_COMPLETE PrivateSubnet2 subnet-a059fb7bd23898fd7 AWS::EC2::Subnet CREATE_COMPLETE ProtectedSubnet1 subnet-1ca041ff52b2493fb AWS::EC2::Subnet CREATE_COMPLETE ProtectedSubnet2 subnet-eff4ebad7049f6c6f AWS::EC2::Subnet CREATE_COMPLETE PublicRouteTable rtb-6f5f999ed1a475a4e AWS::EC2::RouteTable CREATE_COMPLETE PrivateSubnet1RouteTable AWS::EC2::RouteTable CREATE_COMPLETE PrivateSubnet2RouteTable AWS::EC2::RouteTable CREATE_COMPLETE ProtectedRouteTable rtb-453340a863a7a1059 AWS::EC2::RouteTable CREATE_COMPLETE CustomNetworkAcl acl-b0001fb613e8118d2 AWS::EC2::NetworkAcl CREATE_COMPLETE VPCFlowLog1 AWS::EC2::FlowLog CREATE_COMPLETE VPCGatewayAttachment AWS::EC2::VPCGatewayAttachment CREATE_COMPLETE PublicSubnet1RouteTableAssociation rtbassoc-c838b296a6edb9a37 AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE PublicSubnet2RouteTableAssociation rtbassoc-5fe392e039de6701d AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE PrivateSubnet1RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE PrivateSubnet2RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE ProtectedSubnet1RouteTableAssociation rtbassoc-896b8d426f6c0d5e4 AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE ProtectedSubnet2RouteTableAssociation rtbassoc-8e3ec29094055a5bc AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE CustomNetworkAclEntryInbound unknown AWS::EC2::NetworkAclEntry CREATE_COMPLETE CustomNetworkAclEntryOutbound unknown AWS::EC2::NetworkAclEntry CREATE_COMPLETE NaclAssociationPublicSubnet1 unknown AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE NaclAssociationPublicSubnet2 unknown AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE NaclAssociationPrivateSubnet1 unknown AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE NaclAssociationPrivateSubnet2 unknown AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE NaclAssociationProtectedSubnet1 unknown AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE NaclAssociationProtectedSubnet2 unknown AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE NATGateway1EIP AWS::EC2::EIP CREATE_COMPLETE NATGateway2EIP AWS::EC2::EIP CREATE_COMPLETE PublicRoute rtb-6f5f999ed1a475a4e~0.0.0.0/0 AWS::EC2::Route CREATE_COMPLETE NatGateway1 AWS::EC2::NatGateway CREATE_COMPLETE NatGateway2 AWS::EC2::NatGateway CREATE_COMPLETE PrivateSubnet2Route AWS::EC2::Route CREATE_COMPLETE PrivateSubnet1Route AWS::EC2::Route CREATE_COMPLETE # Execution Result - Stack Events List % stack_name="sample-vpc-stack" aws cloudformation describe-stack-events \ --stack-name "${stack_name}" \ --query "StackEvents[].{Timestamp: Timestamp, LogicalResourceId: LogicalResourceId, ResourceType: ResourceType, ResourceStatus: ResourceStatus, ResourceStatusReason: ResourceStatusReason}" \ --profile localstack \ --output json \ | jq -r '["Timestamp","LogicalResourceId","ResourceType","ResourceStatus","ResourceStatusReason"], (.[] | [.Timestamp, .LogicalResourceId, .ResourceType, .ResourceStatus, .ResourceStatusReason]) | @tsv' \ | column -t -s $'\t' Timestamp LogicalResourceId ResourceType ResourceStatus ResourceStatusReason 2025-05-25T01:49:44.440000+00:00 sample-vpc-stack AWS::CloudFormation::Stack CREATE_COMPLETE 2025-05-25T01:49:44.412000+00:00 PrivateSubnet1Route AWS::EC2::Route CREATE_COMPLETE 2025-05-25T01:49:44.411000+00:00 PrivateSubnet2Route AWS::EC2::Route CREATE_COMPLETE 2025-05-25T01:49:44.411000+00:00 NatGateway2 AWS::EC2::NatGateway CREATE_COMPLETE 2025-05-25T01:49:44.411000+00:00 NatGateway1 AWS::EC2::NatGateway CREATE_COMPLETE 2025-05-25T01:49:44.411000+00:00 PublicRoute AWS::EC2::Route CREATE_COMPLETE 2025-05-25T01:49:44.408000+00:00 PublicRoute AWS::EC2::Route CREATE_IN_PROGRESS 2025-05-25T01:49:44.398000+00:00 NATGateway2EIP AWS::EC2::EIP CREATE_COMPLETE 2025-05-25T01:49:44.398000+00:00 NATGateway1EIP AWS::EC2::EIP CREATE_COMPLETE 2025-05-25T01:49:44.398000+00:00 NaclAssociationProtectedSubnet2 AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE 2025-05-25T01:49:44.391000+00:00 NaclAssociationProtectedSubnet1 AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE 2025-05-25T01:49:44.384000+00:00 NaclAssociationPrivateSubnet2 AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE 2025-05-25T01:49:44.377000+00:00 NaclAssociationPrivateSubnet1 AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE 2025-05-25T01:49:44.370000+00:00 NaclAssociationPublicSubnet2 AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE 2025-05-25T01:49:44.363000+00:00 NaclAssociationPublicSubnet1 AWS::EC2::SubnetNetworkAclAssociation CREATE_COMPLETE 2025-05-25T01:49:44.356000+00:00 CustomNetworkAclEntryOutbound AWS::EC2::NetworkAclEntry CREATE_COMPLETE 2025-05-25T01:49:44.346000+00:00 CustomNetworkAclEntryInbound AWS::EC2::NetworkAclEntry CREATE_COMPLETE 2025-05-25T01:49:44.336000+00:00 ProtectedSubnet2RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE 2025-05-25T01:49:44.333000+00:00 ProtectedSubnet2RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_IN_PROGRESS 2025-05-25T01:49:44.326000+00:00 ProtectedSubnet1RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE 2025-05-25T01:49:44.323000+00:00 ProtectedSubnet1RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_IN_PROGRESS 2025-05-25T01:49:44.316000+00:00 PrivateSubnet2RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE 2025-05-25T01:49:44.316000+00:00 PrivateSubnet1RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE 2025-05-25T01:49:44.316000+00:00 PublicSubnet2RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE 2025-05-25T01:49:44.313000+00:00 PublicSubnet2RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_IN_PROGRESS 2025-05-25T01:49:44.306000+00:00 PublicSubnet1RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_COMPLETE 2025-05-25T01:49:44.299000+00:00 PublicSubnet1RouteTableAssociation AWS::EC2::SubnetRouteTableAssociation CREATE_IN_PROGRESS 2025-05-25T01:49:44.292000+00:00 VPCGatewayAttachment AWS::EC2::VPCGatewayAttachment CREATE_COMPLETE 2025-05-25T01:49:44.290000+00:00 VPCGatewayAttachment AWS::EC2::VPCGatewayAttachment CREATE_IN_PROGRESS 2025-05-25T01:49:44.283000+00:00 VPCFlowLog1 AWS::EC2::FlowLog CREATE_COMPLETE 2025-05-25T01:49:44.283000+00:00 CustomNetworkAcl AWS::EC2::NetworkAcl CREATE_COMPLETE 2025-05-25T01:49:44.280000+00:00 CustomNetworkAcl AWS::EC2::NetworkAcl CREATE_IN_PROGRESS 2025-05-25T01:49:44.269000+00:00 ProtectedRouteTable AWS::EC2::RouteTable CREATE_COMPLETE 2025-05-25T01:49:44.267000+00:00 ProtectedRouteTable AWS::EC2::RouteTable CREATE_IN_PROGRESS 2025-05-25T01:49:44.256000+00:00 PrivateSubnet2RouteTable AWS::EC2::RouteTable CREATE_COMPLETE 2025-05-25T01:49:44.256000+00:00 PrivateSubnet1RouteTable AWS::EC2::RouteTable CREATE_COMPLETE 2025-05-25T01:49:44.256000+00:00 PublicRouteTable AWS::EC2::RouteTable CREATE_COMPLETE 2025-05-25T01:49:44.253000+00:00 PublicRouteTable AWS::EC2::RouteTable CREATE_IN_PROGRESS 2025-05-25T01:49:44.242000+00:00 ProtectedSubnet2 AWS::EC2::Subnet CREATE_COMPLETE 2025-05-25T01:49:44.239000+00:00 ProtectedSubnet2 AWS::EC2::Subnet CREATE_IN_PROGRESS 2025-05-25T01:49:44.218000+00:00 ProtectedSubnet1 AWS::EC2::Subnet CREATE_COMPLETE 2025-05-25T01:49:44.215000+00:00 ProtectedSubnet1 AWS::EC2::Subnet CREATE_IN_PROGRESS 2025-05-25T01:49:44.193000+00:00 PrivateSubnet2 AWS::EC2::Subnet CREATE_COMPLETE 2025-05-25T01:49:44.190000+00:00 PrivateSubnet2 AWS::EC2::Subnet CREATE_IN_PROGRESS 2025-05-25T01:49:44.168000+00:00 PrivateSubnet1 AWS::EC2::Subnet CREATE_COMPLETE 2025-05-25T01:49:44.164000+00:00 PrivateSubnet1 AWS::EC2::Subnet CREATE_IN_PROGRESS 2025-05-25T01:49:44.143000+00:00 PublicSubnet2 AWS::EC2::Subnet CREATE_COMPLETE 2025-05-25T01:49:44.140000+00:00 PublicSubnet2 AWS::EC2::Subnet CREATE_IN_PROGRESS 2025-05-25T01:49:44.109000+00:00 PublicSubnet1 AWS::EC2::Subnet CREATE_COMPLETE 2025-05-25T01:49:44.103000+00:00 PublicSubnet1 AWS::EC2::Subnet CREATE_IN_PROGRESS 2025-05-25T01:49:44.042000+00:00 FlowLogsIAMRole AWS::IAM::Role CREATE_COMPLETE 2025-05-25T01:49:44.042000+00:00 InternetGateway AWS::EC2::InternetGateway CREATE_COMPLETE 2025-05-25T01:49:44.040000+00:00 InternetGateway AWS::EC2::InternetGateway CREATE_IN_PROGRESS 2025-05-25T01:49:44.031000+00:00 VPC1 AWS::EC2::VPC CREATE_COMPLETE 2025-05-25T01:49:43.320000+00:00 VPC1 AWS::EC2::VPC CREATE_IN_PROGRESS 2025-05-25T01:49:43.246000+00:00 sample-vpc-stack AWS::CloudFormation::Stack CREATE_IN_PROGRESS 2025-05-25T01:49:43.238000+00:00 sample-vpc-stack AWS::CloudFormation::Stack REVIEW_IN_PROGRESS # Execution Result - Stack Outputs List % stack_name="sample-vpc-stack" aws cloudformation describe-stacks \ --stack-name "${stack_name}" \ --query "Stacks[].Outputs[].{OutputKey: OutputKey, OutputValue: OutputValue, ExportName: ExportName}" \ --profile localstack \ --output json \ | jq -r '["OutputKey","OutputValue"], (.[] | [.OutputKey, .OutputValue, .ExportName]) | @tsv' \ | column -t -s $'\t' OutputKey OutputValue VPCId vpc-4bd2b9a09d788f172 sample-vpc-id PublicSubnet1Id subnet-c0c96c0f53f7f1cd7 sample-public-subnet1-id PublicSubnet2Id subnet-836137197cc3767a2 sample-public-subnet2-id PrivateSubnet1Id subnet-197c985876fcbfdac sample-private-subnet1-id PrivateSubnet2Id subnet-a059fb7bd23898fd7 sample-private-subnet2-id ProtectedSubnet1Id subnet-1ca041ff52b2493fb sample-protected-subnet1-id ProtectedSubnet2Id subnet-eff4ebad7049f6c6f sample-protected-subnet2-id