diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 43868ca70..7af75dc53 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,4 +1,4 @@
[bumpversion]
-current_version = 3.7.1
+current_version = 4.0.0
commit = True
tag = False
diff --git a/.gitignore b/.gitignore
index 9a89fbb2a..155db88b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,446 +1,54 @@
-### VisualStudioCode template
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-*.code-workspace
-
-# Local History for Visual Studio Code
-.history/
-
-### JetBrains
-.idea
-
-# Gradle
-.idea/**/gradle.xml
-.idea/**/libraries
-
-# Gradle and Maven with auto-import
-# When using Gradle or Maven with auto-import, you should exclude module files,
-# since they will be recreated, and may cause churn. Uncomment if using
-# auto-import.
-# .idea/artifacts
-# .idea/compiler.xml
-# .idea/jarRepositories.xml
-# .idea/modules.xml
-# .idea/*.iml
-# .idea/modules
-# *.iml
-# *.ipr
-
-# CMake
-cmake-build-*/
-
-# Mongo Explorer plugin
-.idea/**/mongoSettings.xml
-
-# File-based project format
-*.iws
-
-# IntelliJ
-out/
-
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Cursive Clojure plugin
-.idea/replstate.xml
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-com_crashlytics_export_strings.xml
-crashlytics.properties
-crashlytics-build.properties
-fabric.properties
-
-# Editor-based Rest Client
-.idea/httpRequests
-
-# Android studio 3.1+ serialized cache file
-.idea/caches/build_file_checksums.ser
-
-### VirtualEnv template
-# Virtualenv
-# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
-.Python
-[Bb]in
-[Ii]nclude
-[Ll]ib
-[Ll]ib64
-[Ll]ocal
-[Ss]cripts
-pyvenv.cfg
-.venv
-pip-selfcheck.json
-
-### Linux template
-*~
-
-# temporary files which can be created if a process still has a handle open of a deleted file
-.fuse_hidden*
-
-# KDE directory preferences
-.directory
-
-# Linux trash folder which might appear on any partition or disk
-.Trash-*
-
-# .nfs files are created when an open file is removed but is still being accessed
-.nfs*
-
-### Hugo template
-# Generated files by hugo
-/public/
-/resources/_gen/
-
-# Executable may be added to repository
-hugo.exe
-hugo.darwin
-hugo.linux
-.hugo_build.lock
-
-### Node template
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-lerna-debug.log*
-
-# Diagnostic reports (https://nodejs.org/api/report.html)
-report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
-
-# Runtime data
-pids
-*.pid
-*.seed
-*.pid.lock
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-*.lcov
-
-# nyc test coverage
-.nyc_output
-
-# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# Bower dependency directory (https://bower.io/)
-bower_components
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (https://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directories
-node_modules/
-jspm_packages/
-
-# Snowpack dependency directory (https://snowpack.dev/)
-web_modules/
-
-# TypeScript cache
-*.tsbuildinfo
-
-# Optional npm cache directory
-.npm
-
-# Optional eslint cache
-.eslintcache
-
-# Microbundle cache
-.rpt2_cache/
-.rts2_cache_cjs/
-.rts2_cache_es/
-.rts2_cache_umd/
-
-# Optional REPL history
-.node_repl_history
-
-# Output of 'npm pack'
-*.tgz
-
-# Yarn Integrity file
-.yarn-integrity
-
-# dotenv environment variables file
-.env
-.env.test
-
-# parcel-bundler cache (https://parceljs.org/)
-.cache
-.parcel-cache
-
-# Next.js build output
-.next
-out
-
-# Nuxt.js build / generate output
-.nuxt
-dist
-
-# Gatsby files
-.cache/
-# Comment in the public line in if your project uses Gatsby and not Next.js
-# https://nextjs.org/blog/next-9-1#public-directory-support
-# public
-
-# vuepress build output
-.vuepress/dist
-
-# Serverless directories
-.serverless/
-
-# FuseBox cache
-.fusebox/
-
-# DynamoDB Local files
-.dynamodb/
-
-# TernJS port file
-.tern-port
-
-# Stores VSCode versions used for testing VSCode extensions
-.vscode-test
-
-# yarn v2
-.yarn/cache
-.yarn/unplugged
-.yarn/build-state.yml
-.yarn/install-state.gz
-.pnp.*
-
-### Vim template
-# Swap
-[._]*.s[a-v][a-z]
-!*.svg # comment out if you don't need vector files
-[._]*.sw[a-p]
-[._]s[a-rt-v][a-z]
-[._]ss[a-gi-z]
-[._]sw[a-p]
-
-# Session
-Session.vim
-Sessionx.vim
-
-# Temporary
-.netrwhist
-# Auto-generated tag files
-tags
-# Persistent undo
-[._]*.un~
-
-### Windows template
-# Windows thumbnail cache files
-Thumbs.db
-Thumbs.db:encryptable
-ehthumbs.db
-ehthumbs_vista.db
-
-# Dump file
-*.stackdump
-
-# Folder config file
-[Dd]esktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Windows Installer files
-*.cab
-*.msi
-*.msix
-*.msm
-*.msp
-
-# Windows shortcuts
-*.lnk
-
-### SAM template
-# gitignore template for AWS Serverless Application Model project
-# website: https://docs.aws.amazon.com/serverless-application-model
-
-# Ignore build folder
-.aws-sam/
-
-### macOS template
-# General
-.DS_Store
-.AppleDouble
-.LSOverride
-
-# Icon must end with two \r
-Icon
-
-# Thumbnails
-._*
-
-# Files that might appear in the root of a volume
-.DocumentRevisions-V100
-.fseventsd
-.Spotlight-V100
-.TemporaryItems
-.Trashes
-.VolumeIcon.icns
-.com.apple.timemachine.donotpresent
-
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
-
-### Python template
-# Byte-compiled / optimized / DLL files
+# Python
__pycache__/
*.py[cod]
*$py.class
-
-# C extensions
*.so
-
-# Distribution / packaging
+.Python
build/
-develop-eggs/
dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-share/python-wheels/
*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-cover/
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-.pybuilder/
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-
-# pyenv
-# For a library or package, you might want to ignore these files since the code is
-# intended to run in multiple environments; otherwise, check them in:
-# .python-version
-
-# pipenv
-# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-# However, in case of collaboration, if having platform-specific dependencies or dependencies
-# having no cross-platform support, pipenv may install dependencies that don't work, or not
-# install all needed dependencies.
-#Pipfile.lock
-
-# PEP 582; used by e.g. github.com/David-OConnor/pyflow
-__pypackages__/
-
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-env/
+# Virtual Environments
+.venv/
venv/
ENV/
-env.bak/
-venv.bak/
+env/
-# Spyder project settings
-.spyderproject
-.spyproject
+# IDEs
+.vscode/
+.idea/
+*.code-workspace
-# Rope project settings
-.ropeproject
+# OS Files
+.DS_Store
+Thumbs.db
+*~
-# mkdocs documentation
-/site
+# Hugo
+/public/
+/resources/_gen/
+.hugo_build.lock
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
+# Node (if used)
+node_modules/
+npm-debug.log*
-# Pyre type checker
-.pyre/
+# AWS SAM
+.aws-sam/
-# pytype static type analyzer
-.pytype/
+# Local Development
+assets/
+.vale.ini
+.kiro
-# Cython debug symbols
-cython_debug/
+# Internal content (synced from internal repo)
+content/
+static/
+contentspec.yaml
+docs/
-### Local Development
+# Workshop Specific
!code/solutions/package-and-deploy/scripts
/code/solutions/package-and-deploy/lambda/pytz*/
/code/solutions/package-and-deploy/infrastructure-packaged.template
/code/solutions/package-and-deploy/response.json
-assets
-.vale.ini
-.kiro
diff --git a/.python-version b/.python-version
new file mode 100644
index 000000000..e4fba2183
--- /dev/null
+++ b/.python-version
@@ -0,0 +1 @@
+3.12
diff --git a/Makefile b/Makefile
index dde063d96..82bc4e78c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,19 @@
SHELL := /bin/bash
-.PHONY : help init test lint nag release clean
+.PHONY : help init test lint nag release clean sync
.DEFAULT: help
-VENV_NAME ?= venv
+VENV_NAME ?= .venv
PYTHON ?= $(VENV_NAME)/bin/python
+PUBLIC_REPO ?= ../cfn-workshop-github
help:
@echo "help get the full command list"
- @echo "init create VirtualEnv and install libraries"
+ @echo "init create VirtualEnv with uv and install libraries"
@echo "test run pre-commit checks"
@echo "lint GitHub actions cfn-lint test"
@echo "nag GitHub actions cfn-nag test"
+ @echo "sync sync files to public GitHub repo"
@echo "version [part=major||minor||patch] bump version and tag release (make version part=patch)"
@echo "release push new tag to release branch"
@echo "clean delete VirtualEnv and installed libraries"
@@ -21,14 +23,14 @@ init: $(VENV_NAME) pre-commit
$(VENV_NAME): $(VENV_NAME)/bin/activate
-$(VENV_NAME)/bin/activate: requirements.txt
- test -d $(VENV_NAME) || virtualenv -p python3 $(VENV_NAME)
- $(PYTHON) -m pip install -U pip
- $(PYTHON) -m pip install -Ur requirements.txt
- touch $(VENV_NAME)/bin/activate
+$(VENV_NAME)/bin/activate: pyproject.toml .python-version
+ uv venv --python-preference only-managed
+ uv pip install -r pyproject.toml
pre-commit: $(VENV_NAME)
- $(VENV_NAME)/bin/pre-commit install
+ # GIT_CONFIG=/dev/null is required for Amazon/AWS corporate machines to bypass
+ # internal Git configuration that interferes with pre-commit hook installation
+ GIT_CONFIG=/dev/null $(VENV_NAME)/bin/pre-commit install
# Tests
test: $(VENV_NAME)
@@ -53,3 +55,19 @@ release: # run on main branch only
clean:
rm -rf "$(VENV_NAME)"
find . -iname "*.pyc" -delete
+
+# Sync to public GitHub repo
+sync:
+ @echo "Syncing to public GitHub repo..."
+ @rsync -av --delete \
+ --exclude='.git/' \
+ --exclude='.venv/' \
+ --exclude='content/' \
+ --exclude='static/' \
+ --exclude='contentspec.yaml' \
+ --exclude='docs/' \
+ --exclude='.gitignore' \
+ --exclude='*.pyc' \
+ --exclude='__pycache__/' \
+ ./ $(PUBLIC_REPO)/
+ @echo "Sync complete!"
diff --git a/README.md b/README.md
index 17a3a0164..a206348d5 100644
--- a/README.md
+++ b/README.md
@@ -5,25 +5,44 @@ AWS CloudFormation - Workshop
-This repository provides all the resources referenced in the [CloudFormation](https://cfn101.workshop.aws/) workshop as
-well as the code used to build it.
+## Workshop Instructions
+
+**The full workshop instructions and content are available at [cfn101.workshop.aws](https://cfn101.workshop.aws/)**
+
+This repository provides the code templates and solutions referenced in the workshop. The workshop instruction files are maintained in AWS Workshop Studio and published to the workshop website. This GitHub repository contains only the code resources needed to complete the workshop labs.
## Usage
-1. Clone the repository to your working directory or Download the ZIP file from GitHub.
-2. Open the downloaded files in your code editor or IDE of your choice.
+1. Visit [cfn101.workshop.aws](https://cfn101.workshop.aws/) for the complete workshop instructions
+2. Clone this repository to your working directory or download the ZIP file from GitHub for the code templates
+3. Open the downloaded files in your code editor or IDE of your choice
-The working directory is located in [code/workspace](code/workspace) where you can follow along and write your code to.
+The working directory is located in [code/workspace](code/workspace) where you can follow along and write your code.
In the [code/solutions](code/solutions), you can find the completed solution for each lab. This can be used as a
reference, in case you get stuck or things don't work as intended.
-## Local development
-To set-up a local development environment for changing the workshop, please follow the instructions in
-[local development](docs/LOCAL_DEVELOPMENT.md) file.
-
## Contributing
-Contributions are more than welcome. Please read the [code of conduct](CODE_OF_CONDUCT.md) and the
-[contributing guidelines](CONTRIBUTING.md).
+
+Contributions to the code templates and solutions are welcome!
+
+### Local Development Setup
+
+To validate your changes locally before submitting a PR:
+
+```bash
+# Install uv (if not already installed)
+# See: https://docs.astral.sh/uv/getting-started/installation/
+
+# Set up environment and install dependencies
+make init
+
+# Run pre-commit checks on all files
+make test
+```
+
+The pre-commit hooks will automatically check your CloudFormation templates for linting issues, formatting, and best practices.
+
+For more details, please read the [code of conduct](CODE_OF_CONDUCT.md) and the [contributing guidelines](CONTRIBUTING.md).
## License
This library is licensed under the MIT-0 License. See the [license](LICENSE) file.
diff --git a/content/advanced/hooks/example-in-python/challenge/index.ja.md b/content/advanced/hooks/example-in-python/challenge/index.ja.md
deleted file mode 100644
index 622bea5f4..000000000
--- a/content/advanced/hooks/example-in-python/challenge/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Challenge"
-weight: 690
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/challenge/index.md b/content/advanced/hooks/example-in-python/challenge/index.md
deleted file mode 100644
index 488ff6434..000000000
--- a/content/advanced/hooks/example-in-python/challenge/index.md
+++ /dev/null
@@ -1,58 +0,0 @@
----
-title: "Challenge"
-weight: 690
----
-
-Previously on this lab, you've written unit tests to validate the core logic of your hook. One of the requirements you were given was to allow for a mechanism to ignore S3 buckets whose names are specified by the hook administrator in the hook's configuration. You've used contract tests and end-to-end tests to validate aspects for this use case: in this challenge, you are tasked to write unit test code for this use case.
-
-First, make sure you're in the `example-hook/` directory, as you'll need to run unit tests from there.
-
-Next, open the existing `src/examplecompany_s3_versioningenabled/tests/test_handlers.py` file. Your task is to append, at the end of the file, a new unit test method you'll write, called `test_when_s3_bucket_is_ignored_then_validation_always_succeeds()`, to assert that when you specify the `my-ignored-bucket,my-other-ignored-bucket` comma-delimited list as an input to the type configuration, the hook validation succeeds regardless of the versioning configuration for the bucket. When you write the unit test method, do not specify the versioning configuration in the resource properties input.
-
-Once you've written the new unit test method, run unit tests from the `example-hook/` directory, and make sure your new test passes as well.
-
-:::expand{header="Need a hint?"}
-- Look at the existing `test_when_s3_bucket_versioning_status_is_enabled_then_succeed()` test method; make a copy of it, and replace the method name in the method copy with `test_when_s3_bucket_is_ignored_then_validation_always_succeeds()`;
-- in the test method you just copied (see the hint above), is there something you'll need to add and to remove for the `resourceProperties` input?
-- Is there anything you need to add to `IgnoreS3BucketNames` further below?
-- Look at the assertion for the response's message: does it need to be updated?
-:::
-
-::::expand{header="Want to see the solution?"}
-Append the following content to the `src/examplecompany_s3_versioningenabled/tests/test_handlers.py` empty file you just created (add two empty lines before pasting the code below):
-
-:::code{language=python showLineNumbers=false showCopyAction=true}
-def test_when_s3_bucket_is_ignored_then_validation_always_succeeds() -> ( # noqa: D103 E501
- None
-):
- MOCK_BASE_HOOK_HANDLER_REQUEST.hookContext.targetModel = {
- "resourceProperties": {
- "BucketName": "my-other-ignored-bucket",
- },
- }
-
- response = handlers._run_pre_create_pre_update_common_checks(
- session=None,
- request=MOCK_BASE_HOOK_HANDLER_REQUEST,
- callback_context=MOCK_CALLBACK_CONTEXT,
- type_configuration=TypeConfigurationModel(
- IgnoreS3BucketNames="my-ignored-bucket,my-other-ignored-bucket",
- ),
- )
-
- assert response.message == "Ignoring versioning configuration."
- assert response.status == OperationStatus.SUCCESS
- assert response.errorCode is None
- assert response.callbackContext is None
- assert response.callbackDelaySeconds == 0
-:::
-
-Next, run the unit tests from the `example-hook/` directory to verify:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pytest --cov
-:::
-
-::::
-
-Choose **Next** to continue!
diff --git a/content/advanced/hooks/example-in-python/cleanup/index.ja.md b/content/advanced/hooks/example-in-python/cleanup/index.ja.md
deleted file mode 100644
index 896bdb379..000000000
--- a/content/advanced/hooks/example-in-python/cleanup/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Cleanup"
-weight: 695
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/cleanup/index.md b/content/advanced/hooks/example-in-python/cleanup/index.md
deleted file mode 100644
index 97c92d84d..000000000
--- a/content/advanced/hooks/example-in-python/cleanup/index.md
+++ /dev/null
@@ -1,147 +0,0 @@
----
-title: "Cleanup"
-weight: 695
----
-
-You'll start with deregistering your hook:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation deregister-type \
- --type-name ExampleCompany::S3::VersioningEnabled \
- --type HOOK \
- --region us-east-1
-:::
-
-Next, you'll delete the stack, created or updated for you by the CloudFormation CLI that you've used to submit the hook to the private registry, by first removing its termination protection:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-termination-protection \
- --no-enable-termination-protection \
- --stack-name examplecompany-s3-versioningenabled-role-stack \
- --region us-east-1
-:::
-
-Delete the stack mentioned above:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --stack-name examplecompany-s3-versioningenabled-role-stack \
- --region us-east-1
-
-aws cloudformation wait stack-delete-complete \
- --stack-name examplecompany-s3-versioningenabled-role-stack \
- --region us-east-1
-:::
-
-Next, before deleting objects from the artifacts bucket created by the `CloudFormationManagedUploadInfrastructure` stack (you've learned about it earlier on this lab), and the stack itself (if you'll choose to do so), you'll need to delete artifacts that you've generated as part of submitting the hook to the registry: this includes the ZIP archive for the hook's code. Start with identifying name of the S3 bucket that the managed upload infrastructure stack created for you:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --query "StackResources[?LogicalResourceId=='ArtifactBucket'].PhysicalResourceId" \
- --region us-east-1 \
- --output text
-:::
-
-Make a note of the bucket name returned by the command; for example, `cloudformationmanageduploadinfrast-artifactbucket-[...omitted...]`. Next, list the bucket's content:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3 ls s3://cloudformationmanageduploadinfrast-artifactbucket-[...omitted...]
-:::
-
-Make a note of the ZIP file for your hook, that should look like this: `examplecompany-s3-versioningenabled-YYYY-MM-DDTHH-MM-SS.zip`. The bucket where this object is stored has versioning enabled, and you'll need to get the object's version ID with this command (make sure to replace the name of the bucket and of the object):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3api list-object-versions \
- --bucket cloudformationmanageduploadinfrast-artifactbucket-[...omitted...] \
- --prefix examplecompany-s3-versioningenabled-YYYY-MM-DDTHH-MM-SS.zip \
- --query "Versions[*].VersionId" --output text
-:::
-
-Make a note of the version ID, that should look like this: `abcdEXAMPLEabcdEXAMPLEabcdEXAMPLE`; next, delete the object version by making sure to replace the bucket name, the object name, and the version ID:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3api delete-object \
- --bucket cloudformationmanageduploadinfrast-artifactbucket-[...omitted...] \
- --key examplecompany-s3-versioningenabled-YYYY-MM-DDTHH-MM-SS.zip \
- --version-id abcdEXAMPLEabcdEXAMPLEabcdEXAMPLE
-:::
-
-If you have performed more than one registry submission for your hook as part of this lab, you might find in the bucket more object(s), whose name start(s) with `examplecompany-s3-versioningenabled-`, and that you would want to remove as well in the same way as shown above.
-
-::alert[If you're currently using your AWS account to create CloudFormation extensions, you might find other objects in the S3 buckets managed by the `CloudFormationManagedUploadInfrastructure` stack (the artifact bucket, and the access log bucket as well), that you might choose to retain. If you wish to proceed with deleting this data and managed upload infrastructure, follow steps shown next; otherwise, skip the remaining part of this cleanup.]{type="warning"}
-
-Next, retrieve the name of the access log bucket:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --query "StackResources[?LogicalResourceId=='AccessLogsBucket'].PhysicalResourceId" \
- --region us-east-1 \
- --output text
-:::
-
-Make a note of the bucket name (example: `cloudformationmanageduploadinfra-accesslogsbucket--[...omitted...]`. List its content (replace the bucket name):
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3 ls s3://cloudformationmanageduploadinfra-accesslogsbucket--[...omitted...]
-:::
-
-As described on this [page](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerLogs.html#how-logs-delivered), Amazon S3 periodically collects and consolidates access logs when you enable server access logging for your bucket (that is, in this case, the bucket for artifacts using the logs bucket), and then uploads the logs to the target logging bucket. If you do not see objects in the logs bucket above at this time, there might be a chance, depending on your case, that logs might be delivered whilst you are attempting to delete the logs bucket later on, if you choose to do so. You cannot delete a bucket with objects in it; if this is the case, you'll get an error when deleting the stack that created the logs bucket: if you choose to delete logs in your logs bucket, use the same process you chose to use above for objects in the artifacts bucket, before (re)attempting to delete the bucket (or the stack that creates it; see steps below for more information).
-
-Next, update the `CloudFormationManagedUploadInfrastructure` stack's settings to disable the `DeletionPolicy: Retain` and `UpdateReplacePolicy: Retain` for both `AccessLogsBucket` and `EncryptionKey` resources. First, get the template for the stack, and save it to the `CloudFormationManagedUploadInfrastructure.template` file on your machine:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation get-template \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --query TemplateBody \
- --region us-east-1 \
- --output text > CloudFormationManagedUploadInfrastructure.template
-:::
-
-Open the `CloudFormationManagedUploadInfrastructure.template` file with your text editor, and:
-- replace all occurrences of `DeletionPolicy: Retain` with `DeletionPolicy: Delete`;
-- replace all occurrences of `UpdateReplacePolicy: Retain` with `UpdateReplacePolicy: Delete`.
-
-Save the updated template, and use it to update the stack next:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --template-body file://CloudFormationManagedUploadInfrastructure.template \
- --capabilities CAPABILITY_IAM \
- --region us-east-1
-
-aws cloudformation wait stack-update-complete \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --region us-east-1
-:::
-
-Delete the updated template copy on your machine:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-rm CloudFormationManagedUploadInfrastructure.template
-:::
-
-Remove the termination protection from the stack:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-termination-protection \
- --no-enable-termination-protection \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --region us-east-1
-:::
-
-Delete the stack:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --region us-east-1
-
-aws cloudformation wait stack-delete-complete \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --region us-east-1
-:::
-
-Almost done! Choose **Next** to continue!
diff --git a/content/advanced/hooks/example-in-python/conclusion/index.ja.md b/content/advanced/hooks/example-in-python/conclusion/index.ja.md
deleted file mode 100644
index 9b1b667af..000000000
--- a/content/advanced/hooks/example-in-python/conclusion/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Conclusion"
-weight: 699
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/conclusion/index.md b/content/advanced/hooks/example-in-python/conclusion/index.md
deleted file mode 100644
index 837821a13..000000000
--- a/content/advanced/hooks/example-in-python/conclusion/index.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "Conclusion"
-weight: 699
----
-
-Congratulations! You have built and tested a sample hook in Python! You've learned key concepts, expectations and objectives for you to keep in mind when writing your proactive validation controls with Hooks.
-
-You can see a list of hooks in the public CloudFormation registry when you navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/), choose **Registry** and then **Public extensions** from the left navigation bar, and then use the filters to list the available hooks.
-
-Also, you can find some existing hooks in the following repositories:
-- https://github.com/aws-cloudformation/community-registry-extensions
-- https://github.com/aws-cloudformation/aws-cloudformation-samples
diff --git a/content/advanced/hooks/example-in-python/end-to-end-test/index.ja.md b/content/advanced/hooks/example-in-python/end-to-end-test/index.ja.md
deleted file mode 100644
index 5559ae7fa..000000000
--- a/content/advanced/hooks/example-in-python/end-to-end-test/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "End-to-end test"
-weight: 680
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/end-to-end-test/index.md b/content/advanced/hooks/example-in-python/end-to-end-test/index.md
deleted file mode 100644
index 5ac4866dc..000000000
--- a/content/advanced/hooks/example-in-python/end-to-end-test/index.md
+++ /dev/null
@@ -1,279 +0,0 @@
----
-title: "End-to-end test"
-weight: 680
----
-
-Are you ready to test the hook you've worked on? For this, you'll prepare a sample CloudFormation template that describes an S3 bucket, and use it for your end-to-end tests.
-
-To get started, change directory to the `cfn101-workshop/code/workspace/hooks` directory; as you were in the `example-hook/` directory earlier, it's easier to just run this command to go to the parent directory, that is the one you need:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd ..
-:::
-
-Next, locate the `sample-s3-bucket.template` file; open it, and append the following content at the end of the file:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- VersioningConfiguration:
- Status: Enabled
-:::
-
-Next, from the directory where the file above is, use the AWS CLI to create a stack, in the `us-east-1` region, with that template:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name example-hook-test \
- --template-body file://sample-s3-bucket.template \
- --region us-east-1
-:::
-
-Next, wait for the stack creation to complete:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --stack-name example-hook-test \
- --region us-east-1
-:::
-
-When done, describe the stack events with this command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-events \
- --stack-name example-hook-test \
- --region us-east-1
-:::
-
-You should see a series of events, in JSON format, for your stack. The first block on the top of the output should have an element such as: `"ResourceStatus": "CREATE_COMPLETE"` for `"StackName": "example-hook-test"`, indicating that stack creation was successful. Scroll through the output using the down arrow key on your keyboard; you should see an event like the following excerpt:
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
- {
- "StackId": "[OMITTED]",
- "EventId": "[OMITTED]",
- "StackName": "example-hook-test",
- "LogicalResourceId": "S3Bucket",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::S3::Bucket",
- "Timestamp": "[OMITTED]",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "ExampleCompany::S3::VersioningEnabled",
- "HookStatus": "HOOK_COMPLETE_SUCCEEDED",
- "HookStatusReason": "Hook succeeded with message: Bucket versioning is enabled.",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookFailureMode": "FAIL"
- }
-:::
-
-As you can see, the hook has been invoked, and it verified the configuration of your bucket successfully! As you look through the events above this one, moving towards the top of the output, you can see that the bucket creation only started after the hook completed the validation of your bucket successfully. To exit the stack events view, press `q` key on your keyboard.
-
-Delete the stack you just created, and wait for its deletion to complete:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --stack-name example-hook-test \
- --region us-east-1
-
-aws cloudformation wait stack-delete-complete \
- --stack-name example-hook-test \
- --region us-east-1
-:::
-
-Let's now test that the hook blocks the provisioning (as you configured it to run in `FAIL` mode, per your requirements) when the S3 bucket is not configured to use versioning and the bucket name is not an ignored one. Update the `sample-s3-bucket.template` file, and change the value for `Status` from `Enabled` to `Suspended`:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
- Status: Suspended
-:::
-
-Next, use the AWS CLI to create the stack again, with the updated template:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name example-hook-test \
- --template-body file://sample-s3-bucket.template \
- --region us-east-1
-:::
-
-Next, wait for the operation to complete:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --stack-name example-hook-test \
- --region us-east-1
-:::
-
-In this case, the behavior you're looking for is that the stack will fail to create, because the hook will return an error. When the previous `wait` command returns back to the shell with a `StackCreateComplete failed` error, describe the stack events with this command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-events \
- --stack-name example-hook-test \
- --region us-east-1
-:::
-
-At the top of the output, you should first find an event where the stack is in the `ROLLBACK_COMPLETE` status. This means that the hook failed, as expected, because the S3 bucket was found not to be compliant, and the stack rolled back. To further validate that the hook behavior is the one you expect, scroll through the output, and you should see an event like the following excerpt:
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
- {
- "StackId": "[OMITTED]",
- "EventId": "[OMITTED]",
- "StackName": "example-hook-test",
- "LogicalResourceId": "S3Bucket",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::S3::Bucket",
- "Timestamp": "[OMITTED]",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "ExampleCompany::S3::VersioningEnabled",
- "HookStatus": "HOOK_COMPLETE_FAILED",
- "HookStatusReason": "Hook failed with message: Bucket versioning is not enabled.",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookFailureMode": "FAIL"
- }
-:::
-
-Congratulations! You have validated that the hook blocked the creation of a non-compliant bucket.
-
-Delete the stack you just created, and wait for its deletion to complete:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --stack-name example-hook-test \
- --region us-east-1
-
-aws cloudformation wait stack-delete-complete \
- --stack-name example-hook-test \
- --region us-east-1
-:::
-
-Let's go ahead and test the use case of an excluded bucket. First, let's establish a pattern for an S3 bucket name you'll use for testing, to reduce the possibility that a bucket name is already taken. The pattern you choose for the bucket name is: `example-hook-test-bucket-ACCOUNT_ID-REGION`, where `ACCOUNT_ID` is your AWS account number, and `REGION` is the region you'll choose for creating both the stack and the bucket. For more information on how to view your AWS account ID, see [View your AWS account ID
-](https://docs.aws.amazon.com/IAM/latest/UserGuide/console_account-alias.html#ViewYourAWSId); in this lab, you'll use the AWS CLI to get your account ID, by running the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws sts get-caller-identity \
- --query 'Account' \
- --output text
-:::
-
-You should get an output that looks like this example: `111122223333`.
-
-Let's compose the name of the bucket that you'll add to the comma-delimited string of ignored bucket names in the hook's configuration! For the AWS region, you'll continue to use `us-east-1`; with the example account ID above, your bucket to exclude would have the following name: `example-hook-test-bucket-111122223333-us-east-1`. Next, you'll update the configuration of the hook; do you recall the `typeConfiguration.json` file you created inside the `example-hook/` directory earlier in this lab? Change directory to `example-hook/`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd example-hook
-:::
-
-Open the `typeConfiguration.json` file, and replace its content with the following shown below (you'll add a new bucket to ignore: do not forget to replace `ACCOUNT_ID` for it, with the output you saw when you ran `aws sts get-caller-identity` above):
-
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "CloudFormationConfiguration": {
- "HookConfiguration": {
- "TargetStacks": "ALL",
- "FailureMode": "FAIL",
- "Properties": {
- "IgnoreS3BucketNames": "example-ignored-bucket,example-ignored-bucket1,example-hook-test-bucket-ACCOUNT_ID-us-east-1"
- }
- }
- }
-}
-:::
-
-Next, you'll update the type configuration for your hook (you already used this method to set the configuration for the hook earlier on in this lab). First, get the ARN for your hook like you did before:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation list-types \
- --type HOOK \
- --filters TypeNamePrefix=ExampleCompany::S3::VersioningEnabled \
- --query 'TypeSummaries[?TypeName==`ExampleCompany::S3::VersioningEnabled`].TypeArn' \
- --output text
-:::
-
-Take note of the resulting ARN for of your hook, and use it to update the type configuration as follows (do not forget to replace the `THE_ARN_OF_YOUR_HOOK` with the ARN for your hook, and to run the command below from the `example-hook/` directory):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation set-type-configuration \
- --configuration file://typeConfiguration.json \
- --type-arn 'THE_ARN_OF_YOUR_HOOK'
-:::
-
-Now that you've updated the configuration for your hook, you'll test it by first updating the template for your test S3 bucket, and by creating a new stack next. Change directory to the `cfn101-workshop/code/workspace/hooks` directory; as you are in the `example-hook/` directory, use the `cd ..` command to go to the parent directory:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd ..
-:::
-
-Locate the `sample-s3-bucket.template` file you used earlier. Open this file: add the whole `BucketName` line underneath the `Properties` node, and leave the `Status` as `Suspended` (as you left it as such in the previous test), as follows:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketName: !Sub 'example-hook-test-bucket-${AWS::AccountId}-${AWS::Region}'
- VersioningConfiguration:
- Status: Suspended
-:::
-
-Note that, in your template snippet above, for the account ID and for the region you chose to use the relevant CloudFormation [pseudo parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html), and you used the `Fn::Sub` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) (shown above in its YAML short form) to compose the resulting string for the bucket name.
-
-Next, use the AWS CLI to create a stack, in the `us-east-1` region, with this template:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name example-hook-test \
- --template-body file://sample-s3-bucket.template \
- --region us-east-1
-:::
-
-Next, wait for the stack creation to complete:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --stack-name example-hook-test \
- --region us-east-1
-:::
-
-When done, describe the stack events with this command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-events \
- --stack-name example-hook-test \
- --region us-east-1
-:::
-
-In this case, the behavior you're looking for is that the stack creation will succeed, because the hook will ignore the non-compliant bucket when it looks at the bucket's name. Scroll through the output; you should see an event like the following excerpt:
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
- {
- "StackId": "[OMITTED]",
- "EventId": "[OMITTED]",
- "StackName": "example-hook-test",
- "LogicalResourceId": "S3Bucket",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::S3::Bucket",
- "Timestamp": "[OMITTED]",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "ExampleCompany::S3::VersioningEnabled",
- "HookStatus": "HOOK_COMPLETE_SUCCEEDED",
- "HookStatusReason": "Hook succeeded with message: Ignoring versioning configuration.",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookFailureMode": "FAIL"
- }
-:::
-
-As the bucket name is in the list of ignored buckets, the validation passed regardless of its versioning configuration. You've validated this aspect as well!
-
-Delete the stack you just created, and wait for its deletion to complete:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --stack-name example-hook-test \
- --region us-east-1
-
-aws cloudformation wait stack-delete-complete \
- --stack-name example-hook-test \
- --region us-east-1
-:::
-
-Are you ready for a challenge? Choose **Next** to continue!
diff --git a/content/advanced/hooks/example-in-python/index.ja.md b/content/advanced/hooks/example-in-python/index.ja.md
deleted file mode 100644
index b22d3ef9a..000000000
--- a/content/advanced/hooks/example-in-python/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Custom Hooks"
-weight: 620
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/index.md b/content/advanced/hooks/example-in-python/index.md
deleted file mode 100644
index 2edacf527..000000000
--- a/content/advanced/hooks/example-in-python/index.md
+++ /dev/null
@@ -1,69 +0,0 @@
----
-title: "Custom Hooks"
-weight: 620
----
-
-### Overview
-::alert[You have the choice to register your hook as a private or as a public extension in the CloudFormation registry: this lab covers private extension examples.]{type="info"}
-
-When you submit a private extension (such as a module, a resource type, or a hook), you make it available in the CloudFormation registry in your AWS account for a given AWS region: private extensions give you the ability to test the behavior of your resource type in a sandbox environment, such as in an AWS account you own, and that you use for testing/experimentation. Another use case for having a private extension is for validation logic that is company-specific or proprietary.
-
-For more information on private extensions, see [Using private extensions in CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-register.html). For more information on public extensions, see [Publishing extensions to make them available for public use](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/publish-extension.html).
-
-::alert[Please refer to [AWS CloudFormation pricing](https://aws.amazon.com/cloudformation/pricing/) for information on charges to your account when you use hooks.]{type="info"}
-
-
-### Key concepts
-
-Key concepts for developing a hook include:
-
-* [model](https://docs.aws.amazon.com/cloudformation-cli/latest/hooks-userguide/hooks-model.html): a document where you describe which resource type (or types) you wish to trigger a hook invocation, and at which lifecycle phase (pre-create, pre-update, or pre-delete). Moreover, if you plan to make AWS API calls from your hook to make additional validation checks, you can also specify the relevant permissions you need in the model;
-* [handlers](https://docs.aws.amazon.com/cloudformation-cli/latest/hooks-userguide/hooks-model.html#model-hook-project-add-handler): the invocation points for your hook: at least one of `preCreate`, `preUpdate`, or `preDelete` is required.
-
-In this lab, you'll follow steps to build and submit a custom hook, that you'll write in Python, to the AWS CloudFormation registry in your AWS account for a given AWS region as a private extension. You'll also navigate through the example source code implementation logic for the hook, to understand key concepts and best practices.
-
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* understand key concepts to develop a hook;
-* use the [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) to create a new project for a hook, run tests, and submit the hook as a private extension to the CloudFormation registry in your AWS account and for a given region;
-* understand how to use the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) to test your hook locally.
-
-
-### Start Lab
-
-Let's get started! Make believe you are a member of the security team for an example organization. You're tasked with creating a hook to validate that [Amazon Simple Storage Service (Amazon S3)](https://aws.amazon.com/s3/) bucket resources that your AWS account users create with CloudFormation, are set up with [versioning configuration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html#cfn-s3-bucket-versioningconfiguration) enabled. For this task, you choose to use CloudFormation Hooks as a proactive validation control: you'll create a hook to enforce versioning being enabled on S3 buckets that your users describe with CloudFormation templates, and that manage with relevant CloudFormation stacks.
-
-Your first step is to use the [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) -that you've installed in the prerequisites section- to create a project for your hook. Change directory to the `cfn101-workshop/code/workspace/hooks` directory: use the following commands to create a new directory for your project, and move into it next:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mkdir example-hook
-cd example-hook
-:::
-
-Next, use the CloudFormation CLI to create a new project for your hook; you'll be asked a number of questions - for that, you'll follow through next on this lab:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn init
-:::
-
-When prompted:
-
-- specify `h`, followed by enter, to indicate your choice of developing a new hook;
-- for the name of your hook, choose to specify: `ExampleCompany::S3::VersioningEnabled`, followed by pressing the _enter_ (or _return_ key) on your keyboard;
-- follow the directions to choose `python39`, and use the _enter_ (or _return_ key) to continue;
-- when asked to use Docker for platform-independent packaging, choose `Y` followed by the _enter_ (or _return_ key).
-
-At this point, you should see a message indicating your project has been initialized. The CloudFormation CLI has created for you a number of files and directories that include, in particular:
-
-- `.rpdk-config`: this is the project's configuration file, that contains a number of information including information on the language name (`"language": "python39",`) and the runtime (`"runtime": "python3.9",`) choices you've made. In the future, as new runtimes are made available, you might want to update both information, and then test and resubmit the hook to the registry.
-- `README.md`: this in an automatically-generated file, that you'd want to update as needed for other members of the team to learn about this hook.
-- `docs/`: a directory with automatically-generated documentation content. As you develop your hook, you'll want to use the `cfn generate` command to refresh content for this directory, as well as for other parts of the hook you're building.
-- `examplecompany-s3-versioningenabled.json`: this is the schema model file, named after your hook: you'll start with updating this file as your next step.
-- `hook-role.yaml`: this file is automatically created or regenerated when you run the `cfn generate` command. The CloudFormation CLI creates this file for you based on permissions you specify in the schema; when you use the CloudFormation CLI to submit your hook to the registry, it creates or updates a CloudFormation stack with this template that describes an IAM execution role for your hook.
-- `src/`: a directory with files that you'll use to implement the business logic of your hook.
-- `template.yml`: an auto-generated file for the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-reference.html#serverless-sam-cli), that you'll use to test your hook locally. Note that this file also contains runtime information (`Runtime: python3.9` for both `TypeFunction` and `TestEntrypoint`), that in the future you might want to update as well as needed (see considerations made above for the `.rpdk-config` file).
-
-Are you ready to get the functional requirements for the hook you'll build? Choose **Next** to continue!
diff --git a/content/advanced/hooks/example-in-python/model-your-hook/index.ja.md b/content/advanced/hooks/example-in-python/model-your-hook/index.ja.md
deleted file mode 100644
index d18a8beb6..000000000
--- a/content/advanced/hooks/example-in-python/model-your-hook/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Model your hook"
-weight: 630
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/model-your-hook/index.md b/content/advanced/hooks/example-in-python/model-your-hook/index.md
deleted file mode 100644
index fc853c809..000000000
--- a/content/advanced/hooks/example-in-python/model-your-hook/index.md
+++ /dev/null
@@ -1,62 +0,0 @@
----
-title: "Model your hook"
-weight: 630
----
-
-So far, you've used the CloudFormation CLI to start the structure of a new project for your hook. The security team of an example company now gives you the functional requirements for the example control you'll build:
-
-- your hook will need to be invoked when users, in the current AWS account and AWS region, create or update S3 buckets using CloudFormation. That is, when users in the account describe resources of the `AWS::S3::Bucket` [type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html) in CloudFormation templates they author, and use such templates to create or update CloudFormation stacks to, in turn, create or update S3 buckets;
-- if a non-compliant S3 bucket resource is found, treat this as an error, and signal to CloudFormation that the bucket cannot be created or updated;
-- the hook should also have a configuration for the account administrator to use, to ignore buckets with a given name should edge cases require an S3 bucket not to be using the versioning feature.
-
-Next, you'll use the requirements above to model your hook using the schema file in JSON that you've read about in the previous page on this lab. To get started, open the `examplecompany-s3-versioningenabled.json` file, and replace its content with the following:
-
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "typeName": "ExampleCompany::S3::VersioningEnabled",
- "description": "Example hook to validate that versioning is enabled for Amazon S3 buckets.",
- "sourceUrl": "https://catalog.workshops.aws/cfn101/en-US/advanced/hooks",
- "documentationUrl": "https://catalog.workshops.aws/cfn101/en-US/advanced/hooks",
- "typeConfiguration": {
- "properties": {
- "IgnoreS3BucketNames": {
- "description": "Comma-delimited string of Amazon S3 bucket names to exclude from versioning validation setting checks. Don't add space characters. Leave the value for this property empty (\"\") if you plan on not using it. Otherwise, make sure you specify value(s) conforming to S3 bucket naming rules (https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html). If you plan to use this property, specify values as in following examples: \"mybucket\", or \"my-bucket-1,my-bucket-2\". Do not add a trailing comma(s).",
- "default": "",
- "pattern": "^([a-z0-9][a-z0-9//.//-]*[a-z0-9]){0,1}$|^([a-z0-9][a-z0-9//.//-]*[a-z0-9]){1}(,[a-z0-9][a-z0-9//.//-]*[a-z0-9])*$",
- "type": "string"
- }
- },
- "additionalProperties": false
- },
- "required": [],
- "handlers": {
- "preCreate": {
- "targetNames": [
- "AWS::S3::Bucket"
- ],
- "permissions": []
- },
- "preUpdate": {
- "targetNames": [
- "AWS::S3::Bucket"
- ],
- "permissions": []
- }
- },
- "additionalProperties": false
-}
-:::
-
-Save the updated file. As you can see, you're modeling the `IgnoreS3BucketNames` input configuration property to allow for edge-case exceptions as per the requirements, and you're targeting `AWS::S3::Bucket` resources to be examined by your hook before you create (`preCreate` handler), or update (`preUpdate` handler) a CloudFormation stack. In the schema above, you could also have added a configuration for a `preDelete` handler (which is another available invocation point for Hooks): in this case, you choose not to use this additional control as per requirements above, that are only relevant to when resources are being created or mutated, but not deleted.
-
-::alert[With this example hook, you only plan to inspect S3 buckets' configuration values coming from the CloudFormation template when your hook is invoked. This information will be exposed to the hook automatically, and you don't need to make any API calls to AWS service(s) from your hook to retrieve bucket configuration values: this is why you are passing empty lists to the `permissions` properties in the schema above. If you would have needed to make API calls to AWS services from your hook's handler(s), you would have also needed to indicate which IAM permission(s) (for example: `s3:ListBuckets`) you required.]{type="info"}
-
-For more information on the schema of a hook, and on modeling options, see [Modeling AWS CloudFormation Hooks](https://docs.aws.amazon.com/cloudformation-cli/latest/hooks-userguide/hooks-model.html).
-
-Now that you've updated the schema that models your hook, it's time to refresh the documentation for your hook in the `docs/` directory and, as applicable, the content of the `hook-role.yaml` template file. Run the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn generate
-:::
-
-It's now time to write code for your hook! Choose **Next** to continue!
diff --git a/content/advanced/hooks/example-in-python/register-your-hook/index.ja.md b/content/advanced/hooks/example-in-python/register-your-hook/index.ja.md
deleted file mode 100644
index 290c48bd4..000000000
--- a/content/advanced/hooks/example-in-python/register-your-hook/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Register your hook"
-weight: 670
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/register-your-hook/index.md b/content/advanced/hooks/example-in-python/register-your-hook/index.md
deleted file mode 100644
index 4e5672234..000000000
--- a/content/advanced/hooks/example-in-python/register-your-hook/index.md
+++ /dev/null
@@ -1,68 +0,0 @@
----
-title: "Register your hook"
-weight: 670
----
-
-For you to use your hook with CloudFormation, you first need to submit it to the registry as a private extension. You can, subsequently, also choose to make your hook public, but we'll not cover this in this lab.
-
-When you submit a hook to the registry, you register the hook in a given AWS account and region: if you need to make the hook available in another account or region, you'll need to make a separate submission to the registry for that. Alternatively, you can use [AWS CloudFormation StackSets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/what-is-cfnstacksets.html) to submit the hook across regions and accounts by using a CloudFormation template where you describe, with code, the intent of submitting the hook to the registry using [CloudFormation resource types](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_CloudFormation.html) such as `AWS::CloudFormation::HookVersion`, `AWS::CloudFormation::HookDefaultVersion`, and `AWS::CloudFormation::HookTypeConfig`. In this lab, you'll use the CloudFormation CLI to submit your hook to the registry for a given region.
-
-To submit your hook to the `us-east-1` region with the CloudFormation CLI, use the following command from the `example-hook/` directory:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn submit --set-default --region us-east-1
-:::
-
-At the end of the process, you should get a message indicating that version `00000001` of your hook has been registered, and set as the default version.
-
-When you use the CloudFormation CLI with the `cfn submit` command above to submit extensions to the CloudFormation registry (hooks, resource types, and modules), it'll create or update a CloudFormation stack in your account and for the region you're using, so to manage on your behalf a number of resources needed to submit an extension to the registry. This stack is called `CloudFormationManagedUploadInfrastructure`. Moreover, when you work with hooks or with resource types, the CloudFormation CLI also creates or updates another stack, whose name prefix is derived from the extension's name (in your case, the name of the stack will be `examplecompany-s3-versioningenabled-role-stack`), to create or update the execution role for the extension by using the CloudFormation template generated by the CloudFormation CLI (in your case, `hook-role.yaml`) that you've learned about earlier on this lab.
-
-As this is the first time that you're submitting the hook to the registry, as the hook administrator persona you'll need to configure the hook after you submitted it to the registry. You can also configure the hook any time you need, should its configuration settings require an update to reflect your needs in the future.
-
-Let's configure the hook! Create, inside the `example-hook/` directory, a file called `typeConfiguration.json` (like the one you created in your `.cfn-cli/` directory earlier):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch typeConfiguration.json
-:::
-
-Next, open the `typeConfiguration.json` file you just created inside the `example-hook/` directory, and add the following content to it:
-
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "CloudFormationConfiguration": {
- "HookConfiguration": {
- "TargetStacks": "ALL",
- "FailureMode": "FAIL",
- "Properties": {
- "IgnoreS3BucketNames": "example-ignored-bucket,example-ignored-bucket1"
- }
- }
- }
-}
-:::
-
-::alert[In the example above, you've used `FAIL` for `FailureMode`. This is because as part of your requirements -and as part of how you'd want a hook to typically work- you want to treat compliance failures as errors that will prevent a given operation (such as, create, update, or delete) to run. If you wish to just simply emit a warning that will non prevent the provisioning of a non-compliant resource, use `WARN` instead of `FAIL`; you might only want to use `WARN` for limited use cases, such as -for example- to avoid preventing the provisioning of valid workloads in your sandbox account as you develop and test your hook with CloudFormation stacks, or if you want to give your account users a compliance deadline before you'll turn the setting to `FAIL`.]{type="warning"}
-
-Next, you'll use the [AWS Command Line Interface](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/index.html) (and not the CloudFormation CLI in this case) to set the type configuration for your hook. First, you'll get the [Amazon Resource Name (ARN)](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) for your hook:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation list-types \
- --type HOOK \
- --filters TypeNamePrefix=ExampleCompany::S3::VersioningEnabled \
- --query 'TypeSummaries[?TypeName==`ExampleCompany::S3::VersioningEnabled`].TypeArn' \
- --output text
-:::
-
-The command above should have returned the ARN of your hook, that uses the following format: `arn:aws:cloudformation:us-east-1:YOUR_ACCOUNT_ID:type/hook/ExampleCompany-S3-VersioningEnabled`; use this ARN to set up the type configuration as follows, by replacing `THE_ARN_OF_YOUR_HOOK` with the ARN you just retrieved:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation set-type-configuration \
- --configuration file://typeConfiguration.json \
- --type-arn 'THE_ARN_OF_YOUR_HOOK'
-:::
-
-At the end of the process, you should get `ConfigurationArn` as the output, indicating information for the type configuration you've just set.
-
-Congratulations! You just submitted to the registry, and configured your hook as the hook administrator persona! This concludes the first of the two workflows you learned about at the beginning of this lab. Are you ready to test the hook with CloudFormation, and see what you users would see in a variety of scenarios you'll test?
-
-Choose **Next** to continue!
diff --git a/content/advanced/hooks/example-in-python/write-code/index.ja.md b/content/advanced/hooks/example-in-python/write-code/index.ja.md
deleted file mode 100644
index bebacb5f7..000000000
--- a/content/advanced/hooks/example-in-python/write-code/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Write code"
-weight: 640
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/write-code/index.md b/content/advanced/hooks/example-in-python/write-code/index.md
deleted file mode 100644
index 4a21e8255..000000000
--- a/content/advanced/hooks/example-in-python/write-code/index.md
+++ /dev/null
@@ -1,327 +0,0 @@
----
-title: "Write code"
-weight: 640
----
-
-When you used the CloudFormation CLI to generate the project for your hook, it also created some files and directories in the `src/` directory. You'll next focus on inspecting and editing the content of the `handlers.py` file in the `src/examplecompany_s3_versioningenabled/` directory, to add the business logic for the proactive control you're implementing with your hook.
-
-::alert[When you inspect the content of the `src/examplecompany_s3_versioningenabled/` directory, you'll see a number of files that are managed by the CloudFormation CLI when you run the `cfn generate` command (that you've already used earlier): for example, the `models.py` file and files in the `target_models` directory. Do not manually change these files or content, as they'll be overwritten by the CloudFormation CLI when you'll run `cfn generate`.]{type="warning"}
-
-Open the `handlers.py` file mentioned above: the content of this file has been automatically generated for you when you used the CloudFormation CLI to create the project for your hook. Familiarize with the structure of the file: you'll see 3 methods, `pre_create_handler()`, `pre_update_handler()`, and `pre_delete_handler()` that are decorated, respectively, with the following wrappers:
-
-- `@hook.handler(HookInvocationPoint.CREATE_PRE_PROVISION)`
-- `@hook.handler(HookInvocationPoint.UPDATE_PRE_PROVISION)`
-- `@hook.handler(HookInvocationPoint.DELETE_PRE_PROVISION)`
-
-The intent is to have each of these methods above being called for a relevant event: for example, `pre_create_handler()` to be called when the hook is invoked for a given S3 bucket on stack creation. Each of these methods will need to have the business logic -written by you, in this case- to analyze the properties for a given resource (S3 bucket, in your case), that are described by users in a CloudFormation template.
-
-Each of the methods above must return a properly-configured `ProgressEvent` object on events such as a successful verification of resource properties (`OperationStatus.SUCCESS`: your resource is compliant), or a failure (`OperationStatus.FAILED`: your resource is not compliant), so that CloudFormation understands what to do next.
-
-Per requirements you received, you'll only want to invoke your hook on pre-create and pre-update events. This means that:
-
-- you can remove the pre-delete method and logic, that you won't need for your use case, and
-- you can conveniently use one single, shared method for both pre-create and pre-update operations in your use case: this way, you can efficiently maintain the business logic code in one place.
-
-How can you consume, from the business logic of a given handler method, the resource properties coming from a CloudFormation template? When you look at the input parameters for methods above, you'll see the `request` parameter: first, you get the target model of the resource (S3 bucket in your case) from `request.hookContext.targetModel`, and then you can consume `resourceProperties` from the target model.
-
-The boilerplate code also passes in, as an input parameter, `callback_context`. Typically, you'd use this parameter if the operations you run in your handler code take more than 30 seconds, _as hooks time out after 30 seconds_. You set up the callback context to persist values you need to read the current state in a subsequent reinvocation of the current handler. To signal the intent of calling back the current handler, you set `status` to `OperationStatus.IN_PROGRESS`, `callbackContext` to the value(s) you need, and optionally `callbackDelaySeconds` in the `ProgressEvent` object that you return from the handler's code. You won't use this functionality in the hook you're building.
-
-As you continue to look at the boilerplate code, you also note the `type_configuration` input parameter for each of the methods mentioned above: you'll use this parameter from the business logic of your code to consume the optional hook configuration value(s) (in your case, `IgnoreS3BucketNames`), that you've already modeled in the schema earlier.
-
-Before implementing the logic you need, note that the boilerplate code also has the following example snippet:
-
-:::code{language=python showLineNumbers=false showCopyAction=false}
- if isinstance(session, SessionProxy):
- client = session.client("s3")
-:::
-
-The example above shows you how to properly create, for a hook, an SDK client (in your example, an S3 client), by using a pre-vended session proxy. You use an SDK client from a hook's code only if you need to make AWS API calls to a given AWS service (should this be the case, you'll also want to add the necessary IAM permissions to the schema for your hook). You won't need this functionality for the hook you'll build, but it's worth mentioning this important aspect anyway, as you might need it in your hooks for use cases that require verification checks that go beyond static code analysis.
-
-Let's implement the create and update handler logic! You'll use one shared entrypoint method, with both the pre-create and pre-update decorations. Replace the entire content of the `handlers.py` file with the following:
-
-:::code{language=python showLineNumbers=false showCopyAction=true}
-"""Example hook to validate versioning is enabled for an Amazon S3 bucket."""
-
-import logging
-from typing import (
- Any,
- List,
- Mapping,
- MutableMapping,
- Optional,
-)
-
-from cloudformation_cli_python_lib import ( # type: ignore
- HandlerErrorCode,
- Hook,
- HookInvocationPoint,
- OperationStatus,
- ProgressEvent,
- SessionProxy,
-)
-
-from .models import (
- HookHandlerRequest,
- TypeConfigurationModel,
-)
-
-
-# Use this logger to forward log messages to CloudWatch Logs.
-LOG = logging.getLogger(__name__)
-TYPE_NAME = "ExampleCompany::S3::VersioningEnabled"
-
-hook = Hook(TYPE_NAME, TypeConfigurationModel)
-test_entrypoint = hook.test_entrypoint
-
-
-@hook.handler(HookInvocationPoint.CREATE_PRE_PROVISION)
-@hook.handler(HookInvocationPoint.UPDATE_PRE_PROVISION)
-def pre_create_pre_update_common_handler(
- session: Optional[SessionProxy],
- request: HookHandlerRequest,
- callback_context: MutableMapping[str, Any],
- type_configuration: TypeConfigurationModel,
-) -> ProgressEvent:
- """Use a common method for pre-create and pre-update validations."""
- return _run_pre_create_pre_update_common_checks(
- session=session,
- request=request,
- callback_context=callback_context,
- type_configuration=type_configuration,
- )
-
-
-def _run_pre_create_pre_update_common_checks(
- session: Optional[SessionProxy],
- request: HookHandlerRequest,
- callback_context: MutableMapping[str, Any],
- type_configuration: TypeConfigurationModel,
-) -> ProgressEvent:
- """Run common checks for pre-create and pre-update validations."""
- try:
- progress = ProgressEvent(status=OperationStatus.IN_PROGRESS)
-
- # Read the target properties of the S3 bucket.
- resource_properties = None
- target_model = _get_target_model(
- request=request,
- )
- if target_model:
- resource_properties = _get_resource_properties(
- target_model=target_model,
- )
-
- # Return a failure immediately if there are no S3 bucket
- # properties defined in the template.
- if resource_properties is None:
- message = "The S3 bucket has no properties set."
- LOG.error(message)
- progress.status = OperationStatus.FAILED
- progress.message = message
- progress.errorCode = HandlerErrorCode.NonCompliant
- return progress
-
- # Consume the IgnoreS3BucketNames type configuration
- # directive, and return success if the user specifies a bucket
- # name that is ignored in the directive.
- if (
- hasattr(
- type_configuration,
- "IgnoreS3BucketNames",
- )
- and type_configuration.IgnoreS3BucketNames != ""
- ):
- bucket_name = _get_bucket_name(
- resource_properties=resource_properties,
- )
- if bucket_name:
- ignore_s3_bucket_names_list = _get_ignore_s3_bucket_names_list(
- type_configuration
- )
- if bucket_name in ignore_s3_bucket_names_list:
- message = "Ignoring versioning configuration."
- LOG.info(message)
- # Set status to success to signal that the
- # validation is successful, and return progress.
- progress.status = OperationStatus.SUCCESS
- progress.message = message
- return progress
-
- # If the bucket is not in the list of buckets to ignore,
- # proceed with the validation: start with checking if the
- # VersioningConfiguration property is set.
- versioning_configuration = _get_versioning_configuration(
- resource_properties=resource_properties,
- )
- if versioning_configuration is None:
- message = "The VersioningConfiguration property value is missing."
- LOG.error(message)
- progress.status = OperationStatus.FAILED
- progress.message = message
- progress.errorCode = HandlerErrorCode.NonCompliant
- return progress
- else:
- # Check if the Status property for VersioningConfiguration
- # is set to Enabled.
- versioning_configuration_status = (
- _get_versioning_configuration_status(
- versioning_configuration=versioning_configuration,
- )
- )
- if (
- versioning_configuration_status
- and versioning_configuration_status == "Enabled"
- ):
- message = "Bucket versioning is enabled."
- LOG.info(message)
- progress.status = OperationStatus.SUCCESS
- progress.message = message
- return progress
-
- # Fail the validation by default if the code execution did not
- # succeed above.
- message = "Bucket versioning is not enabled."
- LOG.error(message)
- progress.status = OperationStatus.FAILED
- progress.message = message
- progress.errorCode = HandlerErrorCode.NonCompliant
- return progress
- except Exception as exception:
- LOG.error(exception)
- progress.status = OperationStatus.FAILED
- progress.message = str(exception)
- progress.errorCode = HandlerErrorCode.InternalFailure
- return progress
-
-
-def _get_target_model(
- request: HookHandlerRequest,
-) -> Optional[Mapping[str, Any]]:
- """Return the target model of the resource from the request."""
- return request.hookContext.targetModel
-
-
-def _get_resource_properties(
- target_model: Optional[Mapping[str, Any]],
-) -> Any:
- """Return the resource properties from the target model."""
- return (
- target_model.get("resourceProperties")
- if target_model and target_model.get("resourceProperties")
- else None
- )
-
-
-def _get_ignore_s3_bucket_names_list(
- type_configuration: TypeConfigurationModel,
-) -> List[str]:
- """Return a list of items from type_configuration.IgnoreS3BucketNames."""
- # Remove spaces on assignment for ignore_s3_bucket_names.
- ignore_s3_bucket_names = (
- type_configuration.IgnoreS3BucketNames.replace(" ", "")
- if type_configuration.IgnoreS3BucketNames
- else ""
- )
-
- # Remove any list item that is an empty string when creating a
- # list of bucket names to ignore from IgnoreS3BucketNames in the
- # type configuration.
- return list(
- filter(
- None,
- ignore_s3_bucket_names.split(","),
- )
- )
-
-
-def _get_bucket_name(
- resource_properties: Any,
-) -> Any:
- """Return the bucket name from the resource properties."""
- # Remove spaces, if any, as well.
- return (
- resource_properties.get("BucketName").replace(" ", "")
- if resource_properties and resource_properties.get("BucketName")
- else None
- )
-
-
-def _get_versioning_configuration(
- resource_properties: Any,
-) -> Any:
- """Return the versioning configuration from the resource properties."""
- return (
- resource_properties.get("VersioningConfiguration")
- if resource_properties
- and resource_properties.get("VersioningConfiguration")
- else None
- )
-
-
-def _get_versioning_configuration_status(
- versioning_configuration: Any,
-) -> Any:
- """Return the status from the versioning configuration."""
- return (
- versioning_configuration.get("Status")
- if versioning_configuration and versioning_configuration.get("Status")
- else None
- )
-:::
-
-Save the file, and take a look at the code: can you recognize some of the implementation aspects that relate to the requirements you were given, for example: the code that checks if a bucket is ignored from the validation logic, if its name is in an input list maintained by the hook's administrator?
-
-Also, note how the outer structure of the input data is validated. When you describe an S3 bucket with a CloudFormation template, for it to pass the validation above it needs to look like the following snippet:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-AWSTemplateFormatVersion: 2010-09-09
-Description: Example S3 bucket.
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- VersioningConfiguration:
- Status: Enabled
-:::
-
-As you traverse the `Properties` tree above, you write the logic to validate that `Status`, for `VersioningConfiguration`, is set to `Enabled`. What if the `Properties` node above is missing though, or what if the `VersioningConfiguration` node underneath it is missing instead? The hook's business logic above also checks for these specific cases, and returns targeted error messages to the end user for them to easily pinpoint the relevant error.
-
-As part of the prerequisites for running this lab, you've installed tools such as [mypy](https://github.com/python/mypy), a static type checker for Python, and [flake8](https://flake8.pycqa.org/en/latest/) for linting Python code. You'll use both tools in this lab as examples to check the code for the hook you're building.
-
-::alert[You're not required to use `mypy` and `flake8` for your hook code to work. This lab shows an example usage of such tools in the context of the sample Python code for the hook you're building; you can choose to use tools and configurations you need or prefer in your projects.]{type="info"}
-
-First, let's configure your hook's project settings for `mypy`. Create a `mypy.ini` configuration file for your hook project as follows (make sure you are in the `example-hook/` directory):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch mypy.ini
-:::
-
-When done, add this content to the `mypy.ini` file you just created:
-
-:::code{language=text showLineNumbers=false showCopyAction=true}
-[mypy]
-follow_imports = silent
-
-strict = True
-:::
-
-Next, run `mypy` against your `handlers.py` file (make sure you are in the `example-hook/` directory):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mypy src/examplecompany_s3_versioningenabled/handlers.py
-:::
-
-You should see an output indicating no errors. Next, run `flake8` against the same file:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-flake8 \
- --docstring-convention pep257 \
- --ignore=W503,W504 \
- --max-complexity=10 \
- --max-line-length=79 \
- src/examplecompany_s3_versioningenabled/handlers.py
-:::
-
-You should see no output messages, indicating no errors have occurred. As part of the example set of command options for `flake8` above, note the `max-complexity=10` directive, that uses the `mccabe` [plugin](https://flake8.pycqa.org/en/latest/user/options.html#cmdoption-flake8-max-complexity) for McCabe's [cyclomatic complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity) metric to check if the code, at the method level for example, exceeds an example cyclomatic complexity value of `10` when it takes a number of paths: you use this check to measure how complex the structure of your code is, and you can choose to use this indicator as an opportunity to improve the code you write so that it is easier to maintain over time. A practical example would be to break down methods into smaller, specialized functions you can easily maintain -and reuse, as needed- in your code that, overall, will be more readable.
-
-Next, you'll write some tests for your hook's logic, so that you'll have the opportunity to run these tests locally to speed up the development loop. Choose **Next** to continue!
diff --git a/content/advanced/hooks/example-in-python/write-contract-tests/index.ja.md b/content/advanced/hooks/example-in-python/write-contract-tests/index.ja.md
deleted file mode 100644
index 922cd2633..000000000
--- a/content/advanced/hooks/example-in-python/write-contract-tests/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Write contract tests"
-weight: 660
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/write-contract-tests/index.md b/content/advanced/hooks/example-in-python/write-contract-tests/index.md
deleted file mode 100644
index 497ef6d01..000000000
--- a/content/advanced/hooks/example-in-python/write-contract-tests/index.md
+++ /dev/null
@@ -1,162 +0,0 @@
----
-title: "Write contract tests"
-weight: 660
----
-
-Contract tests help you test your hook locally, thus speeding up the development lifecycle. Moreover, if you plan to make your hook available as a public extension, it is required for it to pass contract tests.
-
-While you're not required to pass contract tests for a privately-registered hook -like the one you're working on- it is recommended to strive to write and pass contract tests anyway: not only this helps you with development velocity, but also it helps maintaining a higher quality bar.
-
-To get started, first create the following files in an `inputs/` directory you'll also create at the root level of your hook's project; make sure you run the following commands from the `example-hook/` directory:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mkdir inputs/
-touch inputs/inputs_1_pre_create.json
-touch inputs/inputs_1_pre_update.json
-touch inputs/inputs_1_invalid.json
-touch inputs/inputs_2_pre_create.json
-touch inputs/inputs_2_pre_update.json
-touch inputs/inputs_2_invalid.json
-:::
-
-As you can see above, for this hook you chose to use two series of contract tests, denoted by `inputs_1_` and `inputs_2_` file prefixes. Each series will have different permutations of inputs that you'll pass to your hook, to validate that it will work as you expect across different scenarios.
-
-You'll cover 2 test cases (recall the requirements you were given, as you read through): a bucket with a generic name (or with no specified name) being tested, and a bucket with a specific name that will cause it to be ignored from being validated. In the first case, the bucket is expected to pass validation on pre-create and pre-update if versioning is enabled for it in its configuration; in the second case, the bucket is expected to pass validation if its name is one of the ignored buckets in the hook's configuration (regardless of its versioning configuration). In both test cases, the hook is supposed to fail when an invalid configuration is provided as the input.
-
-Now that you've learned the testing logic you'll use in contract tests for this hook, open each of the JSON files above, and add content shown next for each one of them:
-
-- `inputs/inputs_1_pre_create.json`:
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "AWS::S3::Bucket": {
- "resourceProperties": {
- "VersioningConfiguration": {
- "Status": "Enabled"
- }
- }
- }
-}
-:::
-
-- `inputs/inputs_1_pre_update.json`:
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "AWS::S3::Bucket": {
- "resourceProperties": {
- "VersioningConfiguration": {
- "Status": "Enabled"
- }
- }
- }
-}
-:::
-
-- `inputs/inputs_1_invalid.json`:
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "AWS::S3::Bucket": {
- "resourceProperties": {
- "VersioningConfiguration": {
- "Status": "Suspended"
- }
- }
- }
-}
-:::
-
-- `inputs/inputs_2_pre_create.json`:
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "AWS::S3::Bucket": {
- "resourceProperties": {
- "BucketName": "example-ignored-bucket",
- "VersioningConfiguration": {
- "Status": "Suspended"
- }
- }
- }
-}
-:::
-
-- `inputs/inputs_2_pre_update.json`:
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "AWS::S3::Bucket": {
- "resourceProperties": {
- "BucketName": "example-ignored-bucket",
- "VersioningConfiguration": {
- "Status": "Suspended"
- }
- }
- }
-}
-:::
-
-- `inputs/inputs_2_invalid.json`:
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "AWS::S3::Bucket": {
- "resourceProperties": {
- "BucketName": "example-non-ignored-bucket"
- }
- }
-}
-:::
-
-::alert[In the examples above, you're specifying input configuration for the `AWS::S3::Bucket` resource type for each input file: this is because you're expected to test each target resource type that you declare in the hook's schema. If you are targeting additional resource type(s) in your hook's schema, you're required to add configuration(s) for such resource type(s) as well in each contract test input file; otherwise, contract tests will fail.]{type="warning"}
-
-Now that you have written contract test inputs, you'll need to work on 2 additional steps:
-
-- simulate locally the hook's type configuration; that is, how to pass the list of ignored buckets to the hook when you'll run it, and
-- learn how to run contract test, so that your hook can consume the inputs above locally.
-
-Let's start with setting up the type configuration locally: you'll need to create a `.cfn-cli/` directory in your home directory, and then add a file in it, called `typeConfiguration.json`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mkdir ~/.cfn-cli/
-touch ~/.cfn-cli/typeConfiguration.json
-:::
-
-Next, open the `~/.cfn-cli/typeConfiguration.json` file, and add the following content to it:
-
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "CloudFormationConfiguration": {
- "HookConfiguration": {
- "TargetStacks": "ALL",
- "FailureMode": "FAIL",
- "Properties": {
- "IgnoreS3BucketNames": "example-ignored-bucket,example-ignored-bucket1"
- }
- }
- }
-}
-:::
-
-Save the file; as you can see, you're adding configuration directives that include the `IgnoreS3BucketNames` property with a comma-delimited string of buckets to ignore. For more information on developing hooks, including type configuration properties, see [AWS CloudFormation Hooks development overview](https://docs.aws.amazon.com/cloudformation-cli/latest/hooks-userguide/hooks-development-overview.html).
-
-Now that you have set up contract test inputs and the type configuration for the hook, you'll run contract tests to pass this information to the hook and consume it from your hook's business logic. You'll need 2 terminal consoles: in the first one, you'll package up the hook and run the contract tests via the `cfn test` command; in the second one, you'll use the SAM CLI (that you've installed as part of prerequisites) to simulate a local endpoint running your hook. Let's get started:
-
-- in a terminal window, make sure you're inside the `example-hook/` directory, and run the following command to package up the hook:
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cfn submit --dry-run
- :::
-
-- open a new terminal window, and make sure you're inside the `example-hook/` directory (you might need to change to the `cfn101-workshop/code/workspace/hooks/example-hook/` directory first, as you opened a new terminal). Next, run the following command from the `example-hook/` directory to run a local endpoint for your hook - note that after you run the command, it will not return back to the shell (this is the expected behavior):
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- sam local start-lambda
- :::
-
-- go back to the terminal window where you packaged up the hook, make sure you're inside the `example-hook/` directory, and run the following command to run the contract tests:
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cfn test --enforce-timeout 120
- :::
-
-You should see 2 test cases running; at the end, both should succeed.
-
-For more information on command options available for contract tests, see [test](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-cli-test.html) in the CloudFormation Command Line Interface (CLI) User Guide.
-
-Congratulations! You ran contract tests for your hook! In the next page, you'll submit your hook to the private registry in one AWS region; choose **Next** to continue!
diff --git a/content/advanced/hooks/example-in-python/write-unit-tests/index.ja.md b/content/advanced/hooks/example-in-python/write-unit-tests/index.ja.md
deleted file mode 100644
index af9469a92..000000000
--- a/content/advanced/hooks/example-in-python/write-unit-tests/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Write unit tests"
-weight: 650
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/example-in-python/write-unit-tests/index.md b/content/advanced/hooks/example-in-python/write-unit-tests/index.md
deleted file mode 100644
index c64dd1d1b..000000000
--- a/content/advanced/hooks/example-in-python/write-unit-tests/index.md
+++ /dev/null
@@ -1,342 +0,0 @@
----
-title: "Write unit tests"
-weight: 650
----
-
-You've written code to implement the business logic of your hook. As part of software development best practices, you'll now write unit tests to verify that key pieces of your hook work as you expect, thus increasing your level of confidence on your code's functional aspects.
-
-In addition to writing unit tests, you'll also write and run contract tests in this lab, and you'll also run end-to-end tests as well. Let's start with unit tests first.
-
-When you write unit tests, it is important to have a reasonable amount of key code being tested. For that, you use a software metric as an indicator, called [code coverage](https://en.wikipedia.org/wiki/Code_coverage), that expresses the percentage of code you're covering with your unit tests. While a 100% code coverage would be -ideally- desirable, it is not very easy or very practical to achieve -or even needed- in some cases. Most of the time, it makes sense to agree on a reasonable amount code coverage: for example, 80%. What really matters is which code you're covering with unit tests; think of what the important pieces of your code you want to cover are.
-
-To get started, you'll use [pytest](https://pytest.org/) with the [pytest-cov](https://pytest-cov.readthedocs.io/en/latest/index.html) plugin to run unit tests and to measure code coverage for your hook's code. You should already have installed `pytest-cov` as part of the prerequisites for this lab. Make sure you are in the `example-hook/` directory, and then create an empty code coverage configuration file, called `.coveragerc`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch .coveragerc
-:::
-
-Next, add this content to the `.coveragerc` file you just created:
-
-:::code{language=text showLineNumbers=false showCopyAction=true}
-[report]
-fail_under = 80
-
-show_missing = True
-
-
-[run]
-branch = True
-
-include =
- src/*/*
-
-omit =
- */__init__.py
- src/*/models.py
- src/*/target_models/*
- src/*/tests/*
-:::
-
-Save the file. When you look at the file above, you note that you're telling `coverage.py` to:
-
-- fail unit tests under 80% of code coverage;
-- show which code lines are not covered by your unit tests;
-- enable coverage for branches you have in your code (for example, `if` and `else` blocks);
-- include the `src/` code path, while excluding files generated by the CloudFormation CLI, and test files in the `tests/` directory.
-
-Next, make sure you're in the `example-hook/` directory; use the following commands to create the `tests` directory inside the `src/examplecompany_s3_versioningenabled/` path, and two empty files (you'll use one of them, `test_handlers.py`, later on to implement your tests):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mkdir src/examplecompany_s3_versioningenabled/tests
-touch src/examplecompany_s3_versioningenabled/tests/__init__.py
-touch src/examplecompany_s3_versioningenabled/tests/test_handlers.py
-:::
-
-Next, add the following content to the `src/examplecompany_s3_versioningenabled/tests/test_handlers.py` empty file you just created:
-
-:::code{language=python showLineNumbers=false showCopyAction=true}
-"""Tests: example hook to validate versioning is enabled for an S3 bucket."""
-
-import re
-import uuid
-from typing import (
- Any,
- MutableMapping,
-)
-
-from unittest.mock import (
- patch,
-)
-
-from cloudformation_cli_python_lib import ( # type: ignore
- HandlerErrorCode,
- HookContext,
- HookInvocationPoint,
- OperationStatus,
-)
-
-from .. import handlers
-from ..models import (
- HookHandlerRequest,
- TypeConfigurationModel,
-)
-
-
-# Derive the src sub-directory folder name from the type config
-# (example output for this hook: examplecompany_s3_versioningenabled)
-HOOK_CODE_SRC_SUBDIR_NAME = re.sub("::", "_", handlers.TYPE_NAME.lower())
-
-MOCK_ACCOUNT_ID = "111122223333"
-MOCK_ARN_SUFFIX = "00000000-0000-0000-0000-000000000000"
-MOCK_CALLBACK_CONTEXT: MutableMapping[str, Any] = {}
-MOCK_HOOK_TYPE_VERSION = "00000001"
-MOCK_REGION = "us-east-1"
-MOCK_STACK_NAME = "example"
-MOCK_TARGET = "AWS::S3::Bucket"
-MOCK_TARGET_LOGICAL_ID = "ExampleBucket"
-
-MOCK_STACK_ID = f"arn:aws:cloudformation:{MOCK_REGION}::stack/{MOCK_STACK_NAME}/{MOCK_ARN_SUFFIX}" # noqa: E501
-
-MOCK_BASE_HOOK_HANDLER_REQUEST = HookHandlerRequest(
- clientRequestToken=str(uuid.uuid4()),
- hookContext=HookContext(
- awsAccountId=MOCK_ACCOUNT_ID,
- hookTypeName=handlers.TYPE_NAME,
- hookTypeVersion=MOCK_HOOK_TYPE_VERSION,
- # Using CREATE_PRE_PROVISION as the invocation point also for
- # tests on the update invocation point, since both create and
- # update invocation points share the same handler code.
- invocationPoint=HookInvocationPoint.CREATE_PRE_PROVISION,
- stackId=MOCK_STACK_ID,
- targetLogicalId=MOCK_TARGET_LOGICAL_ID,
- targetModel=None,
- targetName=MOCK_TARGET,
- targetType=MOCK_TARGET,
- ),
-)
-
-
-def test_when_ignore_s3_bucket_names_is_missing_if_compliant_succeed() -> ( # noqa: D103 E501
- None
-):
- MOCK_BASE_HOOK_HANDLER_REQUEST.hookContext.targetModel = {
- "resourceProperties": {
- "VersioningConfiguration": {"Status": "Enabled"},
- },
- }
-
- response = handlers._run_pre_create_pre_update_common_checks(
- session=None,
- request=MOCK_BASE_HOOK_HANDLER_REQUEST,
- callback_context=MOCK_CALLBACK_CONTEXT,
- type_configuration=TypeConfigurationModel(None),
- )
-
- assert response.message == "Bucket versioning is enabled."
- assert response.status == OperationStatus.SUCCESS
- assert response.errorCode is None
- assert response.callbackContext is None
- assert response.callbackDelaySeconds == 0
-
-
-def test_when_ignore_s3_bucket_names_is_missing_if_non_compliant_fail() -> ( # noqa: D103 E501
- None
-):
- MOCK_BASE_HOOK_HANDLER_REQUEST.hookContext.targetModel = {
- "resourceProperties": {
- "VersioningConfiguration": {"Status": "Suspended"},
- },
- }
-
- response = handlers._run_pre_create_pre_update_common_checks(
- session=None,
- request=MOCK_BASE_HOOK_HANDLER_REQUEST,
- callback_context=MOCK_CALLBACK_CONTEXT,
- type_configuration=TypeConfigurationModel(None),
- )
-
- assert response.message == "Bucket versioning is not enabled."
- assert response.status == OperationStatus.FAILED
- assert response.errorCode == HandlerErrorCode.NonCompliant
- assert response.callbackContext is None
- assert response.callbackDelaySeconds == 0
-
-
-def test_when_s3_bucket_versioning_status_is_enabled_then_succeed() -> ( # noqa: D103 E501
- None
-):
- MOCK_BASE_HOOK_HANDLER_REQUEST.hookContext.targetModel = {
- "resourceProperties": {
- "VersioningConfiguration": {"Status": "Enabled"},
- },
- }
-
- response = handlers._run_pre_create_pre_update_common_checks(
- session=None,
- request=MOCK_BASE_HOOK_HANDLER_REQUEST,
- callback_context=MOCK_CALLBACK_CONTEXT,
- type_configuration=TypeConfigurationModel(
- IgnoreS3BucketNames="",
- ),
- )
-
- assert response.message == "Bucket versioning is enabled."
- assert response.status == OperationStatus.SUCCESS
- assert response.errorCode is None
- assert response.callbackContext is None
- assert response.callbackDelaySeconds == 0
-
-
-def test_when_s3_bucket_versioning_status_is_not_enabled_then_fail() -> ( # noqa: D103 E501
- None
-):
- MOCK_BASE_HOOK_HANDLER_REQUEST.hookContext.targetModel = {
- "resourceProperties": {
- "VersioningConfiguration": {"Status": "Suspended"},
- },
- }
-
- response = handlers._run_pre_create_pre_update_common_checks(
- session=None,
- request=MOCK_BASE_HOOK_HANDLER_REQUEST,
- callback_context=MOCK_CALLBACK_CONTEXT,
- type_configuration=TypeConfigurationModel(
- IgnoreS3BucketNames="",
- ),
- )
-
- assert response.message == "Bucket versioning is not enabled."
- assert response.status == OperationStatus.FAILED
- assert response.errorCode == HandlerErrorCode.NonCompliant
- assert response.callbackContext is None
- assert response.callbackDelaySeconds == 0
-
-
-def test_when_s3_bucket_properties_are_missing_then_fail() -> ( # noqa: D103
- None
-):
- MOCK_BASE_HOOK_HANDLER_REQUEST.hookContext.targetModel = {}
-
- response = handlers._run_pre_create_pre_update_common_checks(
- session=None,
- request=MOCK_BASE_HOOK_HANDLER_REQUEST,
- callback_context=MOCK_CALLBACK_CONTEXT,
- type_configuration=TypeConfigurationModel(
- IgnoreS3BucketNames="",
- ),
- )
-
- assert response.message == "The S3 bucket has no properties set."
- assert response.status == OperationStatus.FAILED
- assert response.errorCode == HandlerErrorCode.NonCompliant
- assert response.callbackContext is None
- assert response.callbackDelaySeconds == 0
-
-
-def test_when_s3_bucket_versioning_property_is_missing_then_fail() -> ( # noqa: D103 E501
- None
-):
- MOCK_BASE_HOOK_HANDLER_REQUEST.hookContext.targetModel = {
- "resourceProperties": {
- "VersioningConfiguration": None,
- },
- }
-
- response = handlers._run_pre_create_pre_update_common_checks(
- session=None,
- request=MOCK_BASE_HOOK_HANDLER_REQUEST,
- callback_context=MOCK_CALLBACK_CONTEXT,
- type_configuration=TypeConfigurationModel(
- IgnoreS3BucketNames="",
- ),
- )
-
- assert (
- response.message
- == "The VersioningConfiguration property value is missing."
- )
- assert response.status == OperationStatus.FAILED
- assert response.errorCode == HandlerErrorCode.NonCompliant
- assert response.callbackContext is None
- assert response.callbackDelaySeconds == 0
-
-
-def test_when_exception_is_thrown_then_fail() -> None: # noqa: D103
- MOCK_BASE_HOOK_HANDLER_REQUEST.hookContext.targetModel = {}
-
- with patch(
- f"{HOOK_CODE_SRC_SUBDIR_NAME}.handlers._get_target_model",
- side_effect=ValueError("Example error."),
- ):
- response = handlers._run_pre_create_pre_update_common_checks(
- session=None,
- request=MOCK_BASE_HOOK_HANDLER_REQUEST,
- callback_context=MOCK_CALLBACK_CONTEXT,
- type_configuration=TypeConfigurationModel(
- IgnoreS3BucketNames="",
- ),
- )
-
- assert response.message == "Example error."
- assert response.status == OperationStatus.FAILED
- assert response.errorCode == HandlerErrorCode.InternalFailure
- assert response.callbackContext is None
- assert response.callbackDelaySeconds == 0
-
-
-def test_when_s3_bucket_name_is_not_ignored_then_if_non_compliant_fail() -> ( # noqa: D103 E501
- None
-):
- MOCK_BASE_HOOK_HANDLER_REQUEST.hookContext.targetModel = {
- "resourceProperties": {
- "BucketName": "my-non-ignored-bucket",
- "VersioningConfiguration": {"Status": "Suspended"},
- },
- }
-
- response = handlers._run_pre_create_pre_update_common_checks(
- session=None,
- request=MOCK_BASE_HOOK_HANDLER_REQUEST,
- callback_context=MOCK_CALLBACK_CONTEXT,
- type_configuration=TypeConfigurationModel(
- IgnoreS3BucketNames="my-ignored-bucket,my-other-ignored-bucket",
- ),
- )
-
- assert response.message == "Bucket versioning is not enabled."
- assert response.status == OperationStatus.FAILED
- assert response.errorCode == HandlerErrorCode.NonCompliant
- assert response.callbackContext is None
- assert response.callbackDelaySeconds == 0
-:::
-
-Save the file. Look at the example unit test code you just added: can you recognize which parts of the code are covered? As you can see, in this file you first set some variables on top of the code, and you reference these variables in `MOCK_BASE_HOOK_HANDLER_REQUEST` that you reuse across unit test methods. In each method, you create a mock of the target model, and run the handler code to assert either success or failure scenarios.
-
-Next, type the following command from the `example-hook/` directory to run unit tests:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pytest --cov
-:::
-
-Congratulations! Your code coverage is slightly above 80%. There are some other lines of code that you could cover, but let's move on for now.
-
-Next, run `mypy` against your `test_handlers.py` file (make sure you are in the `example-hook/` directory):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mypy src/examplecompany_s3_versioningenabled/tests/test_handlers.py
-:::
-
-You should see an output indicating no errors. Next, run `flake8` against the same file:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-flake8 \
- --docstring-convention pep257 \
- --ignore=W503,W504 \
- --max-complexity=10 \
- --max-line-length=79 \
- src/examplecompany_s3_versioningenabled/tests/test_handlers.py
-:::
-
-You should see no output messages, indicating no errors have occurred.
-
-Choose **Next** to continue!
diff --git a/content/advanced/hooks/guard-hooks/activate-guard-hook/index.ja.md b/content/advanced/hooks/guard-hooks/activate-guard-hook/index.ja.md
deleted file mode 100644
index c12bbed85..000000000
--- a/content/advanced/hooks/guard-hooks/activate-guard-hook/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Activate a Guard Hook"
-weight: 630
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/guard-hooks/activate-guard-hook/index.md b/content/advanced/hooks/guard-hooks/activate-guard-hook/index.md
deleted file mode 100644
index d4e872d8e..000000000
--- a/content/advanced/hooks/guard-hooks/activate-guard-hook/index.md
+++ /dev/null
@@ -1,159 +0,0 @@
----
-title: "Activate a Guard Hook"
-weight: 630
----
-
-### Introduction
-
-To use an AWS Guard Hook in your account, you must first activate the Hook for the account and Region where you want to use it. Activating a Hook makes it usable in stack operations in the account and Region where it's activated.
-
-When you activate a Guard Hook, CloudFormation creates an entry in your account's registry for the activated Hook as a private Hook. This allows you to set any configuration properties the Hook includes. Configuration properties define how the Hook is configured for a given AWS account and Region.
-
-#### Using AWS Console to Create a Guard Hook
-
-##### **Open AWS CloudFormation Hooks**
-
-1. Open **AWS CloudFormation Console**.
-2. Navigate to the **Hooks** section.
-3. Click on **With Guard** option in the **Create a Hook** dropdown list.
-
-
-
-##### **Step 1: Provide your Guard rules**
-
-Configure the Guard Hook source with your S3-stored rules:
-
-
-
-Use the following parameters:
-
-1. **Guard Hook source** – Select **Store your Guard rules in S3**
-2. **S3 URI** – Enter the **S3 URI of your Guard rules file** (e.g., `s3://guard-hook-bucket-/hooks/s3-security-rules.guard`)
-
-::alert[If you need to find your S3 URI, refer back to the [Write Guard rules for Hook](../write-guard-rules/) section where you uploaded your Guard rules file.]{type="info"}
-
-3. **Object version** – (Optional) If your S3 bucket has versioning enabled, you can specify a version
-4. **S3 bucket for Guard output report** – (Optional) You can use the same bucket for output reports
-
-Click **Next** to continue.
-
-##### **Step 2: Hook details and settings**
-
-Configure the Hook behavior and execution settings:
-
-
-
-Use the following parameters:
-
-1. **Hook Name** – `S3SecurityGuardHook`
-2. **Hook Targets** – Select **Resources**.
- ::alert[We choose **Resources** as the target because our Guard rules are designed to evaluate individual CloudFormation resources (specifically S3 buckets) rather than the entire template.]{type="info"}
-3. **Hook Actions** – Select **Create**.
- ::alert[This implements evaluation during CloudFormation **CREATE** operation]{type="info"}
-4. **Hook Mode** – Set to **Fail**.
- ::alert[With Hook Mode being Warn the hook will only emit a warning message when a hook fails, without stopping the provisioning operation. While with Fail mode the hook will stop the provisioning operation when a Hook fails.]{type="info"}
-5. **Execution Role** – Choose **Existing Execution Role** and select the **GuardHookExecutionRole** created earlier.
-
-::alert[To find your execution role, look for a role name similar to `GuardHookExecutionRoleStack-GuardHookExecutionRole-` that was created in the [Prepare to create a Guard Hook](../prepare-guard-hook/) section.]{type="info"}
-
-Click **Next** to continue.
-
-##### **Step 3: Apply Hook filters (Optional)**
-
-Configure which resources the Hook should target:
-
-
-
-For **Hook filters** we will add **`AWS::S3::Bucket`** to filter the hook to just check for the creations of S3 buckets.
-
-We will use the default options for the other configurations here so there is no need to update them.
-
-Click **Next** to continue.
-
-##### **Step 4: Review and activate**
-
-Review all your settings before creating the Hook:
-
-
-
-Review the settings:
-- **Hook Name**: S3SecurityGuardHook
-- **Guard Rules Source**: S3 URI pointing to your rules file
-- **Target**: Resources (AWS::S3::Bucket)
-- **Actions**: Create
-- **Mode**: Fail
-- **Execution Role**: GuardHookExecutionRole
-
-Click **Create** to register the Hook and wait for a few seconds for the Hook to be created and activated.
-
-
-
-### Alternative: Using AWS CLI to Activate Guard Hook
-
-You can also activate the Guard Hook using the AWS CLI:
-
-```bash
-# First, activate the Hook type
-aws cloudformation activate-type \
- --type HOOK \
- --type-name "AWS::CloudFormation::GuardHook" \
- --publisher-id "AWS" \
- --region us-east-1
-
-# Then, set the Hook configuration
-aws cloudformation set-type-configuration \
- --type HOOK \
- --type-name "AWS::CloudFormation::GuardHook" \
- --configuration '{
- "CloudFormationConfiguration": {
- "HookConfiguration": {
- "TargetStacks": "ALL",
- "FailureMode": "FAIL",
- "Properties": {
- "GuardRuleS3Uri": "s3://your-guard-rules-bucket/hooks/s3-security-rules.guard",
- "OutputS3Uri": "s3://your-guard-rules-bucket/guard-output/",
- "ExecutionRoleArn": "arn:aws:iam::123456789012:role/GuardHookExecutionRole"
- }
- },
- "TargetOperations": ["CREATE"],
- "TargetFilters": {
- "Types": ["AWS::S3::Bucket"]
- }
- }
- }' \
- --region us-east-1
-```
-
-### Understanding Guard Hook Configuration
-
-The Guard Hook configuration includes several important settings:
-
-#### **Guard Rules Source**
-- **S3 URI**: Points to your Guard rules file in S3
-- **Versioning**: Optionally specify a specific version for consistency
-- **Access**: The execution role must have read permissions to this S3 location
-
-#### **Target Configuration**
-- **Resources**: Targets individual resource operations
-- **Filters**: Limits evaluation to specific resource types (AWS::S3::Bucket)
-- **Actions**: Specifies when to run (CREATE, UPDATE, DELETE)
-
-#### **Execution Settings**
-- **Failure Mode**: FAIL stops operations on rule violations, WARN allows them to continue
-- **Execution Role**: IAM role with necessary S3 permissions
-
-#### **Output Configuration**
-- **Output S3 URI**: Optional location for detailed validation reports
-- **Report Format**: JSON or YAML format for output reports
-
-### Conclusion
-
-Once the Hook is activated, it will automatically evaluate CloudFormation stack changes based on the defined Guard rules. By enforcing S3 security best practices, the Guard Hook ensures that only compliant S3 bucket configurations are deployed. You can now proceed to the test section and monitor the Hook's behavior in your stack operations using the activated hook.
-
-The Guard Hook will evaluate your S3 resources against the rules we defined:
-- ✅ Versioning must be enabled
-- ✅ Public access must be blocked
-- ✅ Server-side encryption must be configured
-- ✅ No public read access allowed
-
-Choose **Next** to test the Guard Hook functionality!
diff --git a/content/advanced/hooks/guard-hooks/cleanup/index.ja.md b/content/advanced/hooks/guard-hooks/cleanup/index.ja.md
deleted file mode 100644
index 7088e78cc..000000000
--- a/content/advanced/hooks/guard-hooks/cleanup/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Cleanup"
-weight: 650
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/guard-hooks/cleanup/index.md b/content/advanced/hooks/guard-hooks/cleanup/index.md
deleted file mode 100644
index d98554ead..000000000
--- a/content/advanced/hooks/guard-hooks/cleanup/index.md
+++ /dev/null
@@ -1,103 +0,0 @@
----
-title: "Cleanup"
-weight: 650
----
-
-### Introduction
-
-### Clean Up Resources
-
-After testing is completed, please delete the resources we created during this Lab.
-
-#### Using AWS CLI
-
-Run the following commands to delete the test CloudFormation stacks:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack --stack-name s3-noncompliant-stack --region us-east-1
-:::
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack --stack-name s3-compliant-stack --region us-east-1
-:::
-
-#### Disable The Guard Hook
-
-To disable a Hook in your account:
-
-1. Sign in to the AWS Management Console and open the AWS [CloudFormation console](https://console.aws.amazon.com/cloudformation).
-
-2. On the navigation bar at the top of the screen, choose the AWS Region where the Hook is located.
-
-3. From the navigation pane, choose **Hooks**.
-
-4. Choose the name of the Hook you want to **disable** (e.g., `S3SecurityGuardHook`).
-
-5. On the Hook details page, to the right of the Hook's name, choose the **Disable** button.
-
-6. When prompted for confirmation, choose **Disable Hook**.
-
-#### Remove Guard Rules from S3
-
-To clean up the Guard rules stored in S3:
-
-1. **Delete the Guard rules file**:
-```bash
-aws s3 rm s3://your-guard-rules-bucket/hooks/s3-security-rules.guard
-```
-
-2. **Delete any output reports** (if configured):
-```bash
-aws s3 rm s3://your-guard-rules-bucket/guard-output/ --recursive
-```
-
-3. **Optionally delete the S3 bucket** (if created specifically for this lab):
-```bash
-# First ensure the bucket is empty
-aws s3 rb s3://your-guard-rules-bucket --force
-```
-
-#### Remove Hook Execution Role
-
-Please use the stack name provided in [Prepare to create a Guard Hook](../prepare-guard-hook/#deploy-the-hook-execution-role) Section:
-
-```bash
-aws cloudformation delete-stack --stack-name GuardHookExecutionRoleStack --region us-east-1
-```
-
-#### Alternative: Using AWS CLI to Deactivate Guard Hook
-
-You can also deactivate the Guard Hook using the AWS CLI:
-
-```bash
-# Deactivate the Guard Hook
-aws cloudformation deactivate-type \
- --type HOOK \
- --type-name "AWS::CloudFormation::GuardHook" \
- --region us-east-1
-```
-
-#### Verify Cleanup
-
-Verify that the following resources are deleted if they are no longer needed:
-
-- ✅ **Test CloudFormation stacks** (s3-noncompliant-stack, s3-compliant-stack)
-- ✅ **Guard Hook** (S3SecurityGuardHook)
-- ✅ **Guard rules file in S3** (s3-security-rules.guard)
-- ✅ **Guard output reports in S3** (if configured)
-- ✅ **IAM execution role** (GuardHookExecutionRole)
-- ✅ **S3 bucket** (if created specifically for this lab)
-
-#### Understanding the Cleanup Process
-
-The cleanup process removes:
-
-1. **Test Resources**: The CloudFormation stacks and any S3 buckets they created
-2. **Hook Configuration**: The activated Guard Hook and its configuration
-3. **Guard Rules**: The policy files stored in S3
-4. **IAM Permissions**: The execution role and associated policies
-5. **Output Reports**: Any validation reports generated during testing
-
-This ensures that no residual resources remain that could incur costs or interfere with future testing.
-
-Almost done! Choose **Next** to continue!
diff --git a/content/advanced/hooks/guard-hooks/index.ja.md b/content/advanced/hooks/guard-hooks/index.ja.md
deleted file mode 100644
index beff3fbb8..000000000
--- a/content/advanced/hooks/guard-hooks/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Guard Hooks"
-weight: 600
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/guard-hooks/index.md b/content/advanced/hooks/guard-hooks/index.md
deleted file mode 100644
index 58242315a..000000000
--- a/content/advanced/hooks/guard-hooks/index.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-title: "Guard Hooks"
-weight: 600
----
-
-### Introduction
-
-AWS CloudFormation Guard Hooks enable you to validate CloudFormation and AWS Cloud Control API operations using AWS CloudFormation Guard rules. Guard is an open-source, general-purpose, domain-specific language (DSL) that you can use to author policy-as-code. When an operation is triggered, your Hook can:
-
-* Evaluate the operation against your defined Guard rules.
-* Either block the operation if it doesn't meet requirements
- Or allow it to proceed with a warning message.
-
-These Hooks act as custom validation checkpoints that you can configure to intercept and assess specific CloudFormation operations before they're executed using declarative Guard rules instead of custom code.
-
-You can configure Guard Hooks to intercept and evaluate the following CloudFormation operations:
-* Resource operations
-* Stack operations
-* Change set operations
-
-## In This Lab
-
-We will explore how Guard Hooks can be effectively used for resource-level operations. Consider a common security requirement: as a member of an organization's security team, you need to ensure all S3 buckets deployed through CloudFormation have versioning enabled and public access blocked.
-
-In the example, we will review and create Guard rules required for Guard Hooks, followed by registering and activating the Guard Hook using the created rules. After activation, we'll test the Guard hook functionality with new CloudFormation deployments and explore the steps for validating and troubleshooting Guard Hook invocations.
diff --git a/content/advanced/hooks/guard-hooks/prepare-guard-hook/index.ja.md b/content/advanced/hooks/guard-hooks/prepare-guard-hook/index.ja.md
deleted file mode 100644
index 6a8e2a468..000000000
--- a/content/advanced/hooks/guard-hooks/prepare-guard-hook/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Prepare to create a Guard Hook"
-weight: 620
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/guard-hooks/prepare-guard-hook/index.md b/content/advanced/hooks/guard-hooks/prepare-guard-hook/index.md
deleted file mode 100644
index 6443c2c46..000000000
--- a/content/advanced/hooks/guard-hooks/prepare-guard-hook/index.md
+++ /dev/null
@@ -1,162 +0,0 @@
----
-title: "Prepare to create a Guard Hook"
-weight: 620
----
-
-### **Introduction**
-
-Before you create a **Guard Hook** for validating **S3 configurations**, we need to complete the following steps to create an execution role with IAM permissions and a trust policy to allow CloudFormation to invoke a Guard Hook.
-
-1. **Upload Guard Rules to S3** – The Guard rules must be stored in S3 for the Hook to access them.
-2. **Deploy the CloudFormation Hook Execution Role** – This role allows CloudFormation Hooks to assume permissions for accessing S3 and reading Guard rules.
-3. **Register the Hook in AWS CloudFormation** – The Hook will be configured to evaluate S3 resource changes before provisioning.
-4. **Attach Hook to a CloudFormation Stack** – This ensures enforcement during stack deployments.
-
----
-
-### **Step 1: Verify Guard Rules in S3**
-
-::alert[If you haven't uploaded your Guard rules to S3 yet, please complete the [Write Guard rules for Hook](../write-guard-rules/) section first, specifically Step 5: Upload Guard Rules to S3.]{type="warning"}
-
-Since the Guard rules **s3-security-rules.guard** should already be uploaded to S3, follow these steps to verify the **S3 URI**:
-
-1. **Go to the AWS S3 Console**:
-
- - Open [AWS S3 Console](https://console.aws.amazon.com/s3).
- - Navigate to your bucket containing the Guard rules.
- - Locate the **s3-security-rules.guard** file.
-
-2. **Copy the S3 URI**:
- - The S3 URI format will be:
- ```
- s3://your-guard-rules-bucket/hooks/s3-security-rules.guard
- ```
- - Copy this URI for use in the next step.
-
----
-
-### **Step 2: Create CloudFormation for Guard Hook IAM Role**
-
-To enable the **CloudFormation Guard Hook** to validate **S3 configurations** by accessing Guard rules from S3, we must create an IAM role that CloudFormation Hooks can assume. This role ensures that the hook has the necessary permissions to:
-
-**Access S3 Objects**: The hook reads Guard rules from the specified S3 bucket and object.
-
-**Write Output Reports**: Optionally, the hook can write validation reports to an S3 bucket.
-
-By defining a dedicated **IAM role**, we ensure that CloudFormation Hooks can securely perform these operations without requiring excessive permissions across AWS services.
-
-#### **Deploy the Hook Execution Role**
-
-::alert[If you've cloned our repo then you can also find this yaml file in our _cfn101-workshop/code/workspace/hooks/guard-hook-role.yaml_ folder.]{type="info"}
-
-1. Copy the **S3 URI of your Guard rules** from the AWS Management Console.
-2. Open **guard-hook-role.yaml** file then replace `` with your actual bucket name and save the **guard-hook-role.yaml** file:
-
-```yaml
-AWSTemplateFormatVersion: "2010-09-09"
-Description: "IAM role configuration for Guard Hook"
-
-Parameters:
- S3BucketName:
- Type: String
- Default: ""
- Description: "Name of the S3 bucket containing Guard rules"
-
-Resources:
- GuardHookExecutionRole:
- Type: "AWS::IAM::Role"
- Properties:
- AssumeRolePolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Effect: Allow
- Principal:
- Service: hooks.cloudformation.amazonaws.com
- Action: "sts:AssumeRole"
- Policies:
- - PolicyName: GuardHookS3Access
- PolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Effect: Allow
- Action:
- - "s3:ListBucket"
- - "s3:GetObject"
- - "s3:GetObjectVersion"
- Resource:
- - !Sub "arn:aws:s3:::${S3BucketName}"
- - !Sub "arn:aws:s3:::${S3BucketName}/*"
- - Effect: Allow
- Action:
- - "s3:PutObject"
- - "s3:PutObjectAcl"
- Resource:
- - !Sub "arn:aws:s3:::${S3BucketName}/guard-output/*"
-
-Outputs:
- GuardHookExecutionRoleArn:
- Description: "ARN of the Guard Hook execution role"
- Value: !GetAtt GuardHookExecutionRole.Arn
- Export:
- Name: !Sub "${AWS::StackName}-GuardHookExecutionRoleArn"
-```
-
-#### **3. Deploy the Hook Role via AWS Console**
-
-1. **Open AWS CloudFormation Console**:
-
- - Navigate to [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation).
- - Click **Create Stack** → **With new resources (standard)**.
- - Upload the modified `guard-hook-role.yaml` file (with the correct S3 bucket name).
-
-2. **Provide Stack Details**:
-
- - Enter a **stack name** (e.g., `GuardHookExecutionRoleStack`).
- - Update the **S3BucketName** parameter with your actual bucket name.
- - Click **Next**.
-
-3. **Configure Stack Settings**:
-
- - Leave the default values unless modifications are needed.
- - Click **Next**.
-
-4. **Review and Create**:
- - Acknowledge that CloudFormation might create IAM resources.
- - Click **Create Stack**.
-
-5. **Wait for Deployment Completion**:
- - Navigate to the **Outputs** tab.
- - Look for `GuardHookExecutionRoleArn` and **copy its value** for later use.
-
----
-
-### **Step 3: Understanding Guard Hook Permissions**
-
-The IAM role we created provides the following permissions:
-
-#### **S3 Read Permissions**
-- `s3:ListBucket`: Allows the Hook to list objects in the S3 bucket
-- `s3:GetObject`: Enables reading the Guard rules file
-- `s3:GetObjectVersion`: Supports versioned S3 objects
-
-#### **S3 Write Permissions (Optional)**
-- `s3:PutObject`: Allows writing Guard output reports
-- `s3:PutObjectAcl`: Sets appropriate permissions on output files
-
-#### **Trust Policy**
-The role trusts the `hooks.cloudformation.amazonaws.com` service, allowing CloudFormation to assume this role when invoking Guard Hooks.
-
----
-
-### **Step 4: Verify Prerequisites**
-
-Before proceeding to activate the Guard Hook, ensure you have:
-
-1. ✅ **Guard rules file uploaded to S3**
-2. ✅ **S3 URI of the Guard rules file**
-3. ✅ **IAM execution role created and deployed**
-4. ✅ **Execution role ARN copied**
-
-Now, all the preparation is done. The Guard rules are ready in S3, and we have the necessary IAM role for the Guard Hook to function properly.
-
-Choose **Next** to continue!
diff --git a/content/advanced/hooks/guard-hooks/test-guard-hook/index.ja.md b/content/advanced/hooks/guard-hooks/test-guard-hook/index.ja.md
deleted file mode 100644
index 6458d5809..000000000
--- a/content/advanced/hooks/guard-hooks/test-guard-hook/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Test Guard Hook"
-weight: 640
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/guard-hooks/test-guard-hook/index.md b/content/advanced/hooks/guard-hooks/test-guard-hook/index.md
deleted file mode 100644
index a86994ce6..000000000
--- a/content/advanced/hooks/guard-hooks/test-guard-hook/index.md
+++ /dev/null
@@ -1,359 +0,0 @@
----
-title: "Test Guard Hook"
-weight: 640
----
-
-### **Introduction**
-
-Now that we have deployed the **S3SecurityGuardHook**, we need to test it to ensure it correctly validates S3 configurations before CloudFormation provisions resources.
-
-::alert[Before running the AWS CloudFormation commands in this section, ensure you have configured your AWS credentials using `aws configure` or by setting up an AWS profile. The commands will use your configured AWS account credentials to create and manage CloudFormation stacks.]{type="warning"}
-
-We will test the hook with two different CloudFormation stacks.
-
-1. **A non-compliant S3 bucket** that violates the Guard rules and fails the CloudFormation Stack deployment.
-2. **A compliant S3 bucket** that meets all Guard rule criteria which results into successful deployment of CloudFormation stack.
-
----
-
-::alert[To get started, ensure that you are in `cfn101-workshop/code/workspace/hooks/guard_hook` directory.]{type="info"}
-
-#### **Scenario 1: Non-Compliant S3 Bucket (Validation Failure)**
-
-Locate and open the `noncompliant-s3.yaml` file.
-The CloudFormation template in this file **violates several Guard rules** that the Guard Hook is currently validating.
-
-```yaml
-AWSTemplateFormatVersion: '2010-09-09'
-Resources:
- NonCompliantS3Bucket:
- Type: 'AWS::S3::Bucket'
- Properties:
- BucketName: noncompliant-test-bucket
- # Missing VersioningConfiguration - violates s3_versioning_enabled rule
- # Missing PublicAccessBlockConfiguration - violates s3_public_access_blocked rule
- # Missing BucketEncryption - violates s3_encryption_enabled rule
- AccessControl: PublicRead # Violates s3_no_public_read rule
-```
-
-Next, from the directory where the file above is, use the AWS CLI to create a stack, in the us-east-1 region, with that template:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-
-aws cloudformation create-stack \
- --stack-name s3-noncompliant-stack \
- --template-body file://noncompliant-s3.yaml \
- --region us-east-1
-:::
-
-The cloudformation `create-stack` command will return an output in JSON format like this:
-
-```JSON
-{
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/s3-noncompliant-stack/c997a360-a481-11f0-ae62-1251de0de62d"
-}
-```
-
-::alert[After seeing the JSON output, press `q` to exit the output view if you're using a pager.]{type="info"}
-
-Then let's check the stack events and hook evaluation results using the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-events \
- --stack-name s3-noncompliant-stack \
- --query 'StackEvents[?HookType!=`null` && contains(HookType, `S3SecurityGuardHook`)]' \
- --region us-east-1
-:::
-
-##### Checking for Hook Status Messages
-
-When executing the above command, you need to look for the HookStatus field in the response. Initially, you might see `"HOOK_IN_PROGRESS"` status, which means the hook is still evaluating the template.
-
-You should continue running the command repeatedly (every few seconds) until you see either:
-
-- "HookStatus": **_"HOOK_COMPLETE_FAILED"_** (for non-compliant templates)
-- "HookStatus": **_"HOOK_COMPLETE_SUCCEEDED"_** (for compliant templates)
-
-Since the stack contains an S3 bucket definition that is non-compliant according to the Guard rules in the Guard Hook, the stack will fail to create. The `describe-stack-events` command will show the hook evaluation results similar to the following:
-
-```json
-[
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/s3-noncompliant-stack/c997a360-a481-11f0-ae62-1251de0de62d",
- "EventId": "NonCompliantS3Bucket-9cd25ccd-8b45-4c61-890e-08c042d5be66",
- "StackName": "s3-noncompliant-stack",
- "LogicalResourceId": "NonCompliantS3Bucket",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::S3::Bucket",
- "Timestamp": "2025-10-08T20:03:02.446000+00:00",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "Private::Guard::S3SecurityGuardHook",
- "HookStatus": "HOOK_COMPLETE_FAILED",
- "HookStatusReason": "Hook failed with message: Template failed validation, the following rule(s) failed: s3_encryption_enabled, s3_no_public_read, s3_public_access_blocked, s3_versioning_enabled.",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookInvocationId": "2a36aa47-2d4c-4ab8-a263-4162b342545c",
- "HookFailureMode": "FAIL"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/s3-noncompliant-stack/c997a360-a481-11f0-ae62-1251de0de62d",
- "EventId": "NonCompliantS3Bucket-9cd25ccd-8b45-4c61-890e-08c042d5be66",
- "StackName": "s3-noncompliant-stack",
- "LogicalResourceId": "NonCompliantS3Bucket",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::S3::Bucket",
- "Timestamp": "2025-10-08T20:03:01.818000+00:00",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "Private::Guard::S3SecurityGuardHook",
- "HookStatus": "HOOK_IN_PROGRESS",
- "HookStatusReason": "Invoking hook",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookInvocationId": "2a36aa47-2d4c-4ab8-a263-4162b342545c",
- "HookFailureMode": "FAIL"
- }
-]
-```
-
-::alert[After viewing the JSON output, press `q` to exit the view if you're using a pager.]{type="info"}
-
-The stack events show the progression and failure of the non-compliant stack deployment:
-
-1. Initially, the hook starts its evaluation (HOOK_IN_PROGRESS) during the PRE_PROVISION phase
-2. The hook then fails (HOOK_COMPLETE_FAILED) with specific Guard rule violations:
- - s3_versioning_enabled: Versioning configuration is missing
- - s3_public_access_blocked: Public access block configuration is missing
- - s3_encryption_enabled: Bucket encryption is not configured
- - s3_no_public_read: Public read access is explicitly allowed
-3. Because the hook's HookFailureMode is set to FAIL, the stack creation is halted and rolled back
-
-This demonstrates how the Guard Hook effectively prevents the deployment of S3 buckets that don't meet the specified security requirements, ensuring consistent configuration standards across your AWS infrastructure.
-
-**Understand CloudFormation Stack Failure**
-
-In order to understand the detailed reason for stack failure in the AWS Console, follow the steps below.
-
-- Navigate to [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation).
-- Locate the latest deployment for `s3-noncompliant-stack` Stack.
-
-
-
-- Navigate to the Events section.
-- Locate the `S3SecurityGuardHook` under the Hook invocations section. This entry will contain details about the status of Hook as _Fail_ and Hook status reason with a detailed error message showing which Guard rules failed.
-
-
-
----
-
-### **Scenario 2: Compliant S3 Bucket**
-
-Locate and open the `compliant-s3.yaml` file.
-The CloudFormation template in this file **meets all the required Guard rules** that the Guard Hook is currently validating.
-
-::alert[**Important**: S3 bucket names must be globally unique. If you encounter an error like "The requested bucket name is not available", you need to modify the bucket name in the `compliant-s3.yaml` file to use a unique name such as `compliant-test-bucket--`.]{type="warning"}
-
-```yaml
-AWSTemplateFormatVersion: '2010-09-09'
-Resources:
- CompliantS3Bucket:
- Type: 'AWS::S3::Bucket'
- Properties:
- BucketName: compliant-test-bucket-
- # Compliance: Versioning must be enabled
- VersioningConfiguration:
- Status: Enabled
- # Compliance: Public access must be blocked
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- # Compliance: Server-side encryption must be enabled
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
- # Compliance: No public read access (default behavior, no explicit ACL)
-```
-
-Next, from the directory where the file above is, use the AWS CLI to create a stack, in the us-east-1 region, with that template:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name s3-compliant-stack \
- --template-body file://compliant-s3.yaml \
- --region us-east-1
-:::
-
-The command will return output similar to:
-
-```JSON
-{
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/s3-compliant-stack/c7dd3540-a499-11f0-8e05-0affcdb6e4dd"
-}
-```
-
-::alert[After seeing the JSON output, press `q` to exit the output view if you're using a pager.]{type="info"}
-
-To monitor the stack creation progress and view the hook evaluation results, use the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-events \
- --stack-name s3-compliant-stack \
- --query 'StackEvents[?HookType!=`null` && contains(HookType, `S3SecurityGuardHook`)]' \
- --region us-east-1
-:::
-
-##### Checking for Hook Status Messages
-
-As with the non-compliant stack, you need to run the describe-stack-events command repeatedly until you see the final hook status:
-
-- If you initially see the only event with "HookStatus": `"HOOK_IN_PROGRESS"`, wait a few seconds and run the command again
-- Continue checking until you see "HookStatus": "HOOK_COMPLETE_SUCCEEDED", which indicates the Guard rule validation passed.
-
-For a compliant stack, you should see events similar to this:
-
-```json
-[
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/s3-compliant-stack/c7dd3540-a499-11f0-8e05-0affcdb6e4dd",
- "EventId": "CompliantS3Bucket-c820250f-3c03-44dd-a520-d29bd75f4523",
- "StackName": "s3-compliant-stack",
- "LogicalResourceId": "CompliantS3Bucket",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::S3::Bucket",
- "Timestamp": "2025-10-08T22:54:47.524000+00:00",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "Private::Guard::S3SecurityGuardHook",
- "HookStatus": "HOOK_COMPLETE_SUCCEEDED",
- "HookStatusReason": "Hook succeeded with message: Successful validation",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookInvocationId": "3dc80239-9056-4dd4-9716-eec4d2477ca4",
- "HookFailureMode": "FAIL"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/s3-compliant-stack/c7dd3540-a499-11f0-8e05-0affcdb6e4dd",
- "EventId": "CompliantS3Bucket-c5f4dc9e-1145-4af6-ba40-53b36bc28354",
- "StackName": "s3-compliant-stack",
- "LogicalResourceId": "CompliantS3Bucket",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::S3::Bucket",
- "Timestamp": "2025-10-08T22:54:47.049000+00:00",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "Private::Guard::S3SecurityGuardHook",
- "HookStatus": "HOOK_IN_PROGRESS",
- "HookStatusReason": "Invoking hook",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookInvocationId": "3dc80239-9056-4dd4-9716-eec4d2477ca4",
- "HookFailureMode": "FAIL"
- }
-]
-```
-
-::alert[After viewing the JSON output, press `q` to exit the view if you're using a pager.]{type="info"}
-
-Unlike the non-compliant stack, these stack events show the successful progression of the compliant stack deployment:
-
-1. The hook begins its evaluation (`"HOOK_IN_PROGRESS"`) during the PRE_PROVISION phase
-2. The hook then completes successfully (HOOK_COMPLETE_SUCCEEDED), confirming that:
- - All Guard rules passed validation
- - The S3 bucket configuration meets all security requirements
- - The hook validation allows the stack creation to proceed
-
-To verify the complete stack creation, you can navigate to the AWS CloudFormation Console and check that the stack status is CREATE_COMPLETE.
-
-::alert[While the hook validation succeeded, the final stack creation still depends on other factors such as IAM permissions and service quotas.]{type="info"}
-
-**Review CloudFormation Stack Creation in the AWS Console**
-
-You can review stack and Hook execution status in the AWS Console, by following the steps below.
-
-- Navigate to [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation).
-- Locate the latest deployment for `s3-compliant-stack` Stack.
- - If the status is `CREATE_COMPLETE`, it means the S3 bucket configuration met all Guard rule checks enforced by the Guard Hook, and the stack deployment was successful.
- - If not check the Events output for errors.
-- Navigate to the Events section.
-- Locate the `S3SecurityGuardHook` under the Hook invocations section. This entry will contain details about the status of the Hook and **Hook status reason** with a successful execution message.
-
-
-
----
-
-### View Guard Output Reports in S3
-
-If you configured an S3 output location during Hook activation, you can view detailed Guard validation reports:
-
-1. Open **Amazon S3 Console**.
-2. Navigate to your configured output bucket and prefix (e.g., `s3://your-guard-rules-bucket/guard-output/`).
-3. Look for report files with timestamps corresponding to your stack operations.
-4. Download and review the reports to see detailed Guard rule evaluation results:
-
-**Example successful validation report (JSON format)**:
-```json
-{
- "summary": {
- "status": "PASS",
- "rules_evaluated": 4,
- "rules_passed": 4,
- "rules_failed": 0
- },
- "rules": [
- {
- "rule_name": "s3_versioning_enabled",
- "status": "PASS",
- "message": "S3 bucket has versioning enabled"
- },
- {
- "rule_name": "s3_public_access_blocked",
- "status": "PASS",
- "message": "S3 bucket has public access blocked"
- },
- {
- "rule_name": "s3_encryption_enabled",
- "status": "PASS",
- "message": "S3 bucket has server-side encryption enabled"
- },
- {
- "rule_name": "s3_no_public_read",
- "status": "PASS",
- "message": "S3 bucket does not allow public read access"
- }
- ]
-}
-```
-
-**Example failed validation report**:
-```json
-{
- "summary": {
- "status": "FAIL",
- "rules_evaluated": 4,
- "rules_passed": 1,
- "rules_failed": 3
- },
- "rules": [
- {
- "rule_name": "s3_versioning_enabled",
- "status": "FAIL",
- "message": "S3 bucket does not have versioning enabled"
- },
- {
- "rule_name": "s3_public_access_blocked",
- "status": "FAIL",
- "message": "S3 bucket does not have public access blocked"
- },
- {
- "rule_name": "s3_encryption_enabled",
- "status": "FAIL",
- "message": "S3 bucket does not have server-side encryption enabled"
- },
- {
- "rule_name": "s3_no_public_read",
- "status": "PASS",
- "message": "S3 bucket does not allow public read access"
- }
- ]
-}
-```
-
-**Congratulations! You have successfully tested and validated your Guard Hook for S3 configurations.**
-
-The Guard Hook demonstrates how policy-as-code can be implemented using declarative Guard rules instead of custom Lambda functions, providing a more maintainable and readable approach to infrastructure compliance validation.
diff --git a/content/advanced/hooks/guard-hooks/write-guard-rules/index.ja.md b/content/advanced/hooks/guard-hooks/write-guard-rules/index.ja.md
deleted file mode 100644
index ea322400b..000000000
--- a/content/advanced/hooks/guard-hooks/write-guard-rules/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Write Guard rules for Hook"
-weight: 610
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/guard-hooks/write-guard-rules/index.md b/content/advanced/hooks/guard-hooks/write-guard-rules/index.md
deleted file mode 100644
index 1c1fa2f97..000000000
--- a/content/advanced/hooks/guard-hooks/write-guard-rules/index.md
+++ /dev/null
@@ -1,225 +0,0 @@
----
-title: "Write Guard rules for Hook"
-weight: 610
----
-
-### Write Guard Rules
-
-To ensure that our AWS Guard Hook is functional, we need to create Guard rules that will validate the S3 bucket configurations. These rules will check attributes such as versioning and public access settings before a CloudFormation stack is created or updated.
-
-This guide will walk you through creating Guard rules that enforce S3 security best practices.
-
-Before creating the rules, ensure you have access to the Guard rules directory:
-
-```sh
-# clone our repo if you have not already done so.
-git clone https://github.com/aws-samples/cfn101-workshop.git
-
-# Navigate to the directory where the Guard rules will be stored
-cd cfn101-workshop/code/workspace/hooks/guard_hook
-```
-
-#### **Step 1: Understanding Guard Rule Syntax**
-
-Guard rules use a domain-specific language (DSL) to define validation logic. The basic syntax includes:
-
-- **Resources**: Target specific AWS resource types
-- **Properties**: Access resource properties for validation
-- **Operators**: Use comparison operators like `==`, `!=`, `exists`, etc.
-- **Logical operators**: Combine conditions with `and`, `or`, `not`
-
-#### **Step 2: Create S3 Security Guard Rules**
-
-Create a new file called `s3-security-rules.guard` with the following content:
-
-```guard
-# S3 Security Guard Rules for CloudFormation Hook
-# These rules ensure S3 buckets follow security best practices
-
-# Rule 1: S3 buckets must have versioning enabled
-rule s3_versioning_enabled {
- Resources.*[ Type == 'AWS::S3::Bucket' ] {
- Properties {
- VersioningConfiguration exists
- VersioningConfiguration.Status == "Enabled"
- }
- }
-}
-
-# Rule 2: S3 buckets must have public access blocked
-rule s3_public_access_blocked {
- Resources.*[ Type == 'AWS::S3::Bucket' ] {
- Properties {
- PublicAccessBlockConfiguration exists
- PublicAccessBlockConfiguration.BlockPublicAcls == true
- PublicAccessBlockConfiguration.BlockPublicPolicy == true
- PublicAccessBlockConfiguration.IgnorePublicAcls == true
- PublicAccessBlockConfiguration.RestrictPublicBuckets == true
- }
- }
-}
-
-# Rule 3: S3 buckets should have server-side encryption enabled
-rule s3_encryption_enabled {
- Resources.*[ Type == 'AWS::S3::Bucket' ] {
- Properties {
- BucketEncryption exists
- BucketEncryption.ServerSideEncryptionConfiguration exists
- BucketEncryption.ServerSideEncryptionConfiguration[*].ServerSideEncryptionByDefault exists
- BucketEncryption.ServerSideEncryptionConfiguration[*].ServerSideEncryptionByDefault.SSEAlgorithm in ["AES256", "aws:kms"]
- }
- }
-}
-
-# Rule 4: S3 buckets should not allow public read access
-rule s3_no_public_read {
- Resources.*[ Type == 'AWS::S3::Bucket' ] {
- Properties {
- # Ensure no public read permissions in ACL
- when AccessControl exists {
- AccessControl != "PublicRead"
- AccessControl != "PublicReadWrite"
- }
- }
- }
-}
-```
-
-#### **Step 3: Understanding the Guard Rules**
-
-Let's break down what each rule does:
-
-**Rule 1: S3 Versioning Enabled** - Ensures all S3 buckets have versioning enabled for data protection by checking that `VersioningConfiguration.Status` is set to "Enabled", which protects against accidental deletion or modification of objects.
-
-**Rule 2: Public Access Blocked** - Prevents S3 buckets from being publicly accessible by verifying all four public access block settings are enabled, preventing data breaches from misconfigured public access.
-
-**Rule 3: Encryption Enabled** - Ensures data at rest is encrypted by checking for server-side encryption configuration with AES256 or KMS, protecting sensitive data stored in S3.
-
-**Rule 4: No Public Read Access** - Provides an additional check to prevent public read permissions by ensuring ACL doesn't allow public read or read-write access, preventing unauthorized data access.
-
-#### **Step 4: Test Guard Rules Locally (Optional)**
-
-Before using the rules in a Hook, you can test them locally using the Guard CLI. First, install the Guard CLI for your operating system:
-
-**For macOS and Linux:** Use the installation guide at the [AWS CloudFormation Guard documentation](https://docs.aws.amazon.com/cfn-guard/latest/ug/setting-up-linux.html).
-
-::alert[For Windows installation, follow the detailed steps in the [Windows installation guide](https://docs.aws.amazon.com/cfn-guard/latest/ug/setting-up-windows.html) which includes installing Rust and Cargo, then running `cargo install cfn-guard`.]{type="info"}
-
-Once Guard CLI is installed, create a test CloudFormation template (`test-s3-template.yaml`):
-
-```yaml
-AWSTemplateFormatVersion: "2010-09-09"
-Resources:
- TestBucket:
- Type: "AWS::S3::Bucket"
- Properties:
- BucketName: test-bucket-compliant
- VersioningConfiguration:
- Status: Enabled
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
-```
-
-3. **Test the rules**:
-
-```bash
-cfn-guard validate --rules s3-security-rules.guard --data test-s3-template.yaml
-```
-
-To see how Guard validation works with non-compliant resources, try editing the YAML file to make it non-compliant (for example, change `IgnorePublicAcls: true` to `IgnorePublicAcls: false`) and run the validation again. You'll see detailed error output showing exactly which rules failed and why:
-
-```
-/path/to/test-s3-template.yaml Status = FAIL
-FAILED rules
-s3-security-rules.guard/s3_public_access_blocked FAIL
----
-Evaluating data /path/to/test-s3-template.yaml against rules s3-security-rules.guard
-Number of non-compliant resources 1
-Resource = TestBucket {
- Type = AWS::S3::Bucket
- Rule = s3_public_access_blocked {
- ALL {
- Check = PublicAccessBlockConfiguration.IgnorePublicAcls EQUALS true {
- ComparisonError {
- Error = Check was not compliant as property value [Path=/Resources/TestBucket/Properties/PublicAccessBlockConfiguration/IgnorePublicAcls[L:11,C:26] Value=false] not equal to value [Path=[L:0,C:0] Value=true].
- PropertyPath = /Resources/TestBucket/Properties/PublicAccessBlockConfiguration/IgnorePublicAcls[L:11,C:26]
- Operator = EQUAL
- Value = false
- ComparedWith = true
- Code:
- 9. PublicAccessBlockConfiguration:
- 10. BlockPublicAcls: true
- 11. BlockPublicPolicy: true
- 12. IgnorePublicAcls: false
- 13. RestrictPublicBuckets: true
- 14. BucketEncryption:
-
- }
- }
- }
- }
-}
-```
-
-This output shows that the `s3_public_access_blocked` rule failed because `IgnorePublicAcls` was set to `false` instead of the required `true` value. The detailed error message includes the exact line number and property path where the violation occurred, making it easy to identify and fix compliance issues.
-
-#### **Step 5: Upload Guard Rules to S3**
-
-Guard Hooks require the rules to be stored in Amazon S3. Before proceeding, ensure you have configured your local AWS credentials.
-
-::alert[Set up your AWS credentials using `aws configure` or by setting up an AWS profile. For detailed guidance, see the [AWS CLI Configuration documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html).]{type="info"}
-
-1. **Create an S3 bucket**:
-
-You can create the bucket using the AWS CLI or through the [Amazon S3 Console](https://s3.console.aws.amazon.com/s3/buckets).
-
-**Bucket Naming Suggestion**: Use a unique name like `guard-hook-bucket-` (e.g., `guard-hook-bucket-john-doe`)
-
-**Using AWS CLI** (replace with your chosen bucket name):
-```bash
-export GUARD_BUCKET_NAME="guard-hook-bucket-"
-aws s3 mb s3://$GUARD_BUCKET_NAME --region us-east-1
-```
-
-**Using S3 Console**:
-- Navigate to the [Amazon S3 Console](https://s3.console.aws.amazon.com/s3/buckets)
-- Click "Create bucket"
-- Enter your bucket name: `guard-hook-bucket-`
-- Select region: `us-east-1`
-- **Best Practice**: Keep the default "Block all public access" settings enabled for security
-- Click "Create bucket"
-
-2. **Upload the Guard rules file**:
-
-```bash
-aws s3 cp s3-security-rules.guard s3://$GUARD_BUCKET_NAME/hooks/s3-security-rules.guard
-```
-
-3. **Note the S3 URI** for later use:
-
-```
-s3://$GUARD_BUCKET_NAME/hooks/s3-security-rules.guard
-```
-
-#### **Step 6: Review Guard Rule Structure**
-
-The Guard rules we created follow this structure:
-
-- **Rule Declaration**: Each rule has a unique name and is declared with the `rule` keyword
-- **Resource Selection**: Uses `Resources.*[ Type == 'ResourceType' ]` to target specific resources
-- **Property Validation**: Accesses resource properties using dot notation
-- **Conditional Logic**: Uses `when` statements for conditional validation
-- **Operators**: Employs various operators (`==`, `!=`, `exists`, `in`) for comparisons
-
-These rules will be evaluated by the Guard Hook engine whenever a CloudFormation operation targets S3 buckets, ensuring compliance with your security policies before resources are provisioned.
-
-Now that we've created our Guard rules, let's proceed to prepare the Hook execution role and activate the Guard Hook.
-
-Choose **Next** to continue!
diff --git a/content/advanced/hooks/index.ja.md b/content/advanced/hooks/index.ja.md
deleted file mode 100644
index 5c46dc8a9..000000000
--- a/content/advanced/hooks/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Hooks"
-weight: 400
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/index.md b/content/advanced/hooks/index.md
deleted file mode 100644
index 548fc7bf4..000000000
--- a/content/advanced/hooks/index.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-title: "Hooks"
-weight: 400
----
-
-### Introduction
-
-This part of the workshop focuses on how you can extend creation, provisioning, and management capabilities of [AWS CloudFormation](https://aws.amazon.com/cloudformation/) with proactive compliance validation controls you develop.
-
-[AWS CloudFormation Hooks](https://docs.aws.amazon.com/cloudformation-cli/latest/hooks-userguide/what-is-cloudformation-hooks.html) is a feature that allows you to create proactive controls (or to reuse existing ones) to validate that your CloudFormation resources are compliant with your company's best practices. For example, you could create a proactive validation control to check that an [Amazon Simple Storage Service (Amazon S3)](https://aws.amazon.com/s3/) bucket, whose desired state you describe in CloudFormation template(s), is set up by your users to have [versioning configuration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html#cfn-s3-bucket-versioningconfiguration) enabled, or if [server-side encryption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html#cfn-s3-bucket-bucketencryption) is enabled for S3 buckets you create, with CloudFormation, with an [encryption algorithm](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-serversideencryptionbydefault.html#cfn-s3-bucket-serversideencryptionbydefault-ssealgorithm) you choose from the ones that are available. Those are just two examples and, as you can imagine, there can be many others.
-
-With the examples above using an S3 bucket, when you model your hook you choose to target the `AWS::S3::Bucket` resource type. When you then create or update a stack with a template that describes an S3 bucket, your hook gets invoked before CloudFormation attempts to create or update the bucket. When invoked, your hook validates that -for example- the versioning property for your bucket is set to the `Enabled` `Status`. If you were to have 2 S3 buckets in your template, each bucket would cause an instance of the hook getting invoked (in this example, you'll have 2 hook invocations, one for each bucket).
-
-You can specify the target of your hooks invocations: resource, stack, change set, and/or Cloud Control API operations.
-
-There are two discrete workflows for hooks, each one for a specific user persona/team of a given company:
-
-- the security team, that establishes which proactive controls to enable, and
-- the application team(s), that describe the infrastructure for their applications, or for their workloads, with CloudFormation.
-
-In this lab, you'll start with the first workflow to build and test a sample hook, and then you'll create a stack to verify your hook works as you'd expect as part of the second workflow above.
-
-The Software Development Life Cycle (SDLC) process of a hook, that is part of the first workflow, can be described as follows:
-
-* develop and activate your hook, using Lambda hook, Guard hook, and/or custom hook;
-* manage the configuration of your hook: you describe the behavior of the hook (for example, whether to invoke the hook for stacks in your account in a given region, whether compliance validation errors yield to denying the provisioning of the non-compliant resource, or simply to a warning);
-* see the result of your hook evaluation
-
-Please refer to AWS CloudFormation pricing for information on charges to your account when you use hooks.
diff --git a/content/advanced/hooks/lambda-hooks/Cleanup/index.ja.md b/content/advanced/hooks/lambda-hooks/Cleanup/index.ja.md
deleted file mode 100644
index 5aac4408e..000000000
--- a/content/advanced/hooks/lambda-hooks/Cleanup/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Cleanup"
-weight: 550
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/lambda-hooks/Cleanup/index.md b/content/advanced/hooks/lambda-hooks/Cleanup/index.md
deleted file mode 100644
index 2bc6f7784..000000000
--- a/content/advanced/hooks/lambda-hooks/Cleanup/index.md
+++ /dev/null
@@ -1,50 +0,0 @@
----
-title: "Cleanup"
-weight: 550
----
-
-### Introduction
-
-### Clean Up Resources
-
-After testing is completed, please delete the resources we created during this Lab.
-#### Using AWS CLI
-Run the following commands to delete the test CloudFormation stacks:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack --stack-name ddb-noncompliant-stack --region us-east-1
-:::
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack --stack-name ddb-compliant-stack --region us-east-1
-:::
-#### Disable The Lambda Hook
-To disable a Hook in your account
-1. Sign in to the AWS Management Console and open the AWS [CloudFormation console](https://console.aws.amazon.com/cloudformation).
-
-2. On the navigation bar at the top of the screen, choose the AWS Region where the Hook is located.
-
-3. From the navigation pane, choose **Hooks**.
-
-4. Choose the name of the Hook you want to **disable**.
-
-5. On the Hook details page, to the right of the Hook's name, choose the Disable button.
-
-6. When prompted for confirmation, choose **Disable Hook**.
-
-#### Remove the Lambda Function
-
-To remove the lambda function using the AWS Console:
-
-1. Open the [AWS Lambda Console](https://console.aws.amazon.com/lambda).
-2. Find `DynamoDBConfigValidationHook` and click on the function.
-3. Click **Delete** from the **Actions** drop-down menu.
-
-**Remove Hook Execution Role**
-
-Please use the stack name provided in [Prepare to create a Lambda Hook](../prepare-lambda-hook/#deploy-the-hook-execution-role) Section
-```
-aws cloudformation delete-stack --stack-name HookExecutionRoleStack --region us-east-1
-```
-Verify that the **Lambda function, IAM roles(deployed using hook-role.yaml file)** are deleted if they are no longer needed.
-
-Almost done! Choose **Next** to continue!
diff --git a/content/advanced/hooks/lambda-hooks/activate-lambda-hook/index.ja.md b/content/advanced/hooks/lambda-hooks/activate-lambda-hook/index.ja.md
deleted file mode 100644
index 008bb51fa..000000000
--- a/content/advanced/hooks/lambda-hooks/activate-lambda-hook/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Activate a Lambda Hook"
-weight: 530
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/lambda-hooks/activate-lambda-hook/index.md b/content/advanced/hooks/lambda-hooks/activate-lambda-hook/index.md
deleted file mode 100644
index c2b76d9a7..000000000
--- a/content/advanced/hooks/lambda-hooks/activate-lambda-hook/index.md
+++ /dev/null
@@ -1,57 +0,0 @@
----
-title: "Activate a Lambda Hook"
-weight: 530
----
-
-### Introduction
-
-To use an AWS Lambda Hook in your account, you must first activate the Hook for the account and Region where you want to use it. Activating a Hook makes it usable in stack operations in the account and Region where it's activated.
-
-When you activate a Lambda Hook, CloudFormation creates an entry in your account's registry for the activated Hook as a private Hook. This allows you to set any configuration properties the Hook includes. Configuration properties define how the Hook is configured for a given AWS account and Region.
-
-#### Using AWS Console to Create a Lambda Hook
-
-##### **Open AWS CloudFormation Hooks**
-
-1. Open **AWS CloudFormation Console**.
-2. Navigate to the **Hooks** section.
-3. Click on **With Lambda** option in the **Create a Hook** dropdown list.
-
-##### **Configure Hook Settings**
-
-
-Use the following parameters when configuring the lambda hook:
-
-1. **Hook Name** – `DynamoDBConfigValidationHook`
-2. **Lambda Function ARN** – Enter the **ARN copied earlier**.
-3. **Hook Targets** – Select **Resources**.
- ::alert[We choose **Resources** as the target because our Lambda function is designed to evaluate individual CloudFormation resources (specifically DynamoDB tables) rather than the entire template. This approach aligns with our Lambda function's logic, which examines specific properties of DynamoDB table resources like ***PointInTimeRecoveryEnabled*** and ***ProvisionedThroughput***. When the hook is triggered for each relevant resource during stack operations, it ensures granular validation of these individual resource configurations.]{type="info"}
-4. **Hook Actions** – Select **Create**.
- ::alert[This implements evaluation during CloudFormation **CREATE** operation]{type="info"}
-5. **Hook Mode** – Set to **Fail**.
- ::alert[With Hook Mode being Warn the hook will only emit a warning message when a hook fails, without stopping the provisioning operation. While with Fail mode the hook will stop the provisioning operation when a Hook fails.]{type="info"}
-6. **Execution Role** – Choose **Existing Execution Role** and select the **HookExecutionRole** created earlier in the **Prepare to create a Lambda Hook** section.
-
-::alert[You can find more information about the other configuration parameters on the [AWS document page](https://docs.aws.amazon.com/cloudformation-cli/latest/hooks-userguide/lambda-hooks-activate-hooks.html)]{type="info"}
-Then click on **Next**.
-
-##### **Apply Hook filters**
-
-For **Hook filters** we will add **`AWS::DynamoDB::Table`** to filter the hook to just check for the creations of DynamoDB tables.
-
-
-
-We will use the default options for the other configurations here so there is no need to update them.
-
-##### **Review and Create Hook**
-
-1. Click **Next**.
-2. Review the settings.
-3. Click **Create** to register the Hook.
- 
-4. Then wait for a few seconds for the Hook to be created.
- 
-
-### Conclusion
-
-Once the Hook is activated, it will automatically evaluate CloudFormation stack changes based on the defined targets and actions. By enforcing best practices and compliance requirements, the Lambda Hook ensures that only approved configurations are deployed. You can now proceed to the test section and monitor the Hook's behavior in your stack operations using the activated hook.
diff --git a/content/advanced/hooks/lambda-hooks/deploy-lambda-function-for-hook/index.ja.md b/content/advanced/hooks/lambda-hooks/deploy-lambda-function-for-hook/index.ja.md
deleted file mode 100644
index 5aa40a1fb..000000000
--- a/content/advanced/hooks/lambda-hooks/deploy-lambda-function-for-hook/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Deploy Lambda function for Hook"
-weight: 510
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/lambda-hooks/deploy-lambda-function-for-hook/index.md b/content/advanced/hooks/lambda-hooks/deploy-lambda-function-for-hook/index.md
deleted file mode 100644
index 8eef34249..000000000
--- a/content/advanced/hooks/lambda-hooks/deploy-lambda-function-for-hook/index.md
+++ /dev/null
@@ -1,323 +0,0 @@
----
-title: "Deploy Lambda function for Hook"
-weight: 510
----
-
-### Deploy Lambda Function
-
-To ensure that our AWS Lambda Hook is functional, we need to deploy the Lambda function that will validate the DynamoDB configurations. This function will check attributes such as read/write capacity and point-in-time recovery before a CloudFormation stack is created or updated.
-
-This guide will walk you through deploying the Lambda function manually via the AWS Console.
-
-Before deploying, ensure you have access to the Lambda function code, you could achieve that by the using following commands in your terminal:
-
-```sh
-# clone our repo if you have not already done so.
-git clone https://github.com/aws-samples/cfn101-workshop.git
-
-# Navigate to the directory where the Lambda function is stored
-cd cfn101-workshop/code/workspace/hooks/lambda_hook
-```
-
-#### **Step 1: Open AWS Lambda Console**
-
-1. Go to [AWS Lambda Console](https://console.aws.amazon.com/lambda).
-2. Click on **Create function**.
-3. Under **Choose a function type**, select **Author from scratch**.
-
-#### **Step 2: Configure Function Settings**
-
-1. **Function name**: Enter a name (e.g., `DynamoDBConfigValidationHook`).
-2. **Runtime**: Select `Python 3.13`.
-3. **Execution role**:
- - Choose **Create a new role with basic Lambda permissions** which is the default option for execution role.
- 
-4. **Click on Create function**
-
-#### **Step 3: Deploy the Lambda Code**
-
-1. Paste in below lambda code:
-
-```python
-# Lambda function for evaluating DynamoDB table compliance
-
-import json
-import logging
-
-# Set up logging
-logger = logging.getLogger()
-logger.setLevel(logging.INFO)
-
-def validate_dynamodb_table(table_config):
- """
- Validate the DynamoDB table properties to enforce compliance.
- """
- validation_errors = []
-
- logger.info(f"Validating DynamoDB table properties: {json.dumps(table_config, indent=2)}")
-
- # Check Read and Write Capacity
- read_capacity = table_config.get('ProvisionedThroughput', {}).get('ReadCapacityUnits', 0)
- write_capacity = table_config.get('ProvisionedThroughput', {}).get('WriteCapacityUnits', 0)
- if read_capacity > 20 or write_capacity > 20:
- validation_errors.append("ReadCapacityUnits and WriteCapacityUnits must not exceed 20.")
-
- # Check Point-In-Time Recovery
- point_in_time_recovery = table_config.get('PointInTimeRecoverySpecification', {}).get('PointInTimeRecoveryEnabled', False)
- if not point_in_time_recovery:
- validation_errors.append("PointInTimeRecoverySpecification must be enabled.")
-
- return validation_errors
-
-def lambda_handler(event, context):
- """
- Entry point for the Lambda function. Handles validation of DynamoDB configurations.
- """
- logger.info(f"Received event: {json.dumps(event, indent=2)}")
-
- try:
- # Validate if 'requestData' is present in the event
- if "requestData" not in event:
- logger.error("Error: Missing 'requestData' key in event payload.")
- return {
- 'hookStatus': 'FAILED',
- 'errorCode': 'InvalidRequest',
- 'message': "Missing 'requestData' key in event payload.",
- 'clientRequestToken': event.get('clientRequestToken', 'N/A')
- }
-
- request_data = event['requestData']
- logger.info(f"Processing Request Data: {json.dumps(request_data, indent=2)}")
-
- # Ensure 'targetType' and 'targetModel' are present
- if 'targetType' not in request_data or 'targetModel' not in request_data:
- logger.error("Error: Missing 'targetType' or 'targetModel' in requestData.")
- return {
- 'hookStatus': 'FAILED',
- 'errorCode': 'InvalidRequest',
- 'message': "Missing 'targetType' or 'targetModel' in requestData.",
- 'clientRequestToken': event.get('clientRequestToken', 'N/A')
- }
-
- # Process only DynamoDB table resources
- if request_data['targetType'] == 'AWS::DynamoDB::Table':
- table_properties = request_data['targetModel'].get('resourceProperties', {})
- validation_errors = validate_dynamodb_table(table_properties)
-
- if validation_errors:
- logger.warning(f"Validation failed: {', '.join(validation_errors)}")
- return {
- 'hookStatus': 'FAILED',
- 'errorCode': 'NonCompliant',
- 'message': f"DynamoDB configuration validation failed: {', '.join(validation_errors)}",
- 'clientRequestToken': event['clientRequestToken']
- }
-
- logger.info("DynamoDB configuration validation successful.")
- return {
- 'hookStatus': 'SUCCESS',
- 'message': 'DynamoDB configuration validation successful',
- 'clientRequestToken': event['clientRequestToken']
- }
-
- else:
- logger.error(f"Error: Unsupported targetType {request_data['targetType']}.")
- return {
- 'hookStatus': 'FAILED',
- 'errorCode': 'InvalidResource',
- 'message': f"Unsupported targetType {request_data['targetType']}.",
- 'clientRequestToken': event['clientRequestToken']
- }
-
- except Exception as e:
- logger.exception("Unexpected error occurred.")
- return {
- 'hookStatus': 'FAILED',
- 'errorCode': 'InternalFailure',
- 'message': f'Hook encountered an error: {str(e)}',
- 'clientRequestToken': event.get('clientRequestToken', 'N/A')
- }
-
-```
-
-2. Click on the **Deploy** button.
- 
-3. The function is now live and ready to be tested.
-
-#### Step 4: Review Lambda Function
-
-Before we dive into testing the lambda function let's review what this lambda function is doing.
-
-To navigate to the Lambda function code:
-
-1. Open the **AWS Lambda Console**.
-2. Locate the function deployed for the hook (e.g., `DynamoDBConfigValidationHook`).
-3. Click on the function to view its implementation.
-
-Now, let's do a quick overview of the Lambda function implementation. There are plenty comments in the lambda code explaining each line of the code, take a look at them if you have time.
-
-##### Stack Resource Evaluation
-
-The function evaluates below deployment configurations for Amazon DynamoDB:
-
-- **Read and Write Capacity** (should not exceed 20).
-- **Point-In-Time Recovery** (must be enabled).
-- **Billing Mode** (must be PAY_PER_REQUEST).
-
-##### Request Input
-
-Here is an example input for the request:
-
-```json
-{
- "requestData": {
- "targetName": "AWS::DynamoDB::Table",
- "targetType": "AWS::DynamoDB::Table",
- "targetModel": {
- "resourceProperties": {
- "TableName": "ExampleTable",
- "BillingMode": "PAY_PER_REQUEST",
- "PointInTimeRecoverySpecification": {
- "PointInTimeRecoveryEnabled": true
- },
- "GlobalSecondaryIndexes": [
- {
- "IndexName": "ExampleGSI",
- "KeySchema": [{ "AttributeName": "Id", "KeyType": "HASH" }]
- }
- ],
- "ProvisionedThroughput": {
- "ReadCapacityUnits": 10,
- "WriteCapacityUnits": 10
- }
- }
- }
- },
- "clientRequestToken": "example-token"
-}
-```
-
-##### Response
-
-Now, lets review how Lambda function needs to respond back to communicate request success or failure.
-
-##### Response Attributes Explanation
-
-**hookStatus**: Represents the overall validation status. Possible values include:
-
-- "SUCCESS": Indicates that the validation checks have passed.
-- "FAILED": Indicates that the validation checks have failed.
-
-**message**: Provides a human-readable explanation of the validation result.
-
-- In a success response, it confirms that the configuration meets the required standards.
-- In a failure response, it specifies the issue that caused the validation failure.
-
-**clientRequestToken**: A unique identifier associated with the request, which helps track validation attempts.
-
-**errorCode** (only in failure responses): Provides a specific error code related to the validation failure.
-
-- "NonCompliant": Indicates that the DynamoDB configuration does not meet compliance requirements.
-- "InvalidRequest": This means needed input from the hook event did not include attributes like `requestData,targetModel or targetType`
-
-###### Example of a Successful Response
-
-If the DynamoDB configuration has passed all validation checks, including Check Point-In-Time Recovery and Check Read and Write Capacity, the Lambda function returns the following response:
-
-```json
-{
- "hookStatus": "SUCCESS",
- "message": "DynamoDB configuration validation successful",
- "clientRequestToken": "example-token"
-}
-```
-
-##### Example of a Failed Response
-
-If the DynamoDB configuration does not have the Check Point-In-Time Recovery feature enabled, the validation will fail, and the Lambda function will return a response similar to this:
-
-```json
-{
- "hookStatus": "FAILED",
- "errorCode": "NonCompliant",
- "message": "Point-In-Time Recovery must be enabled.",
- "clientRequestToken": "example-token"
-}
-```
-
-This response indicates that the configuration is non-compliant and requires corrective action to pass the validation checks.
-
-#### **Step 5(Optional): Mock Test Lambda Function**
-
-Before integrating the Lambda function with CloudFormation hooks, it's helpful to test it independently. This step allows you to simulate how the hook will utilize the Lambda function during actual CloudFormation deployments.
-
-Let's create a test event to mock the hook's behavior:
-
-1. Navigate to the Lambda console and select the function we've created earlier in step 3.
-2. Click on the "Test" tab
-3. Create a new test event with this sample payload:
-
-```json
-{
- "requestData": {
- "targetName": "AWS::DynamoDB::Table",
- "targetType": "AWS::DynamoDB::Table",
- "targetModel": {
- "resourceProperties": {
- "TableName": "TestTable",
- "PointInTimeRecoverySpecification": {
- "PointInTimeRecoveryEnabled": true
- },
- "ProvisionedThroughput": {
- "ReadCapacityUnits": 5,
- "WriteCapacityUnits": 5
- }
- }
- }
- },
- "clientRequestToken": "test-token-123"
-}
-```
-
-##### To create a test event in the AWS Management Console, please follow these steps:
-
-1. Go to the Lambda we've created earlier, click on the blue **Test** button to create a test event.
-2. A dropdown will appear, click on the **Create a new test event**, then give the test event a name of your choice. (in the example below we've named it **_mytestevent_**)
-3. Paste the above event JSON into the **Event JSON** box.
-4. Save the test and then invoke it to test the lambda.
-
-
-
-##### Test Scenario 1: Compliant Configuration
-
-When you execute the test with the above payload, you should receive a successful response:
-Click on the test button to test this hook, you will see the lambda return something similar to this:
-
-```JSON
-{
-"hookStatus": "SUCCESS",
-"message": "DynamoDB configuration validation successful",
-"clientRequestToken": "test-token-123"
-}
-```
-
-##### Test Scenario 2: Non-Compliant Configuration
-
-Modify the test event with these changes:
-
-- Update the test event with `ReadCapacityUnits` value to more than 20,
-- `PointInTimeRecoveryEnabled` value to `False`
- and test again, with our non-compliant input, the Lambda function should return a failure response like below:
-
-```JSON
-{
-"hookStatus": "FAILED",
-"errorCode": "NonCompliant",
-"message": "DynamoDB configuration validation failed: ReadCapacityUnits and WriteCapacityUnits must not exceed 20., PointInTimeRecoverySpecification must be enabled.",
-"clientRequestToken": "test-token-123"
-}
-```
-
-These test scenarios demonstrate how the Lambda function validates DynamoDB table configurations before actual deployment. This pre-deployment validation helps ensure that your DynamoDB tables meet the required security and operational standards.
-
-Congrats on reaching this point! Now that we've verified the Lambda function works as expected, let's proceed to configuring the CloudFormation hook to use this Lambda function we've deployed.
diff --git a/content/advanced/hooks/lambda-hooks/index.ja.md b/content/advanced/hooks/lambda-hooks/index.ja.md
deleted file mode 100644
index 1843ebf34..000000000
--- a/content/advanced/hooks/lambda-hooks/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Lambda Hooks"
-weight: 500
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/lambda-hooks/index.md b/content/advanced/hooks/lambda-hooks/index.md
deleted file mode 100644
index 41af1f243..000000000
--- a/content/advanced/hooks/lambda-hooks/index.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-title: "Lambda Hooks"
-weight: 500
----
-
-### Introduction
-
-AWS CloudFormation Lambda Hooks enable you to validate CloudFormation and AWS Cloud Control API operations using your custom code logic. When an operation is triggered, your Hook can:
-
-* Evaluate the operation against your defined criteria.
-* Either block the operation if it doesn't meet requirements
- Or allow it to proceed with a warning message.
-
-These Hooks act as custom validation checkpoints that you can configure to intercept and assess specific CloudFormation operations before they're executed.
-
-You can configure Lambda Hooks to intercept and evaluate the following CloudFormation operations:
-* Resource operations
-* Stack operations
-* Change set operations
-
-## In This Lab
-
-We will explore how Lambda Hooks can be effectively used for resource-level operations. Consider a common security requirement: as a member of an organization's security team, you need to ensure all DynamoDB tables deployed through CloudFormation have encryption enabled.
-
-In the example, we will review and deploy a Lambda function required for Lambda Hooks, followed by registering and activating the Lambda Hook using the deployed function. After activation, we'll test the Lambda hook functionality with new CloudFormation deployments and explore the steps for validating and troubleshooting Lambda Hook invocations.
diff --git a/content/advanced/hooks/lambda-hooks/prepare-lambda-hook/index.ja.md b/content/advanced/hooks/lambda-hooks/prepare-lambda-hook/index.ja.md
deleted file mode 100644
index a4d54353e..000000000
--- a/content/advanced/hooks/lambda-hooks/prepare-lambda-hook/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Prepare to create a Lambda Hook"
-weight: 510
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/lambda-hooks/prepare-lambda-hook/index.md b/content/advanced/hooks/lambda-hooks/prepare-lambda-hook/index.md
deleted file mode 100644
index 225aabaa1..000000000
--- a/content/advanced/hooks/lambda-hooks/prepare-lambda-hook/index.md
+++ /dev/null
@@ -1,111 +0,0 @@
----
-title: "Prepare to create a Lambda Hook"
-weight: 510
----
-
-### **Introduction**
-
-Before you create a **Lambda Hook** for validating **DynamoDB configurations**, we need to complete the following steps to create an execution role with IAM permissions and a trust policy to allow CloudFormation to invoke a Lambda Hook.
-
-1. **Retrieve the Lambda Function ARN** – This ARN is required to configure the Hook Execution Role.
-2. **Deploy the CloudFormation Hook Execution Role** – This role allows CloudFormation Hooks to assume permissions for invoking Lambda and reading DynamoDB configurations.
-3. **Register the Hook in AWS CloudFormation** – The Hook will be configured to evaluate DynamoDB resource changes before provisioning.
-4. **Attach Hook to a CloudFormation Stack** – This ensures enforcement during stack deployments.
-
----
-
-### **Step 1: Retrieve Lambda Function ARN**
-
-Since the Lambda function **DynamoDBConfigValidationHook** has already been deployed, follow these steps to find its **ARN**:
-
-1. **Go to the AWS Lambda Console**:
-
- - Open [AWS Lambda Console](https://console.aws.amazon.com/lambda).
- - Search for **DynamoDBConfigValidationHook**.
- - Click on the function name.
-
-2. **Copy the ARN**:
- - At the top-right of the **Lambda function details page**, find the **Function ARN**.
- - The ARN format will be:
- ```
- arn:aws:lambda:::function:DynamoDBConfigValidationHook
- ```
- - Copy this ARN for use in the next step.
-
----
-
-### **Step 2: Create CloudFormation for Lambda Hook IAM Role**
-
-To enable the **CloudFormation Hook** to validate **DynamoDB configurations** by invoking the Lambda function, we must create an IAM role that CloudFormation Hooks can assume. This role ensures that the hook has the necessary permissions to:
-
-**Invoke the Lambda Function**: The hook calls the Lambda function, which performs validation checks on the DynamoDB configuration.
-
-By defining a dedicated **IAM role**, we ensure that CloudFormation Hooks can securely perform these operations without requiring excessive permissions across AWS services.
-
-#### **Deploy the Hook Execution Role**
-
-::alert[If you've cloned our repo then you can also find this yaml file in our _cfn101-workshop/code/workspace/hooks/hook-role.yaml_ folder.]{type="info"}
-
-1. Copy the **Amazon Resource Name (ARN) of your Lambda function** from the AWS Management Console.
-2. Open **hook-role.yaml** file then replace `` with the copied ARN and save the **hook-role.yaml** file:
-
-```yaml
-AWSTemplateFormatVersion: "2010-09-09"
-Description: "IAM role configuration for Lambda Hook"
-
-Resources:
- HookExecutionRole:
- Type: "AWS::IAM::Role"
- Properties:
- AssumeRolePolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Effect: Allow
- Principal:
- Service: hooks.cloudformation.amazonaws.com
- Action: "sts:AssumeRole"
- ManagedPolicyArns:
- - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
- Policies:
- - PolicyName: InvokeHookFunction
- PolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Effect: Allow
- Action:
- - "lambda:InvokeFunction"
- Resource: "" # Replace this with the actual Lambda ARN
-```
-
-
-#### **3.Deploy the Hook Role via AWS Console**
-
-1. **Open AWS CloudFormation Console**:
-
- - Navigate to [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation).
- - Click **Create Stack** → **With new resources (standard)**.
- - Upload the modified `hook-role.yaml` file (with the correct Lambda function ARN).
- 
-
-2. **Provide Stack Details**:
-
- - Enter a **stack name** (e.g., `HookExecutionRoleStack`).
- - Click **Next**.
-
-3. **Configure Stack Settings**:
-
- - Leave the default values unless modifications are needed.
- - Click **Next**.
-
-4. **Review and Create**:
- - Click **Create Stack**.
-
-5. **Wait for Deployment Completion**:
- - Navigate to the **Resources** tab.
- - Look for `HookExecutionRole` and **copy its Physical ID** for later use.
-
-Now, all the preparation is done. The Lambda we created is now ready, and we need to activate the Lambda hook.
-
-Choose **Next** to continue!
-
----
diff --git a/content/advanced/hooks/lambda-hooks/test-lambda-hook/index.ja.md b/content/advanced/hooks/lambda-hooks/test-lambda-hook/index.ja.md
deleted file mode 100644
index 8a395be4b..000000000
--- a/content/advanced/hooks/lambda-hooks/test-lambda-hook/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Test Lambda Hook"
-weight: 540
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/lambda-hooks/test-lambda-hook/index.md b/content/advanced/hooks/lambda-hooks/test-lambda-hook/index.md
deleted file mode 100644
index 6b8555be2..000000000
--- a/content/advanced/hooks/lambda-hooks/test-lambda-hook/index.md
+++ /dev/null
@@ -1,284 +0,0 @@
----
-title: "Test Lambda Hook"
-weight: 540
----
-
-### **Introduction**
-
-Now that we have deployed the **DynamoDBConfigValidationHook**, we need to test it to ensure it correctly validates DynamoDB configurations before CloudFormation provisions resources.
-
-We will test the hook with two different CloudFormation stacks.
-
-1. **A non-compliant DynamoDB table** that violates the validation rules and fails the CloudFormation Stack deployment.
-2. **A compliant DynamoDB table** that meets all validation criteria which results into successful deployment of CloudFormation stack.
-
----
-
-::alert[To get started, ensure that you are in `cfn101-workshop/code/workspace/hooks/lambda_hook`directory.]{type="info"}
-
-#### **Scenario 1: Non-Compliant DynamoDB Table (Validation Failure)**
-
-Locate and open the `noncompliant-ddb.yaml` file.
-The CloudFormation template in this file **violates several validation rules** that the Lambda Hook is currently validating.
-
-```
-AWSTemplateFormatVersion: '2010-09-09'
-Resources:
- NonCompliantDynamoDB:
- Type: 'AWS::DynamoDB::Table'
- Properties:
- TableName: NonCompliantTable
- AttributeDefinitions:
- - AttributeName: "Id"
- AttributeType: "S"
- KeySchema:
- - AttributeName: "Id"
- KeyType: "HASH"
- ProvisionedThroughput:
- ReadCapacityUnits: 25 # Exceeds allowed limit
- WriteCapacityUnits: 10
- GlobalSecondaryIndexes: []
- PointInTimeRecoverySpecification:
- PointInTimeRecoveryEnabled: false # Must be enabled
- BillingMode: "PROVISIONED" # Must be PAY_PER_REQUEST
-```
-
-Next, from the directory where the file above is, use the AWS CLI to create a stack, in the us-east-1 region, with that template:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-
-aws cloudformation create-stack \
- --stack-name ddb-noncompliant-stack \
- --template-body file://noncompliant-ddb.yaml \
- --region us-east-1
-:::
-
-The cloudformation `create-stack` command will return an output in JSON format like this:
-
-```JSON
-{
- "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/ddb-noncompliant-stack/b2xxxxxxx-fxx-11xxf-9xx4-xxxxxxxxxxx7"
-}
-```
-
-Then let's check the stack events and hook evaluation results using the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-events \
- --stack-name ddb-noncompliant-stack \
- --query 'StackEvents[?HookType!=`null` && contains(HookType, `DynamoDBConfigValidationHook`)]' \
- --region us-east-1
-:::
-
-##### Checking for Hook Status Messages
-
-When executing the above command, you need to look for the HookStatus field in the response. Initially, you might see `"HOOK_IN_PROGRESS"` status, which means the hook is still evaluating the template.
-
-You should continue running the command repeatedly (every few seconds) until you see either:
-
-- "HookStatus": **_"HOOK_COMPLETE_FAILED"_** (for non-compliant templates)
-- "HookStatus": **_"HOOK_COMPLETE_SUCCEEDED"_** (for compliant templates)
-
-Since the stack contains a DynamoDB definition that is non-compliant according to the validation logic in the Lambda Hook, the stack will fail to create. The `describe-stack-events` command will show the hook evaluation results similar to the following:
-
-```json
-[
- {
- "StackId": "arn:aws:cloudformation:region:account-id:stack/ddb-noncompliant-stack/stack-id",
- "EventId": "NonCompliantDynamoDB-example-id-1",
- "StackName": "ddb-noncompliant-stack",
- "LogicalResourceId": "NonCompliantDynamoDB",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::DynamoDB::Table",
- "Timestamp": "2025-03-14T01:31:49.324000+00:00",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "Private::Lambda::DynamoDBConfigValidationHook",
- "HookStatus": "HOOK_COMPLETE_FAILED",
- "HookStatusReason": "Hook failed with message: DynamoDB configuration validation failed: ReadCapacityUnits and WriteCapacityUnits must not exceed 20., PointInTimeRecoverySpecification must be enabled.",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookFailureMode": "FAIL"
- },
- {
- "StackId": "arn:aws:cloudformation:region:account-id:stack/ddb-noncompliant-stack/stack-id",
- "EventId": "NonCompliantDynamoDB-example-id-2",
- "StackName": "ddb-noncompliant-stack",
- "LogicalResourceId": "NonCompliantDynamoDB",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::DynamoDB::Table",
- "Timestamp": "2025-03-14T01:31:48.536000+00:00",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "Private::Lambda::DynamoDBConfigValidationHook",
- "HookStatus": "HOOK_IN_PROGRESS",
- "HookStatusReason": "Invoking hook",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookFailureMode": "FAIL"
- }
-]
-```
-
-The stack events show the progression and failure of the non-compliant stack deployment:
-
-1. Initially, the hook starts its evaluation (HOOK_IN_PROGRESS) during the PRE_PROVISION phase
-2. The hook then fails (HOOK\*COMPLETE_FAILED) with specific validation errors:
- - ReadCapacityUnits and WriteCapacityUnits exceed the maximum allowed value of 20
- - Point-in-Time Recovery is not enabled
-3. Because the hook's HookFailureMode is set to FAIL, the stack creation is halted and rolled back
-
-This demonstrates how the Lambda Hook effectively prevents the deployment of DynamoDB tables that don't meet the specified compliance requirements, ensuring consistent configuration standards across your AWS infrastructure.
-
-**Understand CloudFormation Stack Failure**
-
-In order to understand the detailed reason for stack failure in the AWS Console, follow the steps below.
-
-- Navigate to [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation).
-- Locate the latest deployment for `ddb-noncompliant-stack` Stack.
-- Navigate to the Events section.
-- Locate the `DynamoDBConfigValidationHook` under the Hook invocations section. This entry will contain details about the status of Hook as _Fail_ and Hook status reason with a detailed error message as provided by the Lambda Function.
-
-**CloudFormation Stack Failure Output**
-
-
-**Hook Invocation Error Details**
-Here is an example of the `HOOK_COMPLETE_FAILED` status:
-
-
-
----
-
-### **Scenario 2: Compliant DynamoDB Table**
-
-Locate and open the `compliant-ddb.yaml` file.
-The CloudFormation template in this file **meets all the required compliance checks** that the Lambda Hook is currently validating.
-
-```
-
-AWSTemplateFormatVersion: '2010-09-09'
-Resources:
-CompliantDynamoDB:
-Type: 'AWS::DynamoDB::Table'
-Properties:
-TableName: CompliantTable # Ensuring a table name is set
-AttributeDefinitions: - AttributeName: "Id"
-AttributeType: "S" # Defining the primary key attribute type as String
-KeySchema: - AttributeName: "Id"
-KeyType: "HASH" # Using a HASH key as the partition key
-BillingMode: "PAY_PER_REQUEST" # Compliance: Must be PAY_PER_REQUEST
-PointInTimeRecoverySpecification:
-PointInTimeRecoveryEnabled: true # Compliance: Point-in-time recovery must be enabled
-GlobalSecondaryIndexes: - IndexName: "GSI1"
-KeySchema: - AttributeName: "Id"
-KeyType: "HASH"
-Projection:
-ProjectionType: "ALL" # Compliance: At least one Global Secondary Index (GSI) must be defined
-
-```
-
-Next, from the directory where the file above is, use the AWS CLI to create a stack, in the us-east-1 region, with that template:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name ddb-compliant-stack \
- --template-body file://compliant-ddb.yaml \
- --region us-east-1
-:::
-
-To monitor the stack creation progress and view the hook evaluation results, use the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-events \
- --stack-name ddb-compliant-stack \
- --query 'StackEvents[?HookType!=`null` && contains(HookType, `DynamoDBConfigValidationHook`)]' \
- --region us-east-1
-:::
-
-##### Checking for Hook Status Messages
-
-As with the non-compliant stack, you need to run the describe-stack-events command repeatedly until you see the final hook status:
-
-- If you initially see the only event with "HookStatus": `"HOOK_IN_PROGRESS"`, wait a few seconds and run the command again
-- Continue checking until you see "HookStatus": "HOOK_COMPLETE_SUCCEEDED", which indicates the hook validation passed.
-
-For a compliant stack, you should see events similar to this:
-
-```json
-[
- {
- "StackId": "arn:aws:cloudformation:region:account-id:stack/ddb-compliant-stack/stack-id",
- "EventId": "CompliantDynamoDB-example-id-1",
- "StackName": "ddb-compliant-stack",
- "LogicalResourceId": "CompliantDynamoDB",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::DynamoDB::Table",
- "Timestamp": "2025-03-14T01:37:48.528000+00:00",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "Private::Lambda::DynamoDBConfigValidationHook",
- "HookStatus": "HOOK_COMPLETE_SUCCEEDED",
- "HookStatusReason": "Hook succeeded with message: DynamoDB configuration validation successful",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookFailureMode": "FAIL"
- },
- {
- "StackId": "arn:aws:cloudformation:region:account-id:stack/ddb-compliant-stack/stack-id",
- "EventId": "CompliantDynamoDB-example-id-2",
- "StackName": "ddb-compliant-stack",
- "LogicalResourceId": "CompliantDynamoDB",
- "PhysicalResourceId": "",
- "ResourceType": "AWS::DynamoDB::Table",
- "Timestamp": "2025-03-14T01:37:47.833000+00:00",
- "ResourceStatus": "CREATE_IN_PROGRESS",
- "HookType": "Private::Lambda::DynamoDBConfigValidationHook",
- "HookStatus": "HOOK_IN_PROGRESS",
- "HookStatusReason": "Invoking hook",
- "HookInvocationPoint": "PRE_PROVISION",
- "HookFailureMode": "FAIL"
- }
-]
-```
-
-Unlike the non-compliant stack, these stack events show the successful progression of the compliant stack deployment:
-
-1. The hook begins its evaluation (`"HOOK_IN_PROGRESS"`) during the PRE_PROVISION phase
-2. The hook then completes successfully (HOOK_COMPLETE_SUCCEEDED), confirming that:
- - The DynamoDB table configuration meets all compliance requirements
- - The hook validation allows the stack creation to proceed
-
-To verify the complete stack creation, you can navigate to the AWS CloudFormation Console and check that the stack status is CREATE_COMPLETE.
-
-::alert[While the hook validation succeeded, the final stack creation still depends on other factors such as IAM permissions and service quotas.]{type="info"}
-
-**Review CloudFormation Stack Creation in the AWS Console**
-
-You can review stack and Hook execution status in the AWS Console, by following the steps below.
-
-- Navigate to [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation).
-- Locate the latest deployment for `ddb-compliant-stack` Stack.
- - If the status is `CREATE_COMPLETE`, it means the DynamoDB table configuration met all compliance checks enforced by the Lambda Hook, and the stack deployment was successful.
- - If not check the Events output for errors.
-- Navigate to the Events section.
-- Locate the `DynamoDBConfigValidationHook` under the Hook invocations section. This entry will contain details about the status of the Hook and **Hook status reason** with a successful execution message as provided by the Lambda Function.
-
-1. **CloudFormation Stack Creation Output**
- 
-
-2. **Hook Invocation Details**
- 
-
----
-
-### View Logs in CloudWatch
-
-To analyze validation logs, follow these steps:
-
-1. Open **Amazon CloudWatch Console**.
-2. Navigate to **Logs > Log Groups**.
-3. Locate **`/aws/lambda/DynamoDBConfigValidationHook`**.
-4. Review log messages to confirm validation checks and errors:
-
-- The following screenshot shows **an example log of the successful execution of our Lambda Hook**, confirming that the stack creation passed all validation checks:
- 
-
-- In contrast, the screenshot below illustrates **an example log of a failed stack** creation due to non-compliance with the validation rules enforced by the Lambda Hook:
- 
- ::alert[In CloudWatch Logs console, you can search log messages with specific message text shown in the screenshot.]{type="info"}
-
-**Congratulations! You have successfully tested and validated your Lambda Hook for DynamoDB configurations.**
diff --git a/content/advanced/hooks/prerequisites/index.ja.md b/content/advanced/hooks/prerequisites/index.ja.md
deleted file mode 100644
index c972f03cb..000000000
--- a/content/advanced/hooks/prerequisites/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Prerequisites"
-weight: 410
----
-
-Japanese translation is not available yet. Please use the English version.
diff --git a/content/advanced/hooks/prerequisites/index.md b/content/advanced/hooks/prerequisites/index.md
deleted file mode 100644
index a03996416..000000000
--- a/content/advanced/hooks/prerequisites/index.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-title: "Prerequisites"
-weight: 410
----
-
-### Hooks Development Tools
-Before proceeding to the next section, choose to install the following prerequisites:
-
-* install the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-reference.html#serverless-sam-cli) by following notes for your operating system in links shown next. When you install the SAM CLI, follow also notes to install Docker (unless you have already installed it), that is needed for running contract tests:
-
- - [AWS SAM CLI on Linux](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html)
- - [AWS SAM CLI on Windows](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install-windows.html)
- - [AWS SAM CLI on macOS](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install-mac.html)
-
-* install the [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html), and plugin(s) for supported languages that you wish to use.
-
- Use `pip` to install the CloudFormation CLI and language plugins supported for hooks:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- pip install cloudformation-cli cloudformation-cli-python-plugin cloudformation-cli-java-plugin
- :::
-
-::alert[If you already have version 1.0 of the CloudFormation CLI installed, it is recommended to upgrade it to version 2.0, and to upgrade language plugin(s) you use as well. For the upgrade, you can use the `--upgrade` option for the `pip install` command shown previously, and include language plugins you use or plan to use. For more information, see *Upgrading to CFN-CLI 2.0* further down on this [page](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html#resource-type-setup).]{type="info"}
-
-* for the [Custom Hooks](../example-in-python) lab, install the following packages (`cloudformation-cli-python-lib` and `pytest-cov` are needed for running unit tests for the sample application; you'll use the other packages as examples for maintaining the code for the hook you'll build):
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- pip install cloudformation-cli-python-lib flake8 flake8-docstrings mypy pytest-cov
- :::
-
-Choose **Next** to continue!
diff --git a/content/advanced/index.ja.md b/content/advanced/index.ja.md
deleted file mode 100644
index 449f9a1fa..000000000
--- a/content/advanced/index.ja.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "上級編"
-weight: 50
----
-
-ワークショップの**上級編**へようこそ。
-
-この編では、開発した拡張機能を使用して [AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/) の作成、プロビジョニング、管理に関する機能を拡張する方法に焦点を当てます。
-
-[AWS CloudFormation レジストリ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/registry.html)を活用し、AWS アカウントで使用することができる拡張機能を管理します。拡張タイプはパブリックとプライベートが存在し、[モジュール](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/modules.html)、[リソースタイプ](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-types.html)、[フック](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/hooks.html)で構成されます。
diff --git a/content/advanced/index.md b/content/advanced/index.md
deleted file mode 100644
index c0db24a2b..000000000
--- a/content/advanced/index.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "Advanced"
-weight: 50
----
-
-Welcome to the **Advanced** part of the workshop.
-
-This part of the workshop focuses on how you can extend the creation, provisioning, and management capabilities of [AWS CloudFormation](https://aws.amazon.com/cloudformation/) with extensions you develop.
-
-You leverage the [AWS CloudFormation registry](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry.html) to manage extensions that you can choose to use in your account. Extensions can be public or private, and include [modules](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/modules.html), [resource types](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-types.html), and [hooks](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html).
diff --git a/content/advanced/modules/cleanup/index.ja.md b/content/advanced/modules/cleanup/index.ja.md
deleted file mode 100644
index da08a33a5..000000000
--- a/content/advanced/modules/cleanup/index.ja.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-title: "クリーンアップ"
-weight: 340
----
-
-## クリーンアップ
-
-このモジュールで作成したリソースをクリーンアップするには、次の手順に従います。
-
-サンプルモジュールを使用したサンプルスタックを削除します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack --stack-name cfn-workshop-modules
-aws cloudformation wait stack-delete-complete --stack-name cfn-workshop-modules
-:::
-
-:::alert{header="チャレンジを完了した場合にのみ必要" type="warning"}
-モジュールのバージョン `00000001` を CloudFormation レジストリから登録解除します。登録したモジュールのバージョン毎に、この手順を繰り返す必要があります (登録解除できないデフォルトバージョンは例外)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation deregister-type --type MODULE --type-name CFNWORKSHOP::EC2::VPC::MODULE --version-id 00000001
-:::
-
-CloudFormation レジストリからモジュールを登録解除します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation deregister-type --type MODULE --type-name CFNWORKSHOP::EC2::VPC::MODULE
-:::
diff --git a/content/advanced/modules/cleanup/index.md b/content/advanced/modules/cleanup/index.md
deleted file mode 100644
index 05fe9ed43..000000000
--- a/content/advanced/modules/cleanup/index.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-title: "Clean up"
-weight: 340
----
-
-## Clean Up
-
-To clean up the resources you created in this module, follow steps shown next.
-
-Delete the sample stack that consumed the sample module:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack --stack-name cfn-workshop-modules
-aws cloudformation wait stack-delete-complete --stack-name cfn-workshop-modules
-:::
-
-:::alert{header="Only required if you completed the challenge" type="warning"}
-Deregister version `00000001` of the module from the CloudFormation Registry. You will need to repeat this step for each version of this module you registered (except for the default version that cannot be deregistered):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation deregister-type --type MODULE --type-name CFNWORKSHOP::EC2::VPC::MODULE --version-id 00000001
-:::
-
-Deregister the module from the CloudFormation Registry:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation deregister-type --type MODULE --type-name CFNWORKSHOP::EC2::VPC::MODULE
-:::
diff --git a/content/advanced/modules/consume-example/index.ja.md b/content/advanced/modules/consume-example/index.ja.md
deleted file mode 100644
index c1c449117..000000000
--- a/content/advanced/modules/consume-example/index.ja.md
+++ /dev/null
@@ -1,308 +0,0 @@
----
-title: "サンプルモジュールの利用"
-weight: 330
----
-
-#### サンプルモジュールの使用
-
-AWS アカウントの、特定の AWS リージョンのプライベートレジストリに、新しい CloudFormation モジュールを作成して登録しました。つまり、モジュールを CloudFormation テンプレートで他の AWS リソースと同じように使用できるようになりました。
-
-どのように利用できるのか見てみましょう。
-
-新しい YAML ファイルを作成します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch use-module.yaml
-:::
-
-テキストエディターで `use-module.yaml` を開き、以下の CloudFormation の YAML コードを貼り付けます。
-
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-AWSTemplateFormatVersion: 2010-09-09
-
-Resources:
-
- Vpc:
- Type: CFNWORKSHOP::EC2::VPC::MODULE
- Properties:
- VpcCidr: 10.1.0.0/16
-:::
-
-
-この短いコードで終了です。モジュールの便利さについてご理解いただけると思います。
-
-以下のコマンドを実行して、テンプレートから新しいスタックを作成しましょう。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation deploy --template-file use-module.yaml --stack-name cfn-workshop-modules
-:::
-
-### さらに詳しく見る
-
-スタックをデプロイしたので、実際に何が起こったのかを詳しく見てみましょう。CloudFormation でモジュールがどのように機能するのかをより理解しやすくなるでしょう。
-
-AWS コンソールを開き、CloudFormation サービスに移動します。作成したスタックを見つけて、`Resources` タブを選択します。
-スタックには 23 個のリソースがあることが示されていることに注目します。
-
-
-
-このリソースの数は、スタックの処理済みのテンプレートを見れば説明できます。CloudFormation が実際にデプロイするテンプレートは、モジュールの内容に基づいていることがわかります。
-CloudFormation テンプレートでモジュールが使用されると、モジュールリソースはモジュールテンプレートで定義されたリソースに置き換えられます。
-
-
-
-### チャレンジ
-
-作成されたリソースを簡単に識別できるように、モジュールフラグメントで定義されているリソースに `Name` タグを追加します。ユーザーは、モジュールを使用するときに `NameTag` というモジュールの新しいプロパティの値を指定できるようにします。
-
-:::expand{header="ヒントが必要ですか?"}
-* `module.yaml` ファイルを更新して、`Name` タグをサポートするすべてのリソースに追加します。VPC にタグを追加するためのドキュメントは[こちら](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html#cfn-ec2-vpc-tags)です。テンプレート内の他のリソースタイプについては、それぞれのリソースタイプがタグをサポートしているかどうか、また、その利用方法を確認してください。詳細については [AWS リソースおよびプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)をご参照ください。完了したら、フラグメントに指定する新しい `NameTag` 入力パラメーターで、タグをサポートする各リソースに追加した `Name` タグの値を参照します。
-
-* 変更を送信し、新しいモジュールバージョンをデフォルトバージョンとして設定します。詳細については、CloudFormation CLI command reference の `submit` [コマンド](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-cli-submit.html) をご参照ください。
-
-* `use-module.yaml` テンプレートを更新して、新しい `NameTag` モジュールプロパティを含めます。
-
-* `cfn-workshop-modules` スタックの更新を実行します。
-:::
-
-:::expand{header="解決策を確認しますか?"}
-
-`module.yaml` ファイルの内容を次のように更新します。
-
-
-```yaml
-AWSTemplateFormatVersion: 2010-09-09
-
-Description: A full VPC Stack
-
-Parameters:
-
- VpcCidr:
- Type: String
-
- NameTag:
- Type: String
-
-Resources:
-
- Vpc:
- Type: AWS::EC2::VPC
- Properties:
- CidrBlock: !Ref VpcCidr
- EnableDnsHostnames: true
- EnableDnsSupport: true
- InstanceTenancy: default
- Tags:
- - Key: Name
- Value: !Ref NameTag
-
- InternetGateway:
- Type: AWS::EC2::InternetGateway
- Properties:
- Tags:
- - Key: Name
- Value: !Ref NameTag
-
- VPCGatewayAttachment:
- Type: AWS::EC2::VPCGatewayAttachment
- Properties:
- VpcId: !Ref Vpc
- InternetGatewayId: !Ref InternetGateway
-
- EIP1:
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet1
-
- EIP2:
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet2
-
- NATGateway1:
- Type: AWS::EC2::NatGateway
- Properties:
- SubnetId: !Ref Public1Subnet
- AllocationId: !GetAtt EIP1.AllocationId
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet1
-
- NATGateway2:
- Type: AWS::EC2::NatGateway
- Properties:
- SubnetId: !Ref Public2Subnet
- AllocationId: !GetAtt EIP2.AllocationId
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet2
-
- Public1Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [0, !GetAZs '']
- CidrBlock: !Select [0, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: true
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet1
-
- Public2Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [1, !GetAZs '']
- CidrBlock: !Select [1, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: true
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet2
-
- Private1Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [0, !GetAZs '']
- CidrBlock: !Select [2, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: false
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PrivateSubnet1
-
- Private2Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [1, !GetAZs '']
- CidrBlock: !Select [3, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: false
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PrivateSubnet2
-
- Public1RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet1
-
- Public2RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet2
-
- Private1RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PrivateSubnet1
-
- Private2RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PrivateSubnet2
-
- Public1RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Public1RouteTable
- SubnetId: !Ref Public1Subnet
-
- Public2RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Public2RouteTable
- SubnetId: !Ref Public2Subnet
-
- Private1RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Private1RouteTable
- SubnetId: !Ref Private1Subnet
-
- Private2RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Private2RouteTable
- SubnetId: !Ref Private2Subnet
-
- Public1DefaultRoute:
- Type: AWS::EC2::Route
- DependsOn:
- - VPCGatewayAttachment
- Properties:
- RouteTableId: !Ref Public1RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-
- Public2DefaultRoute:
- Type: AWS::EC2::Route
- DependsOn:
- - VPCGatewayAttachment
- Properties:
- RouteTableId: !Ref Public2RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-
- Private1DefaultRoute:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref Private1RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref NATGateway1
-
- Private2DefaultRoute:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref Private2RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref NATGateway2
-```
-
-
-次のコマンドを実行し、この新しいバージョンをデフォルトバージョンとします。
-
-```shell
-cfn submit --set-default
-```
-
-`use-module.yaml` ファイルの内容を次のように更新します。
-
-
-```yaml
-AWSTemplateFormatVersion: 2010-09-09
-
-Resources:
-
- Vpc:
- Type: CFNWORKSHOP::EC2::VPC::MODULE
- Properties:
- VpcCidr: 10.1.0.0/16
- NameTag: VPCModule
-```
-
-
-deploy コマンドを実行し、スタックを更新します。
-
-```shell
-aws cloudformation deploy --template-file use-module.yaml --stack-name cfn-workshop-modules
-```
-:::
diff --git a/content/advanced/modules/consume-example/index.md b/content/advanced/modules/consume-example/index.md
deleted file mode 100644
index 3f936af7c..000000000
--- a/content/advanced/modules/consume-example/index.md
+++ /dev/null
@@ -1,313 +0,0 @@
----
-title: "Consume the Example Module"
-weight: 330
----
-
-#### Using the Sample Module
-
-You have just created and registered a new CloudFormation module with the private registry in your AWS account and for a given AWS Region. This means that your module can now be used in your CloudFormation templates in the same way as any public AWS resource.
-
-Let's see how you can consume it.
-
-Create a new YAML file:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch use-module.yaml
-:::
-
-
-Open `use-module.yaml` file in your text editor and paste the following CloudFormation YAML:
-
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-AWSTemplateFormatVersion: 2010-09-09
-
-Resources:
-
- Vpc:
- Type: CFNWORKSHOP::EC2::VPC::MODULE
- Properties:
- VpcCidr: 10.1.0.0/16
-:::
-
-
-That's it. Nice and short isn't it? You can see why modules are going to be so useful.
-
-Let's create a new stack from that template using the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation deploy --template-file use-module.yaml --stack-name cfn-workshop-modules
-:::
-
-### Taking a closer look
-
-Now that you deployed the stack, let's take a closer look at what actually happened. It will help to understand more on how modules work in CloudFormation.
-
-Open the AWS Console and navigate to the CloudFormation service. Locate the stack that you just created and select the `Resources` tab.
-Notice that the stack is showing it has 23 resources.
-
-
-
-This number of resources can be explained if we take a look at the processed template for this stack. You can see that the actual template that CloudFormation deploys is based upon the content of the module.
-When a module is consumed in a CloudFormation template, the module resource is replaced with the resources defined for it in the module template.
-
-
-
-
-
-
-
-### Challenge
-
-Add `Name` tags to the resources described in the module fragment, so that the resources created are easily identifiable. Users should be able to specify a value for a new, relevant module property called `NameTag` when they consume the module.
-
-:::expand{header="Need a hint?"}
-* Update the `module.yaml` file to add `Name` tags to all the resources that support them. Documentation for adding tags to a VPC can be found [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html#cfn-ec2-vpc-tags). For other resource types in the template, determine whether they support tags or not, and how: see [AWS resource and property types reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) for more information. When done, reference the value for the `Name` tag you added to each resource supporting tags in a new `NameTag` input parameter you specify in the fragment.
-
-* Submit the changes, and set the new module version as the default version. For more information, see the `submit` [command](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-cli-submit.html) in the CloudFormation Command Line Interface reference.
-
-* Update the `use-module.yaml` template to include a new `NameTag` module property.
-
-* Perform a stack update on the `cfn-workshop-modules` stack.
-:::
-
-:::expand{header="Want to see the solution?"}
-
-Update the content of the `module.yaml` file as follows:
-
-
-```yaml
-AWSTemplateFormatVersion: 2010-09-09
-
-Description: A full VPC Stack
-
-Parameters:
-
- VpcCidr:
- Type: String
-
- NameTag:
- Type: String
-
-Resources:
-
- Vpc:
- Type: AWS::EC2::VPC
- Properties:
- CidrBlock: !Ref VpcCidr
- EnableDnsHostnames: true
- EnableDnsSupport: true
- InstanceTenancy: default
- Tags:
- - Key: Name
- Value: !Ref NameTag
-
- InternetGateway:
- Type: AWS::EC2::InternetGateway
- Properties:
- Tags:
- - Key: Name
- Value: !Ref NameTag
-
- VPCGatewayAttachment:
- Type: AWS::EC2::VPCGatewayAttachment
- Properties:
- VpcId: !Ref Vpc
- InternetGatewayId: !Ref InternetGateway
-
- EIP1:
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet1
-
- EIP2:
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet2
-
- NATGateway1:
- Type: AWS::EC2::NatGateway
- Properties:
- SubnetId: !Ref Public1Subnet
- AllocationId: !GetAtt EIP1.AllocationId
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet1
-
- NATGateway2:
- Type: AWS::EC2::NatGateway
- Properties:
- SubnetId: !Ref Public2Subnet
- AllocationId: !GetAtt EIP2.AllocationId
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet2
-
- Public1Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [0, !GetAZs '']
- CidrBlock: !Select [0, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: true
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet1
-
- Public2Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [1, !GetAZs '']
- CidrBlock: !Select [1, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: true
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet2
-
- Private1Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [0, !GetAZs '']
- CidrBlock: !Select [2, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: false
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PrivateSubnet1
-
- Private2Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [1, !GetAZs '']
- CidrBlock: !Select [3, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: false
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PrivateSubnet2
-
- Public1RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet1
-
- Public2RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PublicSubnet2
-
- Private1RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PrivateSubnet1
-
- Private2RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
- Tags:
- - Key: Name
- Value: !Sub ${NameTag}/PrivateSubnet2
-
- Public1RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Public1RouteTable
- SubnetId: !Ref Public1Subnet
-
- Public2RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Public2RouteTable
- SubnetId: !Ref Public2Subnet
-
- Private1RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Private1RouteTable
- SubnetId: !Ref Private1Subnet
-
- Private2RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Private2RouteTable
- SubnetId: !Ref Private2Subnet
-
- Public1DefaultRoute:
- Type: AWS::EC2::Route
- DependsOn:
- - VPCGatewayAttachment
- Properties:
- RouteTableId: !Ref Public1RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-
- Public2DefaultRoute:
- Type: AWS::EC2::Route
- DependsOn:
- - VPCGatewayAttachment
- Properties:
- RouteTableId: !Ref Public2RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-
- Private1DefaultRoute:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref Private1RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref NATGateway1
-
- Private2DefaultRoute:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref Private2RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref NATGateway2
-```
-
-
-Execute the following command to submit this new version as the default version:
-
-```shell
-cfn submit --set-default
-```
-
-Update the content of the `use-module.yaml` file as follows:
-
-
-```yaml
-AWSTemplateFormatVersion: 2010-09-09
-
-Resources:
-
- Vpc:
- Type: CFNWORKSHOP::EC2::VPC::MODULE
- Properties:
- VpcCidr: 10.1.0.0/16
- NameTag: VPCModule
-```
-
-
-Execute another deploy command to update the stack:
-
-```shell
-aws cloudformation deploy --template-file use-module.yaml --stack-name cfn-workshop-modules
-```
-:::
diff --git a/content/advanced/modules/create-example/index.ja.md b/content/advanced/modules/create-example/index.ja.md
deleted file mode 100644
index 40ae1effe..000000000
--- a/content/advanced/modules/create-example/index.ja.md
+++ /dev/null
@@ -1,257 +0,0 @@
----
-title: "サンプルモジュールの作成"
-weight: 320
----
-
-### 概要
-
-このラボでは、AWS アカウントの、特定の AWS リージョンの AWS CloudFormation レジストリに、サンプルの CloudFormation モジュールをプライベート拡張で登録する手順を実施します。
-
-この例では、デフォルト設定の関連リソースを含む [Amazon Virtual Private Cloud](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html) (Amazon VPC) 全体をデプロイするモジュールを作成します。この例を選定した理由は、VPC のように複雑な設定を中央集権的役割のチームがベストプラクティスな方法で定義し、他のチームが簡単に利用できるようにする方法を示すためです。
-
-### 対象トピック
-
-このラボを修了すると、次のことができるようになります。
-
-* モジュールを開発する際に活用すべき重要な概念を理解します。
-* [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) を使用して新しいプロジェクトを作成し、そのモジュールをプライベート拡張として、AWS アカウントの、特定の AWS リージョンの CloudFormation レジストリに送信します。
-* CloudFormation テンプレートでモジュールを使用する方法を理解します。
-
-### ラボを開始
-
-#### サンプルモジュールに関するチュートリアル
-
-さあ、始めましょう!新しいディレクトリを作成し、そのディレクトリ内から以下のコマンドを実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mkdir module
-cd module
-cfn init
-:::
-
-いくつかの質問に対し、回答を入力します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-Initializing new project
-Do you want to develop a new resource(r) or a module(m) or a hook(h)?.
->> m
-What's the name of your module type?
-(::::::MODULE)
->> CFNWORKSHOP::EC2::VPC::MODULE
-Directory /PATH-TO-YOUR-DIRECTORY/cfn101-workshop/module/fragments Created
-Initialized a new project in /PATH-TO-YOUR-DIRECTORY/cfn101-workshop/module
-:::
-
-コマンドを実行することで、ディレクトリ内に何が作成されたのかを見てみましょう。
-
-* `fragments/`: 自動生成された `sample.json` CloudFormation テンプレートファイル。
-* `.rpdk-config`: 上記の init コマンドを実行したときに指定した詳細を格納する設定ファイル。
-* `rpdk.log`: cfn cli によって実行されたアクションのログファイル。
-
-まずは、不要なものを削除しましょう。このワークショップでは YAML 形式を使用するので、`sample.json` ファイルを削除します。このファイルは必要ありません。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-rm fragments/sample.json
-:::
-
-CloudFormation モジュールは、このワークショップで既に作成しているものと同様に、標準の CloudFormation テンプレートを使用して作成されます。ただし、モジュールで使用できるテンプレートファイルは 1 つだけで、ネストされたスタックはサポートされていません。詳細については、[モジュール構造](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/modules-structure.html) ドキュメントの _Creating the module template fragment_ と _Considerations when authoring the template fragment_ をご参照ください。
-
-次の図は、サンプルモジュールに含める VPC リソースを示しています。
-
-
-
-`fragments` フォルダー内にモジュール用の新しい YAML ファイルを作成します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch fragments/module.yaml
-:::
-
-テキストエディターで `module.yaml` を開き、以下の CloudFormation YAML コードを貼り付けます。
-
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-AWSTemplateFormatVersion: 2010-09-09
-
-Description: A full VPC Stack
-
-Parameters:
-
- VpcCidr:
- Type: String
-
-Resources:
-
- Vpc:
- Type: AWS::EC2::VPC
- Properties:
- CidrBlock: !Ref VpcCidr
- EnableDnsHostnames: true
- EnableDnsSupport: true
- InstanceTenancy: default
-
- InternetGateway:
- Type: AWS::EC2::InternetGateway
-
- VPCGatewayAttachment:
- Type: AWS::EC2::VPCGatewayAttachment
- Properties:
- VpcId: !Ref Vpc
- InternetGatewayId: !Ref InternetGateway
-
- EIP1:
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
-
- EIP2:
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
-
- NATGateway1:
- Type: AWS::EC2::NatGateway
- Properties:
- SubnetId: !Ref Public1Subnet
- AllocationId: !GetAtt EIP1.AllocationId
-
- NATGateway2:
- Type: AWS::EC2::NatGateway
- Properties:
- SubnetId: !Ref Public2Subnet
- AllocationId: !GetAtt EIP2.AllocationId
-
- Public1Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [0, !GetAZs '']
- CidrBlock: !Select [0, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: true
-
- Public2Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [1, !GetAZs '']
- CidrBlock: !Select [1, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: true
-
- Private1Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [0, !GetAZs '']
- CidrBlock: !Select [2, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: false
-
- Private2Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [1, !GetAZs '']
- CidrBlock: !Select [3, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: false
-
- Public1RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
-
- Public2RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
-
- Private1RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
-
- Private2RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
-
- Public1RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Public1RouteTable
- SubnetId: !Ref Public1Subnet
-
- Public2RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Public2RouteTable
- SubnetId: !Ref Public2Subnet
-
- Private1RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Private1RouteTable
- SubnetId: !Ref Private1Subnet
-
- Private2RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Private2RouteTable
- SubnetId: !Ref Private2Subnet
-
- Public1DefaultRoute:
- Type: AWS::EC2::Route
- DependsOn:
- - VPCGatewayAttachment
- Properties:
- RouteTableId: !Ref Public1RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-
- Public2DefaultRoute:
- Type: AWS::EC2::Route
- DependsOn:
- - VPCGatewayAttachment
- Properties:
- RouteTableId: !Ref Public2RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-
- Private1DefaultRoute:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref Private1RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref NATGateway1
-
- Private2DefaultRoute:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref Private2RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref NATGateway2
-:::
-
-
-この CloudFormation テンプレートには、CloudFormation を使用して VPC をデプロイしたことのある人ならご存知の 23 個のリソースがあります。コンポーネントが非常に多いため、デプロイするすべての VPC が標準的な方法で行われ、間違いや相違がないことを確認することが難しい場合があります。
-
-これは CloudFormation モジュールの優れたユースケースです。リソースを 1 つのモジュールにまとめることができ、多くのチームが何度でも使用できるため、複雑さが解消され、何度も必要になった場合でもエラーや相違が生じる可能性がなくなります。
-
-テンプレートには `VpcCidr` というパラメーターがあります。これはモジュールを使用する際に使用できるようになるため、ユーザーは標準デプロイを使用しながらも、ユースケースに合わせてカスタマイズすることができます。
-
-`YAML` ファイルが完成したので、モジュールとして CloudFormation レジストリに送信する準備ができました。以下のコマンドを実行し、モジュールをデフォルトリージョンに登録します。リージョンを指定したい場合は、`--region` オプションをコマンドに追加します (例: `--region us-east-2`)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn submit
-:::
-
-次のような出力が表示されます。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-Module fragment is valid.
-Successfully submitted type. Waiting for registration with token '{token}' to complete.
-Registration complete.
-{'ProgressStatus': 'COMPLETE', 'Description': 'Deployment is currently in DEPLOY_STAGE of status COMPLETED', ...
-...}
-:::
-
-これで [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) にアクセスすると、レジストリのページの `アクティブ化済みの拡張機能` セクションに新しいモジュールが表示されるはずです。
-
-
diff --git a/content/advanced/modules/create-example/index.md b/content/advanced/modules/create-example/index.md
deleted file mode 100644
index d3176f6b0..000000000
--- a/content/advanced/modules/create-example/index.md
+++ /dev/null
@@ -1,258 +0,0 @@
----
-title: "Create an Example Module"
-weight: 320
----
-
-### Overview
-
-In this lab, you will follow steps to register a sample CloudFormation module as a private extension with the AWS CloudFormation registry in your AWS account for a specified AWS region.
-
-For this example you will create a module that deploys an entire [Amazon Virtual Private Cloud](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) (Amazon VPC), including associated resources with defaults set. This example has been chosen to show how something as complex as a VPC can be defined by a central team in a best practice way and then consumed easily by other teams.
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* understand key concepts to leverage when you develop a module;
-* use the [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) to create a new project and submit the module as a private extension to the CloudFormation registry in your AWS account for a specified AWS region;
-* understand how to consume the module in CloudFormation templates.
-
-### Start Lab
-
-#### Sample Module Walkthrough
-
-Let's get started! Create a new directory and then issue the following commands from inside that directory:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mkdir module
-cd module
-cfn init
-:::
-
-You will be prompted to answer some questions. Supply the answers as shown below:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-Initializing new project
-Do you want to develop a new resource(r) or a module(m) or a hook(h)?.
->> m
-What's the name of your module type?
-(::::::MODULE)
->> CFNWORKSHOP::EC2::VPC::MODULE
-Directory /PATH-TO-YOUR-DIRECTORY/cfn101-workshop/module/fragments Created
-Initialized a new project in /PATH-TO-YOUR-DIRECTORY/cfn101-workshop/module
-:::
-
-Let's take a look at what the command created in the directory structure:
-
-* `fragments/`: contains an auto generated `sample.json` CloudFormation template file;
-* `.rpdk-config`: this is the config file that stores the details you supplied when you ran the init command above;
-* `rpdk.log`: a log file for the actions carried out by the cfn cli;
-
-
-Let's first clean up a little. You will be using the YAML format for this workshop, so go ahead and delete the `sample.json` file, you will not need it:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-rm fragments/sample.json
-:::
-
-CloudFormation modules are created using a standard CloudFormation template, just like those you have been creating already in this workshop. However, modules can use a single template file only; no nested stacks are supported. For more information, see _Creating the module template fragment_ and _Considerations when authoring the template fragment_ in the [Module structure](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/modules-structure.html) documentation.
-
-The following diagram shows the VPC resources that you will be including in your example module.
-
-
-
-Create a new YAML file for your module within the `fragments` folder:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch fragments/module.yaml
-:::
-
-Open `module.yaml` file in your text editor and paste in the following CloudFormation YAML:
-
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-AWSTemplateFormatVersion: 2010-09-09
-
-Description: A full VPC Stack
-
-Parameters:
-
- VpcCidr:
- Type: String
-
-Resources:
-
- Vpc:
- Type: AWS::EC2::VPC
- Properties:
- CidrBlock: !Ref VpcCidr
- EnableDnsHostnames: true
- EnableDnsSupport: true
- InstanceTenancy: default
-
- InternetGateway:
- Type: AWS::EC2::InternetGateway
-
- VPCGatewayAttachment:
- Type: AWS::EC2::VPCGatewayAttachment
- Properties:
- VpcId: !Ref Vpc
- InternetGatewayId: !Ref InternetGateway
-
- EIP1:
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
-
- EIP2:
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
-
- NATGateway1:
- Type: AWS::EC2::NatGateway
- Properties:
- SubnetId: !Ref Public1Subnet
- AllocationId: !GetAtt EIP1.AllocationId
-
- NATGateway2:
- Type: AWS::EC2::NatGateway
- Properties:
- SubnetId: !Ref Public2Subnet
- AllocationId: !GetAtt EIP2.AllocationId
-
- Public1Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [0, !GetAZs '']
- CidrBlock: !Select [0, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: true
-
- Public2Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [1, !GetAZs '']
- CidrBlock: !Select [1, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: true
-
- Private1Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [0, !GetAZs '']
- CidrBlock: !Select [2, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: false
-
- Private2Subnet:
- Type: AWS::EC2::Subnet
- Properties:
- VpcId: !Ref Vpc
- AvailabilityZone: !Select [1, !GetAZs '']
- CidrBlock: !Select [3, !Cidr [!GetAtt Vpc.CidrBlock, 4, 14 ]]
- MapPublicIpOnLaunch: false
-
- Public1RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
-
- Public2RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
-
- Private1RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
-
- Private2RouteTable:
- Type: AWS::EC2::RouteTable
- Properties:
- VpcId: !Ref Vpc
-
- Public1RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Public1RouteTable
- SubnetId: !Ref Public1Subnet
-
- Public2RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Public2RouteTable
- SubnetId: !Ref Public2Subnet
-
- Private1RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Private1RouteTable
- SubnetId: !Ref Private1Subnet
-
- Private2RouteTableAssociation:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref Private2RouteTable
- SubnetId: !Ref Private2Subnet
-
- Public1DefaultRoute:
- Type: AWS::EC2::Route
- DependsOn:
- - VPCGatewayAttachment
- Properties:
- RouteTableId: !Ref Public1RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-
- Public2DefaultRoute:
- Type: AWS::EC2::Route
- DependsOn:
- - VPCGatewayAttachment
- Properties:
- RouteTableId: !Ref Public2RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-
- Private1DefaultRoute:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref Private1RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref NATGateway1
-
- Private2DefaultRoute:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref Private2RouteTable
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref NATGateway2
-:::
-
-
-This CloudFormation template has 23 resources and will be very familiar to anyone that has used CloudFormation to deploy an entire VPC. With so many components it can be hard to ensure that all the VPCs you deploy are done in a standard way and no mistakes or differences are made.
-
-This is a great use case for CloudFormation modules. These resources can be placed in a single module that can be used by many teams as many times as they wish, removing the complexity and chance of error or differences when needed multiple times.
-
-You will have noticed that template has a parameter; `VpcCidr`. This will be available when consuming the module so that users can use a standard deployment but still have the ability to tailor it to their use case.
-
-Now that you have the `YAML` file complete, you are ready to submit this as a Module to the CloudFormation registry. The command below registers the module in the default region; if you wish to specify a region, append the `--region` option to the command, for example `--region us-east-2`.
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn submit
-:::
-
-You will see output as below:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-Module fragment is valid.
-Successfully submitted type. Waiting for registration with token '{token}' to complete.
-Registration complete.
-{'ProgressStatus': 'COMPLETE', 'Description': 'Deployment is currently in DEPLOY_STAGE of status COMPLETED', ...
-...}
-:::
-
-You can now visit the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation/), and you should be able to see your new module in the `Activated extensions` section of the relevant registry page.
-
-
diff --git a/content/advanced/modules/index.ja.md b/content/advanced/modules/index.ja.md
deleted file mode 100644
index 641a55f37..000000000
--- a/content/advanced/modules/index.ja.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-title: "モジュール"
-weight: 300
----
-
-### はじめに
-
-この章では、開発したモジュールを使用して [AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/) の作成、プロビジョニング、管理に関する機能を拡張する方法に焦点を当てます。
-
-これまでは、CloudFormation を使用して AWS が公開しているリソースタイプを使用してアプリケーションを構築する方法を見てきました。このラボでは、[AWS CloudFormation モジュール](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/modules.html)を活用し、同じ AWS アカウントとリージョンを利用するユーザーが何度も使用できる再利用可能なテンプレートスニペットを作成します。
-
-CloudFormation モジュールの一般的な使用例は、企業内での利用の際、企業固有であったり、独自のロジックを含んだベストプラクティスや一般的な構成コンポーネントを体系化することです。
-
-モジュールは CloudFormation の第一級オブジェクトです。CloudFormation では、あらゆる AWS リソースを管理するのと同様にモジュールを管理できます。モジュールのソフトウェア開発ライフサイクル (SDLC) プロセスは次のように要約できます。
-
-1. モジュールの開発とテストの利用に必要なツールをインストールします。
-2. モジュールの開発を開始します。
-3. 準備ができたら、モジュールを [AWS CloudFormation レジストリ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/registry.html) に送信します。
-4. CloudFormation を使用してモジュールを管理します。他の AWS リソースタイプと同様に、CloudFormation テンプレートにモジュールとそのプロパティを記述します。
-
-::alert[モジュールを CloudFormation レジストリにプライベート拡張として登録するか、パブリック拡張として登録するかを選択できます。このラボでは、プライベート拡張の例を取り上げます。]{type="info"}
-
-プライベート拡張を登録すると、AWS アカウントの AWS CloudFormation レジストリで利用できるようになります。プライベート拡張を使用すると、お客様が所有し、テストや実験に使用している AWS アカウントなどのサンドボックス環境でリソースタイプの動作をテストできます。
-
-必要に応じて、モジュールを、他の [AWS CloudFormation StackSets を使用する AWS リージョン](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/publish-extension-stacksets.html)にデプロイすることができます。
-
-プライベート拡張の詳細については、[CloudFormation でのプライベートエクステンションの使用](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/registry-private.html) をご参照ください。パブリック拡張については、[Publishing extensions to make them available for public use](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/publish-extension.html) をご参照ください。
-
-::alert[モジュールの使用には追加料金はありません。お支払いいただくのは、モジュールがスタック内で作成するリソース分のみです。]{type="info"}
-
-::alert[スタックで許可される最大リソース数やテンプレート本体の最大サイズなどの CloudFormation のクォータは、そのテンプレートに含まれるリソースがモジュールからのものであるかどうかにかかわらず、処理されたテンプレートに適用されます。]{type="info"}
-
-### モジュールの構造
-
-モジュールは次の 2 つの主要部分で構成されています。
-
-* [テンプレートフラグメント](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/modules-structure.html#modules-template-fragment)。定義したモジュールパラメータを含め、モジュールを使用してプロビジョニングするリソースと関連情報を定義します。
-* テンプレートフラグメントに基づいて生成される[モジュールスキーマ](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/modules-structure.html#modules-schema)。モジュールスキーマは、テンプレートフラグメントで定義したコントラクトを宣言し、CloudFormation レジストリ内のユーザーに表示します。
diff --git a/content/advanced/modules/index.md b/content/advanced/modules/index.md
deleted file mode 100644
index c3c07d924..000000000
--- a/content/advanced/modules/index.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-title: "Modules"
-weight: 300
----
-
-### Introduction
-
-This part of the workshop focuses on how you can extend the creation, provisioning, and management capabilities of [AWS CloudFormation](https://aws.amazon.com/cloudformation/) with modules you develop.
-
-In this workshop so far you have seen how to use CloudFormation to build applications using the resource types published by AWS. In this lab you will leverage [AWS CloudFormation Modules](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/modules.html) to create reusable template snippets that can be used many times by other users in the same AWS Account and Region.
-
-A common use case for CloudFormation Modules is for codifying best practice or common configuration components that would be used within an enterprise, but might be company-specific, or contain proprietary logic.
-
-A module is a first-class object in CloudFormation: you can manage your module as you would manage any AWS resource with CloudFormation. The Software Development Life Cycle (SDLC) process of a module can be summarized as follows:
-
-1. Install prerequisite tools you will use for development and testing of your module;
-2. Start to develop your module;
-3. When ready, submit the module to the [AWS CloudFormation registry](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry.html);
-4. Manage your module with CloudFormation: you describe the module and its properties in your CloudFormation template(s), like you would do with any AWS resource type.
-
-::alert[You have the choice to register your module as a private or as a public extension in the CloudFormation registry: this lab covers private extension examples.]{type="info"}
-
-When you submit a private extension, you make it available in the AWS CloudFormation registry in your AWS account. Private extensions give you the ability to test the behavior of your resource type in a sandbox environment, such as in an AWS account you own and that you use for testing/experimentation.
-
-You can choose to deploy your module in other [AWS regions using AWS CloudFormation StackSets](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/publish-extension-stacksets.html) as needed.
-
-For more information on private extensions, see [Using private extensions in CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-register.html). For more information on public extensions, see [Publishing extensions to make them available for public use](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/publish-extension.html).
-
-::alert[There is no additional charge for using modules. You pay only for the resources those modules resolve to in your stacks.]{type="info"}
-
-::alert[CloudFormation quotas, such as the maximum number of resources allowed in a stack, or the maximum size of the template body, apply to the processed template whether the resources included in that template come from modules or not.]{type="info"}
-
-### Module structure
-
-A module consists of two main pieces:
-
-* A [template fragment](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/modules-structure.html#modules-template-fragment), which defines the resources and associated information you want to provision through use of the module, including any module parameters you define.
-* A [module schema](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/modules-structure.html#modules-schema) that you generate based on the template fragment. The module schema declares the contract you defined in the template fragment, and is viewable to users in the CloudFormation registry.
diff --git a/content/advanced/modules/prerequisites/index.ja.md b/content/advanced/modules/prerequisites/index.ja.md
deleted file mode 100644
index f5f20bd49..000000000
--- a/content/advanced/modules/prerequisites/index.ja.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: "前提条件"
-weight: 310
----
-
-### モジュール開発ツール
-
-次のセクションに進む前に、以下のツールをマシンにインストールしてください。
-
-* [CloudFormation コマンドラインインターフェイス (CLI)](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) をインストールします。
-
- `pip` を使用して CloudFormation CLI をインストールします。
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- pip install cloudformation-cli
- :::
-
-::alert[CloudFormation CLI のバージョン 1.0 が既にインストールされている場合は、バージョン 2.0 にアップグレードすることをお勧めします。アップグレードには、`pip install` コマンドの `--upgrade` オプションを使用できます。詳細については、こちらの[ページ](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html#resource-type-setup) の下部に記載の *Upgrading to CFN-CLI 2.0* をご参照ください。]{type="info"}
diff --git a/content/advanced/modules/prerequisites/index.md b/content/advanced/modules/prerequisites/index.md
deleted file mode 100644
index 386be5107..000000000
--- a/content/advanced/modules/prerequisites/index.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: "Prerequisites"
-weight: 310
----
-
-### Module Development Tools
-
-Before proceeding to the next section, install the following prerequisites on your machine:
-
-* install the [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html).
-
- Use `pip` to install the CloudFormation CLI:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- pip install cloudformation-cli
- :::
-
-::alert[If you already have version 1.0 of the CloudFormation CLI installed, it is recommended to upgrade it to version 2.0. For the upgrade, you can use the `--upgrade` option for the `pip install` command shown previously. For more information, see *Upgrading to CFN-CLI 2.0* further down on this [page](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html#resource-type-setup).]{type="info"}
diff --git a/content/advanced/resource-types/example-in-python/index.ja.md b/content/advanced/resource-types/example-in-python/index.ja.md
deleted file mode 100644
index 05fa2f0dd..000000000
--- a/content/advanced/resource-types/example-in-python/index.ja.md
+++ /dev/null
@@ -1,451 +0,0 @@
----
-title: Python での実装例
-weight: 320
----
-
-### 概要
-
-このラボでは、Python で記述されたサンプルプライベート拡張を AWS アカウントの AWS CloudFormation レジストリに登録する手順を実施します。また、リソースタイプのソースコード実装ロジックの例を確認して、リソースタイプ開発ワークフローの主要な概念を理解します。
-
-### 対象トピック
-
-このラボを修了すると、次のことができるようになります。
-
-* リソースタイプを開発する際に活用すべき重要な概念を理解します。
-* [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) を使用して新しいプロジェクトを作成し、コントラクトテストを実行し、リソースタイプをプライベート拡張として AWS アカウントの CloudFormation レジストリに登録します。
-* [AWS SAM CLI](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/install-sam-cli.html) を使用してリソースタイプハンドラーを手動でテストする方法を理解します。
-
-### ラボの開始
-
-このラボでは、[リポジトリ](https://github.com/aws-cloudformation/aws-cloudformation-samples) にあるサンプルリソースタイプを使用します。
-
-::alert[新しいプロジェクトを作成する方法については、[Walkthrough: Develop a resource type](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-walkthrough.html) をご参照ください。]{type="info"}
-
-#### リソースタイプウォークスルーのサンプル
-
-例として、[AWSSamples::EC2::ImportKeyPair](https://github.com/aws-cloudformation/aws-cloudformation-samples/tree/main/resource-types/awssamples-ec2-importkeypair/python) サンプルリソースタイプを使用します。これは、CloudFormation でインポートされた [Amazon EC2 key pair](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-key-pairs.html) をインポートし、管理する例を示しています。
-
-さあ、始めましょう! 新しいディレクトリを作成し、この [リポジトリ](https://github.com/aws-cloudformation/aws-cloudformation-samples) をディレクトリにクローンします。また、[ZIP アーカイブをダウンロード](https://github.com/aws-cloudformation/aws-cloudformation-samples/archive/refs/heads/main.zip) しても実施できます。リポジトリをクローンするには、以下のコマンドを使用します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-git clone https://github.com/aws-cloudformation/aws-cloudformation-samples.git
-:::
-
-リポジトリには多数のサンプルが含まれています。ディレクトリをサンプルリソースタイプのディレクトリに変更します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-cd aws-cloudformation-samples/
-cd resource-types/awssamples-ec2-importkeypair/python/
-:::
-
-ディレクトリ内のいくつかの要素を見てみましょう。
-
-* `docs/`: リソースタイプのプロパティ用に自動生成された構文情報が含まれます。リソーススキーマファイルを変更するたびに、このディレクトリ内のファイルを含む自動生成コードを `cfn generate` CloudFormation CLI [コマンド](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-cli-generate.html) で更新する必要があります。
-* `inputs/`: リソースタイプ入力プロパティのキー/値データを含むファイルが含まれています。リソースタイプ作成者は、コントラクトテストで使用する入力情報を指定します。 *これらのファイルに機密情報を追加しないでください。* 詳細については、[Specifying input data for use in contract tests](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test.html#resource-type-test-input-data) をご参照ください。
-* `awssamples-ec2-importkeypair.json`: 選択したリソースタイプ名にちなんで名付けられた、**リソースのモデルの定義**に使用されるリソーススキーマファイルです。
-* `src/`: リソースタイプ名にちなんで名付けられたディレクトリが含まれています。中には次のものがあります。
- - `models.py`: スキーマを変更すると、お客様に代わって CloudFormation CLI が管理します。
- - `handlers.py`: リソースタイプ開発者が CRUDL 実装ロジックのコードを追加する場所です。任意のテキストエディタで `src/handlers.py` ファイルを開き、`create_handler`、`update_handler`、`delete_handler`、`read_handler`、`list_handler` 関数で示されているように**ハンドラーの構造を認識してください**。
-* `resource-role.yaml`: CloudFormation CLI によって管理されるファイルです。このロールには [AWS Identity and Access Management](https://aws.amazon.com/jp/iam/) (IAM) ロールが記述されており、そのロールの `PolicyDocument` には、リソースタイプ開発者がスキーマファイルの `handlers` セクションで示す権限が含まれています。CloudFormation は CRUDL オペレーションの一環として、ユーザーに代わってこのリソースタイプのリソースを管理する役割を引き受けます。
-* `template.yml`: [AWS Serverless Application Model](https://aws.amazon.com/jp/serverless/sam/) (SAM) テンプレートはリソースタイプテストの一部として使用されます。
-
-#### リソースモデリング
-
-リソースタイプを作成する際の**最初のステップ**は、**リソースのプロパティを記述するスキーマ**を定義することと、**CloudFormationがユーザーに代わってリソースを管理**するために**必要な権限**を定義することです。
-
-まず、このウォークスルーで使用しているサンプルリソースタイプでどのプロパティが必要かを判断することから始めましょう。作成するリソースタイプに関連する API リファレンスページにアクセスします。`AWSSamples::EC2::ImportKeyPair` リソースタイプの例については [Amazon EC2 API リファレンス](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/Welcome.html) を参照します。[AWS ドキュメンテーション](https://docs.aws.amazon.com/ja_jp/index.html) ページに移動し、**コンピューティングカテゴリ**から **Amazon EC2** を選択し、次のページで **API リファレンス**を選択します。
-
-次に、[Action](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/API_Operations.html) から、キーペアに対してプログラムでアクションを実行できる操作を探します。`CreateKeyPair`、`DeleteKeyPair`、`DescribeKeyPairs`、`ImportKeyPair`を書き留めておきます。
-`CreateKeyPair` はキーペアの作成に関係しますが、インポートには関係ないので、必要ありません。代わりに、他の 3 つのアクションが必要です。
-
-[ImportKeyPair](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/API_ImportKeyPair.html) のドキュメントに移動します。*request parameters* と *response elements* を調べて、**スキーマに記述したいプロパティを決定**する必要があります。この場合、*request parameters* には以下を指定する必要があります。
-
-* インポートするキーペアの `KeyName` (ドキュメントに *Required: Yes* と記載)
-* `PublicKeyMaterial` コンテンツ (*Required: Yes*)
-* オプションのタグ設定 (`TagSpecification.N` - *Required: No)*
-
-
-次に、*レスポンス要素*を見てみましょう。リソースを作成すると、`keyFingerprint` を含む他の要素とともに `keyPairId` が返されます。[DeleteKeyPair](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/API_DeleteKeyPair.html) アクションは、`KeyName` を含むパラメータを受け取ります。一旦、以下にまとめてみましょう。
-
-* `KeyName` と `PublicKeyMaterial` は必須の入力パラメータです。タグ (`TagSpecification.N`) はオプションです。
-* `keyPairId` と `keyFingerprint` はリソースの作成後に使用可能になるため、ユーザーが指定することはできません。
-* リソースのプライマリ識別子プロパティには `keyPairId` が適しています。
-
-上記のプロパティは、CloudFormation がユーザーに代わってリソースを管理するために使用する *create*、*update*、*delete* ハンドラーでの使用に適しています。
-
-他の 2 つのハンドラーには追加のプロパティが必要です。*read* (リソースの現在の状態情報が必要な場合に CloudFormation がスタック更新時に呼び出す) と *list* (特定のタイプの複数のリソースについて概要情報が必要な場合に呼び出される) です。この例では、`keySet` や `keyType` などの関連するプロパティを探すために、[`DescribeKeyPairs`](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/API_DescribeKeyPairs.html) が適しています。
-
-では、上記の結果を `AWSSamples::EC2::ImportKeyPair` リソースタイプのスキーマの例と比較してみましょう。お好きなテキストエディターで `awssamples-ec2-importkeypair.json` ファイルを開くと、以下のことがわかります。
-
-* モデルのプロパティと値の制約については、`properties` セクションで定義しています。
-* `KeyName`, `PublicKeyMaterial` は `required` となっています。
-* `KeyPairId`、`KeyFingerprint`、`KeyType` (リソース作成後に決定されるプロパティ) は `readOnlyProperties` として指定されます。
-* `KeyPairId` は `primaryIdentifier` として設定されています。
-* `PublicKeyMaterial` は `writeOnlyProperties` で指定されます。機密データ (パスワードなど) を含む値を記述するときには `writeOnlyProperties` がよく使われます。これらの値は *list* や *read* のリクエストでは返されません。`AWSSamples::EC2::ImportKeyPair` の例では、*list* や *read* ハンドラーで使用されている `DescribeKeyPairs` によって公開鍵情報は返されず、nullになるので、*list* または *read* ハンドラーに含めても意味がありません。そのため、この例では、プロパティを `writeOnlyProperties` と記述することが適切です。
-* `KeyName`、`PublicKeyMaterial` は `createOnlyProperties` として設定されています。そのため、インポートされたキーペアの 2 つの値のいずれかを更新すると、新しい値を持つ新しいリソースが作成され、以前のリソースが削除されます。
-* 必須ではない `Tags` は、スキーマ内の定義間で再利用できるようにするためのベストプラクティスの一環として [`definitions`](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-schema.html#schema-properties-definitions) セクションで定義されています。サンプルスキーマでは、`Tags` は `properties` セクションの `$ref` ポインターで参照します。
-
-スキーマの作成方法とスキーマ要素の詳細については、[Resource type schema](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-schema.html) をご参照ください。
-
-`awssamples-ec2-importkeypair.json` サンプルスキーマファイルには、ハンドラーがユーザーに代わってリソースタイプを管理するために必要な [AWS Identity and Access Management](https://aws.amazon.com/jp/iam/) (IAM) 権限も多数含まれています。サンプルスキーマファイルの `handlers` セクションを見ると、わかりやすい EC2 関連の権限がいくつか見つかります。例えば、*create* ハンドラーと *read* ハンドラーの場合、次のようになっているはずです。
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
- "handlers": {
- "create": {
- "permissions": [
- "ec2:ImportKeyPair",
- "ec2:CreateTags"
- ]
- },
- "read": {
- "permissions": [
- "ec2:DescribeKeyPairs"
- ]
- },
- }
-:::
-
-リソースタイプを作成するときに選択できる権限の詳細については、[AWS サービスのアクション、リソース、および条件キー](https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html)をご参照ください。このページで、必要な AWS サービスを選択します。今回の例だと、[Amazon EC2](https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_amazonec2.html))を選択し、次に [Amazon EC2 で定義されるアクション](https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_amazonec2.html#amazonec2-actions-as-permissions) を選択します。
-
-::alert[開発するリソースのスキーマファイルを変更するときは、リソースタイププロジェクトのルートディレクトリ内から `cfn generate` CloudFormation CLI コマンドを実行して、スキーマの変更を `docs/*`、`resource-role.yaml`、`src/[RESOURCE_TYPE_NAME]/models.py` などのプロジェクトファイルに反映します。]{type="info"}
-
-#### ハンドラー
-
-先ほどの例で示したようにリソーススキーマをモデル化したら、次のステップはハンドラーでコード実装を開始することです。考慮すべき点は以下のとおりです。
-
-* 特定の CRUDL ハンドラー (*Create*、*Read*、*Update*、*Delete*、*List*) には、次のようなビジネスロジックを実装する必要があります。
- * 特定のサービス固有の API (*create* ハンドラーは `ImportKeyPair`、*delete* ハンドラーは `DeleteKeyPair`、など) を呼び出します。
-* 特定のハンドラーで呼び出した特定の API から返されたデータを利用します。さらに、
- * すべてのハンドラーは常に `ProgressEvent` を返さなければなりません。その構造の詳細については、[ProgressEvent object schema](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test-progressevent.html) をご参照ください。
- * エラーがなければ、指定したハンドラーから `status=OperationStatus.SUCCESS` を含む `ProgressEvent` オブジェクトを返します。例: `return ProgressEvent(status=OperationStatus.SUCCESS)`。さらに、ハンドラーが *delete* または *list* でない場合は、リソースのハンドラーコード (API 呼び出しから) で収集したデータを含む、おなじみのオブジェクト (リソースのモデル) を返します。`ResourceModel` *list* ハンドラーでは、単一のモデルではなく、記述しているタイプのリソースごとにモデルのリストを返します。
- * 呼び出す API がエラーを返す場合、または別の例外が発生した場合は、`status=OperationStatus.FAILED` を使用して `ProgressEvent` オブジェクトを返します。その際に考慮すべき点は次のとおりです。
- * スタックトレースや、例外 (`botocore.exceptions.ClientError` やその他の例外等) から得られる特定のエラーメッセージテキストをキャプチャします。これにより、ハンドラーのコードに記述したログステートメントにスタックトレースを表示し、`ProgressEvent` オブジェクトでエラーメッセージの説明を返すことができます。これにより、この情報を CloudFormation イベントの一部として(例えば、CloudFormation コンソールのイベントペインで)利用できるようにして、エラーの原因をユーザーに説明できます。
- * API から発生するエラー (インポートキーペアの例では、[Amazon EC2 API のエラーコード](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/errors-overview.html)からのエラー) に応じて、[ハンドラーエラーコード](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test-contract-errors.html)のエラーにマッピングする必要があります。例えば、EC2 API が `InvalidKeyPair.NotFound` クライアントエラーを返す場合、`ProgressEvent` と共に、`HandlerErrorCode.NotFound` ハンドラーエラーを返す必要があります。
- * リソースタイプが安定するまでに時間がかかる場合 (例えば、リソースが完全に利用可能な状態に達するなど) は、*create*、*update*、*delete* の各ハンドラーで安定化メカニズムを使用します。ハンドラが最初に呼び出されたとき、`OperationStatus.IN_PROGRESS` と共に `ProgressEvent` を返し、その後、そのハンドラが希望の状態になるまで呼び出される場合は、*read* ハンドラを呼び出して進行状況を確認することで次のステップに進みます (例えば、特定のプロパティ値をチェックして作成が完了したか進行中かを判断します)。
-
-上記のトピックの例は、`src/awssamples_ec2_importkeypair/handlers.py` サンプルリソースタイプで確認できます。各ハンドラーは特定の EC2 API を呼び出します。前述のように、スキーマには関連する権限セットが設定されています。
-
-サンプルリソースタイプは上記の例外処理メカニズムを利用しますが、ダウンストリーム API エラーメッセージはキャプチャされ、特定の EC2 API にマップされたハンドラーエラーコードとともに返されます。以下は、サンプルリソースタイプの `read_handler` 関数からの抜粋です (サンプルリソースタイプコードの `_progress_event_failed` 関数を見ると、スタックトレース情報を記録し、`ProgressEvent` の失敗を返すことによって入力情報を利用しています)。
-
-:::code{language=python showLineNumbers=false showCopyAction=false}
- except botocore.exceptions.ClientError as ce:
- return _progress_event_failed(
- handler_error_code=_get_handler_error_code(
- ce.response['Error']['Code'],
- ),
- error_message=str(ce),
- traceback_content=traceback.format_exc(),
- )
-:::
-
-キーペアインポートのユースケースで安定化プロセスが必ずしも必要ではない場合でも、サンプルリソースタイプは、*create*、*update*、*delete* ハンドラーで使用され、`_is_callback` サンプル関数によって駆動するコールバックメカニズムの例を示しています。
-
-#### ユニットテストの実行
-
-ソフトウェア開発のベストプラクティスの一環として、*unit tests* を作成して、コードが期待どおりに動作するという確信を高めます。[ノート](https://github.com/aws-cloudformation/aws-cloudformation-samples/tree/main/resource-types/awssamples-ec2-importkeypair/python#unit-tests) で説明されているように、`AWSSamples::EC2::ImportKeyPair` サンプルリソースタイプには `src/awssamples_ec2_importkeypair/tests` ディレクトリに単体テストが含まれています。そのディレクトリにある `test_handlers.py` ファイル (先ほど選択したリポジトリのクローン/ダウンロードによりマシン上に存在) を見ると、最初に説明したテストユーティリティ関数と、ファイルの途中あたりに定義されているテストユーティリティ関数が表示されます。このファイルの途中には、ユーティリティ関数を使用して、戻り値の検証や投げられた例外の検証等のテストを実行するユニットテストがあります。EC2 API 呼び出しなどの関数呼び出しを含むオブジェクトは、[unittest.mock](https://docs.python.org/3/library/unittest.mock.html) モックオブジェクトライブラリを利用して、モックオブジェクト呼び出しによるテストで置き換え/パッチされます。
-
-ユニットテストを実行しましょう!`AWSSamples::EC2::ImportKeyPair` サンプルリソースタイプのルートレベルにあるディレクトリ (つまり `python` ディレクトリ内) にいることと、前トピックの前提条件に従っていることを確認してください。次に、以下のように単体テストを実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pytest --cov src --cov-report term-missing
-:::
-
-ユニットテストの結果と、合計カバレッジ率の値を示す出力が得られるはずです。サンプルリソースタイプのユニットテストでは、プロジェクトのルートにある `.coveragerc` ファイルを使用します。このファイルには、必要なテストカバレッジ値を含む [設定](https://coverage.readthedocs.io/en/latest/config.html) の選択肢が含まれています。
-
-#### コントラクトテストの実行
-
-このラボの以降のステップでは、`AWSSamples::EC2::ImportKeyPair` サンプルリソースタイプをプライベート拡張としてローカルでテストし、アカウントの CloudFormation レジストリに登録します。
-
-リソースタイプを構築するときや、開発プロセスの非常に早い段階でハンドラーのビジネスロジックを実装する際に順守すべき要件を説明する [Resource type handler contract](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test-contract.html) を必ず活用する必要があります。ハンドラーコントラクトの強制は、パブリックリソースタイプをレジストリに登録したときに行われますが、その場合はコントラクトテストに合格する必要があります。これは、リソースタイプを利用する外部の顧客に代わって高い品質基準を維持するために重要です。
-
-::alert[パブリックリソースタイプを公開するにはコントラクトテストに合格する必要があり、プライベートリソースタイプを送信した場合は実行されません。ただし、ベスト・プラクティスの一環として、開発プロセスの非常に早い段階でコントラクト・テストの仕様を順守するようにしてください。]{type="info"}
-
-サンプルリソースタイプのコントラクトテストを実行してみましょう!まず、[ノート](https://github.com/aws-cloudformation/aws-cloudformation-samples/tree/main/resource-types/awssamples-ec2-importkeypair/python#contract-tests) で説明されているように、サンプルリソースタイプ用のテストサポートインフラストラクチャをセットアップしましょう。サンプルリソースタイプのコントラクトテストでは、アカウント内のテスト専用キーペアリソースを作成、更新、削除します。名前やタグなどのキーペア情報はプロジェクトの `inputs` ディレクトリのファイルで提供され、公開鍵情報は作成した CloudFormation スタックのエクスポートされた値から使用されます。テストデータをコントラクトテストに渡す方法に関する詳細は、[Specifying input data for use in contract tests](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test.html#resource-type-test-input-data) をご参照ください。
-
-::alert[コントラクトテストでは実際の API 呼び出しを行います。関連する環境認証情報または Boto3 認証情報チェーンからの関連する認証情報を使用するよう、テスト用 AWS アカウントを指す設定がされていることを確認します。]{type="info"}
-
-まず、テストに使用する SSH キーペアを生成しましょう。マシンで新しいターミナルコンソールを開き、`AWSSamples::EC2::ImportKeyPair` プロジェクトディレクトリパスの外にある既存、または新しいディレクトリを選択します。準備ができたら、選択または作成したディレクトリに変更し、`ssh-keygen` コマンドで SSH キーペアを作成します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-ssh-keygen -t rsa -C "Example key pair for testing" -f example-key-pair-for-testing
-:::
-
-プロンプトに従い、キーペアの作成を完了します。これで、選択したディレクトリに `example-key-pair-for-testing` と `example-key-pair-for-testing.pub` の 2 つのファイルがあるはずです。前者は秘密鍵で、後者は公開鍵の部分です。次の手順では、必要に応じて公開鍵ファイルを開き、その内容をクリップボードにコピーしてコマンドラインに貼り付けて、内容を指定する必要があります。
-
-次に、入力する公開鍵データを含む [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html) リソースを作成する CloudFormation スタックを作成します。コントラクトテストでは、このスタックの `KeyPairPublicKeyForContractTests` [エクスポートされたスタック出力値](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) が使用されます。次に、サンプルリソースタイプの `inputs` ディレクトリにある入力ファイルには、スタックからエクスポートされた値への `{{KeyPairPublicKeyForContractTests}}` 参照が含まれています。
-
-準備ができたら、サンプルリソースタイプをクローン、またはダウンロードしたターミナルに戻り、`aws-cloudformation-samples/resource-types/awssamples-ec2-importkeypair/python/` ディレクトリにいることを確認します。次のコマンドでは、`examples/example-template-contract-tests-input.yaml` サンプルテンプレートファイルを使用して新しいスタックを作成します。テンプレートでは `KeyPairPublicKey` 入力パラメーターを指定する必要があり、前述のようにコンテンツを指定する必要があります。テンプレートには `OrganizationName` と `OrganizationBusinessUnitName` も必要です。これらはそれぞれ `ExampleOrganization` と `ExampleBusinessUnit` というサンプルデフォルト値で設定されており、値を指定しない場合に使用されます。次に示すように、公開鍵ファイルのコンテンツ用のプレースホルダーを使用してスタックを作成します。このスタックには、公開鍵ファイルの内容をコピーして貼り付ける必要があります (この例では、AWS リージョンに `us-east-1` を使用していますが、必要に応じてこの値を変更してください)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --region us-east-1 \
- --stack-name example-for-key-pair-contract-tests \
- --template-body file://examples/example-template-contract-tests-input.yaml \
- --parameters ParameterKey=KeyPairPublicKey,ParameterValue='PASTE_CONTENT_OF_example-key-pair-for-testing.pub'
-:::
-
-CloudFormation コンソールまたは AWS CLI の [stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) 待機コマンドを使用して、`example-for-key-pair-contract-tests` スタックが作成されるまで待ってください (この例では、AWS リージョンに `us-east-1` を使用しています)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --region us-east-1 \
- --stack-name example-for-key-pair-contract-tests
-:::
-
-次に、マシン上で 2 つのターミナルコンソールを開きます。それぞれで、`AWSSamples::EC2::ImportKeyPair` サンプルリソースタイププロジェクトのルートレベルにいることを確認してください。
-
-* 最初のターミナルコンソールで、Docker がマシン上で実行されていることを確認し、`sam local start-lambda` を実行します
-* 2 つ目のターミナルコンソールで、コントラクトテストを実行します: `cfn generate && cfn submit --dry-run && cfn test`
-
-各ハンドラーのコントラクトテスト (`contract_create_create`、`contract_create_read` など) の詳細については、[Contract tests](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/contract-tests.html) をご参照ください。
-
-このプロセスが終了すると、コントラクトテストの結果を示す出力が表示されます。次のステップに進みましょう!
-
-#### リソースタイプをプライベート拡張として登録する
-
-CloudFormation CLI を使用して CloudFormation アカウントのレジストリにリソースを登録してみましょう (この例では、AWS リージョンに `us-east-1` を使用しています)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn generate && cfn submit --set-default --region us-east-1
-:::
-
-登録が完了するまでお待ちください。その後、`AWSSamples::EC2::ImportKeyPair` サンプルリソースタイプがプライベート拡張としてアカウントに登録されているはずです。確認するには、CloudFormation コンソールで *Activated extensions* を選択し、次に *Privately registered* を選択します。
-
-次に、サンプルリソースタイプをテストしてみましょう。サンプルテンプレートは、クローンまたはダウンロードしたリポジトリに `examples/example-template-import-keypair.yaml` として提供されています。任意のテキストエディターでファイルを開くと、サンプルリソースタイプが `Resources` セクションでどのように参照されているかがわかります。`KeyPairPublicKey` には、コントラクトテストに使用したのと同じ公開鍵の内容を指定します。テンプレートでは、ユーザーが独自の値を指定しない限り、`KeyPairName`、`OrganizationName`、`OrganizationBusinessUnitName` のデフォルト値が使用されます。スタックの作成を選択します (この例では、AWS リージョンに `us-east-1` を使用しています)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --region us-east-1 \
- --stack-name example-key-pair-stack \
- --template-body file://examples/example-template-import-keypair.yaml \
- --parameters ParameterKey=KeyPairPublicKey,ParameterValue='PASTE_CONTENT_OF_example-key-pair-for-testing.pub'
-:::
-
-スタックの作成が完了するまで待ってください。その後、CloudFormation を使用してサンプルキーペアとサンプル `AWSSamples::EC2::ImportKeyPair` リソースタイプ (この例では AWS リージョンに `us-east-1` を使用しています) を正常にインポートできたはずです。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --region us-east-1 \
- --stack-name example-key-pair-stack
-:::
-
-### チャレンジ
-
-##### コンテキスト
-
-コントラクトテストの一環として、[`sam local invoke`](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test.html#manual-testing) コマンドを使用してハンドラーの呼び出しを発行する、[リソースタイプを手動でテストする](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test.html#manual-testing)オプションもあります。テストを手動で実行するには:
-
-* このラボで先ほど行ったように、1 つのターミナルで (サンプルリソースタイプの `python` ディレクトリ内から) `sam local start-lambda` を実行します。
-* 別のターミナルで、例えば、`sam local invoke TestEntrypoint --event sam-tests/YOUR_INPUT_FILE` を使用してハンドラーを呼び出します。ここで `YOUR_INPUT_FILE` は JSON 形式のファイルで、その構造は[こちら](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test.html#manual-testing)に記載されています。プロジェクトのルートレベルの `sam-tests` ディレクトリに保存します。
-
-::alert[`sam-tests` ディレクトリで作成および編集するファイルには、認証情報が含まれている場合があります。`sam-tests/` の場所は、ソースコードリポジトリに追加されないように、`.gitignore` ファイル (このラボで使用したサンプルリソースタイプのプロジェクトのルートレベルにあるファイル) に追加する必要があります。セットアップによっては、`sam-tests` ディレクトリのファイルに認証情報を追加する必要がある場合と不要な場合があります。]{type="info"}
-
-##### チャレンジ
-
-`sam-tests/example-read.json` ファイルを作成して `AWSSamples::EC2::ImportKeyPair` サンプルリソースタイプの *read* ハンドラーをテストします。入力例として、先ほど `example-key-pair-stack` スタックで作成したキーペアを選択します。期待される出力は、サンプル リソース タイプの *read* ハンドラーが最初にフェッチし、返すモデルのプロパティを含むデータ構造です。
-
-:::expand{header="ヒントが必要ですか?"}
-* Python の [UUID](https://docs.python.org/3/library/uuid.html) モジュールを使用して `UUID4` 値を生成して `clientRequestToken` に渡します。
-* Resource type handler contract に関する [ページ](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test-contract.html) の [Read handlers](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test-contract.html#resource-type-test-contract-read) セクションから、*Input assumptions* の内容を読んで、JSON 構造の `desiredResourceState` キーの下に、入力として渡すキーと値を決定します。
-* リソースの論理識別子には、`MyExampleResource` などのサンプル値を使用します。
-:::
-
-:::expand{header="解決策を確認しますか?"}
-* [ここに](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-test.html#manual-testing)記載されている構造を使用し、`sam-tests/example-read.json` ファイルを作成します。
-* Python コマンドラインインターフェイスから、次の例のように `UUID4` 値を生成します。
-
-```shell
->>> import uuid
->>> uuid.uuid4()
-UUID('OUTPUT EDITED: THIS WILL CONTAIN A UUID4 VALUE')
-```
-
-* 作成した `example-key-pair-stack` CloudFormation スタックの `Outputs` セクションから、`KeyPairId` の値を使用し、それを JSON ファイルの構造内の `desiredResourceState` キーの下に作成した新しい `KeyPairId` キーに渡します。
-* 結果のファイル構造は、次の例のようになるはずです。
-
-```json
-{
- "credentials": {
- "accessKeyId": "",
- "secretAccessKey": "",
- "sessionToken": ""
- },
- "action": "READ",
- "request": {
- "clientRequestToken": "REPLACE_WITH_YOUR_UUID4_VALUE_HERE",
- "desiredResourceState": {
- "KeyPairId": "REPLACE_WITH_THE_KEYPAIR_ID"
- },
- "logicalResourceIdentifier": "MyExampleResource"
- },
- "callbackContext": {}
-}
-```
-
-* `sam local invoke TestEntrypoint --event sam-tests/example-read.json` サンプルテストファイルを実行します。出力として、*read* ハンドラーから返されたリソースプロパティ値を含む `resourceModel` セクションが表示されます。
-:::
-
-### クリーンアップ
-
-作成したリソースをクリーンアップする手順は、次の通りです (選択した AWS リージョンを `us-east-1` とします)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --region us-east-1 \
- --stack-name example-key-pair-stack
-
-aws cloudformation wait stack-delete-complete \
- --region us-east-1 \
- --stack-name example-key-pair-stack
-
-aws cloudformation delete-stack \
- --region us-east-1 \
- --stack-name example-for-key-pair-contract-tests
-
-aws cloudformation wait stack-delete-complete \
- --region us-east-1 \
- --stack-name example-for-key-pair-contract-tests
-
-aws cloudformation deregister-type \
- --region us-east-1 \
- --type-name AWSSamples::EC2::ImportKeyPair \
- --type RESOURCE
-:::
-
-リソースタイプ、モジュール、フックなどの CloudFormation エクステンションを登録するために `cfn submit` コマンドを使用すると、CFN-CLI はご利用の AWS アカウントに 2 つの CloudFormation スタックを作成します。1 つはエクステンション (リソースタイプエクステンションやフックエクステンションのためなど) の実行ロールを作成するのもです。もう 1 つはエクステンションのインフラストラクチャーコンポーネントを持つものです。また、CFN-CLI は両方のスタックに削除保護を設定します。この 2 つのスタックとは、このラボ専用の `awssamples-ec2-importkeypair-role-stack` スタックと、このラボや、同じアカウントで CFN-CLI を使用し開発や登録をしているその他のエクステンションで共通使用されている `CloudFormationManagedUploadInfrastructure` スタックです。
-
-次に示す手順に沿って、`awssamples-ec2-importkeypair-role-stack` スタックを削除します。まず、削除保護を解除します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-termination-protection \
- --region us-east-1 \
- --no-enable-termination-protection \
- --stack-name awssamples-ec2-importkeypair-role-stack
-:::
-
-次に `awssamples-ec2-importkeypair-role-stack` スタックを削除します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --region us-east-1 \
- --stack-name awssamples-ec2-importkeypair-role-stack
-
-aws cloudformation wait stack-delete-complete \
- --region us-east-1 \
- --stack-name awssamples-ec2-importkeypair-role-stack
-:::
-
-もう 1 つの `CloudFormationManagedUploadInfrastructure` スタックは、[AWS Key Management Service (AWS KMS)](https://aws.amazon.com/jp/kms/) のキーと 2 つの Amazon S3 バケットなどを作成します。バケットには、このラボを進める際に CFN-CLI がユーザーに代わって作成してアップロードしたリソースタイプの ZIP アーカイブなど、CloudFormation 拡張機能のレジストリに送信ために必要なデータを保持しています。この ZIP アーカイブを削除するには、まず S3 バケットの名前を特定することから始めます。スタック内で `ArtifactBucket` 論理 ID を持つバケットを以下の通りに取得します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --query "StackResources[?LogicalResourceId=='ArtifactBucket'].PhysicalResourceId" \
- --output text
-:::
-
-このコマンドが `ArtifactBucket` のバケット名 (例えば `cloudformationmanageduploadinfra-accesslogsbucket-[...省略...]`) を返します。メモにとってください。以下のコマンドでそのバケットの内容の一覧を取得します。コマンドのパラメータをメモにとったバケット名に書き換えてください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3 ls s3://NAME-OF-YOUR-cloudformationmanageduploadinfrast-artifactbucket-[...]
-:::
-
-このコマンドでは、リソースタイプの情報を持つ ZIP ファイルを `AWSSamples-EC2-ImportKeypair-YYYY-MM-ddthh-MM-SS.zip` のような形の名前で表示されるはずです。ファイル名をメモします。`ArtifactBucket` バケットはバージョニングが有効になっているため、上記の ZIP ファイルオブジェクトのバージョン ID に関する情報を収集する必要があります。以下のコマンドのパラメータをメモしたバケット名とファイル名に置き換えて実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3api list-object-versions \
- --bucket YOUR-cloudformationmanageduploadinfrast-artifactbucket \
- --prefix awssamples-ec2-importkeypair-YYYY-MM-DDTHH-MM-SS.zip \
- --query "Versions[*].VersionId" --output text
-:::
-
-ZIP ファイルのバージョン ID が `abcExampleAbCDExampleABCDExample` のように出力されるはずです。こちらもメモして、以下の通りにオブジェクトのバージョンを削除します。コマンドにメモしたバケット名、ファイル名、バージョン ID 情報を必ず置き換えてください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3api delete-object \
- --bucket YOUR-artifactbucket-name \
- --key awssamples-ec2-importkeypair-YYYY-MM-DDTHH-MM-SS.zip \
- --version-id abcdEXAMPLEabcdEXAMPLEabcdEXAMPLE
-:::
-
-このラボでリソースタイプを複数回レジストリに送信した場合、名前が `awssamples-ec2-importkeypair-` で始まるオブジェクトがバケット内に複数見つかる可能性があり、これらも上記と同じ方法で削除する必要があります。
-
-::alert[`CloudFormationManagedUploadInfrastructure` スタックは、CloudFormation 拡張機能をアカウントのレジストリに送信するために使用されるリソースを管理します。**このラボを実施するために使用されているアカウントで、他のリソースタイプ、モジュール、フックなど、他に CloudFormation 拡張機能を作成している場合、`CloudFormationManagedUploadInfrastructure` スタックで管理している S3 バケットに、他のオブジェクトが見つかる場合があります。それらのオブジェクトを削除しない場合は、このクリーンアップセクションの残りの部分もスキップしてください**。他にオブジェクトがなかった場合は、次の手順に進んでください。]{type="warning"}
-
-次は、スタック内の論理 ID が `AccessLogsBucket` である S3 バケットのバケット名を特定します。次のコマンドでリソースから抽出します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --query "StackResources[?LogicalResourceId=='AccessLogsBucket'].PhysicalResourceId" \
- --output text
-:::
-
-上記のコマンドで `AccessLogsBucket` のバケット名を取得できるはずです。たとえば、`cloudformationmanageduploadinfra-accesslogsbucket-[...省略...]` のような形です。メモをします。このラボの実行の途中でこのバケットにオブジェクトが作成された場合があります。以下のコマンドを使用してその内容の一覧を表示します。コマンドのバケット名はメモしたバケット名で置き換えてください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3 ls s3://NAME-OF-YOUR-cloudformationmanageduploadinfra-accesslogsbucket-[...]
-:::
-
-この [ページ](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/ServerLogs.html#how-logs-delivered) で説明されているように、サーバーアクセスログを有効にすると Amazon S3 はバケット (この場合はログバケットを使用するアーティファクト用のバケット) のアクセスログを定期的に収集して統合し、そのログをターゲットのロギングバケットにアップロードします。現時点でログバケットにオブジェクトが表示されない場合でも、状況によっては、後でログバケットを削除しようとしたときにログが配信された可能性があります。オブジェクトを含むバケットは削除できません。その場合、ログバケットを作成したスタックを削除するとエラーが発生します。ログバケットのログファイルを削除する場合は、先ほどのアーティファクトバケット内のオブジェクトの対応方法と同様のプロセスを実施します。その後に再度ログバケット (または作成したスタック) の削除を試みことができます。以下の手順で実施できます。
-
-`CloudFormationManagedUploadInfrastructure` スタックを削除する前に、`AccessLogsBucket` と `EncryptionKey` の `DeletionPolicy: Retain` と `UpdateReplacePolicy: Retain` を無効化する必要があります。テンプレートを取得して、`CloudFormationManagedUploadInfrastructure.template` に保存してください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation get-template \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --query TemplateBody \
- --output text > CloudFormationManagedUploadInfrastructure.template
-:::
-
-テキストエディタで `CloudFormationManagedUploadInfrastructure.template` を開き、以下の通りに修正します。
-- 全ての `DeletionPolicy: Retain` を `DeletionPolicy: Delete` に書き換えます。
-- 全ての `UpdateReplacePolicy: Retain` を `UpdateReplacePolicy: Delete` に書き換えます。
-
-修正済みテンプレートを保存して、スタックのアップデートに使います。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --template-body file://CloudFormationManagedUploadInfrastructure.template \
- --capabilities CAPABILITY_IAM
-
-aws cloudformation wait stack-update-complete \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure
-:::
-
-不要となった修正済みテンプレートファイルを削除します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-rm CloudFormationManagedUploadInfrastructure.template
-:::
-
-`CloudFormationManagedUploadInfrastructure` スタックの削除保護を解除します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-termination-protection \
- --region us-east-1 \
- --no-enable-termination-protection \
- --stack-name CloudFormationManagedUploadInfrastructure
-:::
-
-`CloudFormationManagedUploadInfrastructure` スタックを削除します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure
-
-aws cloudformation wait stack-delete-complete \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure
-:::
-
-### まとめ
-
-おめでとうございます! Python でのサンプルリソースタイプ実装を一通り実施し、リソースタイプを作成する際に留意すべき重要な概念、期待される事項、目的を学びました。
diff --git a/content/advanced/resource-types/example-in-python/index.md b/content/advanced/resource-types/example-in-python/index.md
deleted file mode 100644
index 0786b2c0a..000000000
--- a/content/advanced/resource-types/example-in-python/index.md
+++ /dev/null
@@ -1,460 +0,0 @@
----
-title: "Example in Python"
-weight: 320
----
-
-### Overview
-
-In this module, you will follow steps to register a sample private extension, written in Python, with the AWS CloudFormation registry in your AWS account. You will also navigate through the example source code implementation logic for the resource type to understand key concepts of the resource type development workflow.
-
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* understand key concepts to leverage when you develop a resource type;
-* use the [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) to create a new project, run contract tests, and submit the resource type as a private extension to the CloudFormation registry in your AWS account;
-* understand how to use the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) to manually test your resource type handlers.
-
-
-
-### Start Lab
-
-In this lab, you will use a sample resource type from this [repository](https://github.com/aws-cloudformation/aws-cloudformation-samples).
-
-::alert[For information on creating a new project instead, see [Walkthrough: Develop a resource type](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-walkthrough.html).]{type="info"}
-
-
-#### Sample resource type walkthrough
-
-As an example, you will use the [AWSSamples::EC2::ImportKeyPair](https://github.com/aws-cloudformation/aws-cloudformation-samples/tree/main/resource-types/awssamples-ec2-importkeypair/python) sample resource type, that illustrates an example of importing and managing an imported [Amazon EC2 key pair](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) with CloudFormation.
-
-Let's get started! Create a new directory and clone this [repository](https://github.com/aws-cloudformation/aws-cloudformation-samples) into it. Alternatively, you can choose to [download a ZIP archive](https://github.com/aws-cloudformation/aws-cloudformation-samples/archive/refs/heads/main.zip) instead. To clone the repository, use the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-git clone https://github.com/aws-cloudformation/aws-cloudformation-samples.git
-:::
-
-The repository contains a number of samples. Change directory into the directory for the sample resource type:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-cd aws-cloudformation-samples/
-cd resource-types/awssamples-ec2-importkeypair/python/
-:::
-
-Let's take a look at a number of elements in the directory structure:
-
-* `docs/`: contains auto-generated syntax information for properties of the resource type. Every time you make changes to the resource schema file, you want to refresh auto-generated code - that includes files in this directory - with the `cfn generate` CloudFormation CLI [command](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-cli-generate.html);
-* `inputs/`: contains files with key/value data for resource type input properties. The resource type creator specifies this input information for use with contract tests: *do not add sensitive information to those files*. For more information, see [Specifying input data for use in contract tests](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test.html#resource-type-test-input-data);
-* `awssamples-ec2-importkeypair.json`: resource schema file, named after the chosen resource type name, used to **describe the model for the resource**;
-* `src/`: contains a directory named after the resource type name, inside you will find:
- - `models.py`: managed by the CloudFormation CLI on your behalf when you make schema changes, and
- - `handlers.py`: where the resource type developer adds code for the CRUDL implementation logic. Open the `src/handlers.py` file with a text editor of your choice, and **familiarize with the handlers' structure** described in `create_handler`, `update_handler`, `delete_handler`, `read_handler`, `list_handler` functions;
-* `resource-role.yaml`: file managed by the CloudFormation CLI, that describes an [AWS Identity and Access Management](https://aws.amazon.com/iam/) (IAM) role whose `PolicyDocument` contains permissions the resource type developer indicates in the `handlers` section of the schema file. CloudFormation assumes this role to manage resources for this resource type on behalf of the user as part of CRUDL operations;
-* `template.yml`: [AWS Serverless Application Model](https://aws.amazon.com/serverless/sam/) (SAM) template used as part of resource type testing.
-
-
-#### Resource modeling
-
-The **first step** in creating a resource type is to **define a schema that describes properties for your resource**, as well as **permissions needed** for **CloudFormation to manage the resource** on your behalf.
-
-Let's start with determining which properties are needed in the sample resource type you are using for this walkthrough. Visit the API reference page relevant to the resource type you wish to create; for the `AWSSamples::EC2::ImportKeyPair` resource type example, you want to look for the [Amazon EC2 API reference](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Welcome.html): you can find it by navigating to the [AWS documentation](https://docs.aws.amazon.com/) page, where you choose **Amazon EC2** from **Compute**, and then **API Reference** in the next page.
-
-Next, from [Actions](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Operations.html), locate operations that give you the ability to programmatically perform actions on a key pair: you note `CreateKeyPair`, `DeleteKeyPair`, `DescribeKeyPairs`, and `ImportKeyPair`. Since `CreateKeyPair` is relevant to a key pair creation and not to its import, it is not needed. The other 3 actions are needed instead.
-
-Navigate to the [ImportKeyPair](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ImportKeyPair.html) documentation: you want to look into *request parameters* and *response elements* to **determine which properties you want to describe in the schema**. For *request parameters*, in this case, you want to specify:
-
-* a `KeyName` for the key pair you're importing (see the *Required: Yes* relevant note in the documentation);
-* your `PublicKeyMaterial` content (*Required: Yes*);
-* a set of optional tags (`TagSpecification.N` - *Required: No)*.
-
-
-Let's now look at *response elements*: `keyPairId` is returned when you create the resource, along with other elements that include the `keyFingerprint`. The [DeleteKeyPair](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteKeyPair.html) action takes in parameters that include the `KeyName`. Let's summarize an initial analysis:
-
-* `KeyName` and `PublicKeyMaterial` are required input parameters; tags (`TagSpecification.N`), are optional;
-* `keyPairId` and `keyFingerprint` are available after the resource is created; hence, cannot be specified by the user;
-* `keyPairId` is a good choice for the resource's primary identifier property.
-
-Properties above are good candidates for use with *create*, *update*, and *delete* handlers CloudFormation uses to manage the resource on your behalf.
-
-Additional properties are needed for the other two handlers: *read* (invoked by CloudFormation on stack updates when resource current state information is required) and *list* (invoked when summary information is needed for multiple resources of a given type). In this example, [`DescribeKeyPairs`](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeKeyPairs.html) is a good choice on which to start to look for relevant properties, such as `keySet` and `keyType`.
-
-Let's now compare findings above with the example schema for the `AWSSamples::EC2::ImportKeyPair` resource type. Open the `awssamples-ec2-importkeypair.json` file with your favorite text editor; you'll note that:
-
-* properties for the model, along with value constraints, are described in the `properties` section;
-* `KeyName`, `PublicKeyMaterial` are set as `required`
-* `KeyPairId`, `KeyFingerprint`, `KeyType` (properties that are determined after resource creation) are specified as `readOnlyProperties`
-* `KeyPairId` is set as a `primaryIdentifier`
-* `PublicKeyMaterial` is specified with `writeOnlyProperties`. You often use `writeOnlyProperties` to describe values containing sensitive data (such as passwords): these values cannot be returned from *list* or *read* requests. In the `AWSSamples::EC2::ImportKeyPair` example, since information for the public key material is not returned by `DescribeKeyPairs` that the example uses in *list* or *read* handlers, it would not make sense to include it with a null value in *list* or *read* handlers: this is why, in the example, describing the property as `writeOnlyProperties` is deemed to be a fit;
-* `KeyName`, `PublicKeyMaterial` are set as `createOnlyProperties`: as such, updating any of the two values for the imported key pair will cause the creation of a new resource with new values, and a deletion of the previous resource;
-* `Tags`, that are not required, are described in the [`definitions`](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-schema.html#schema-properties-definitions) section as part of best practices for potential reuse across definitions in your schema. In the example schema, `Tags` are referenced with a `$ref` pointer in the `properties` section.
-
-For more information on how to create a schema and on schema elements, see [Resource type schema](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-schema.html).
-
-The `awssamples-ec2-importkeypair.json` example schema file also contains a number of [AWS Identity and Access Management](https://aws.amazon.com/iam/) (IAM) permissions that handlers will need to manage the resource type on your behalf. When you look into the `handlers` section on the example schema file, you'll find a number of self-descriptive, EC2-related permissions. For example, for *create* and *read* handlers, you should find the following:
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
- "handlers": {
- "create": {
- "permissions": [
- "ec2:ImportKeyPair",
- "ec2:CreateTags"
- ]
- },
- "read": {
- "permissions": [
- "ec2:DescribeKeyPairs"
- ]
- },
-:::
-
-For more information on permissions from which you can choose when you create your resource type, see [Actions, resources, and condition keys for AWS services](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html): on that page, choose the AWS service you need - in the current example, [Amazon EC2](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html) - and then choose [Actions defined by Amazon EC2](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html#amazonec2-actions-as-permissions).
-
-::alert[When you make changes to the schema file for the resource you develop, run the `cfn generate` CloudFormation CLI command from inside the root directory of your resource type project to reflect schema changes into project files such as `docs/*`, `resource-role.yaml`, and `src/[RESOURCE_TYPE_NAME]/models.py`.]{type="info"}
-
-
-#### Handlers
-
-Once you model a resource schema as shown in the example earlier, the next step is to start the code implementation in handlers. Considerations to make are:
-
-* for a given CRUDL handler (*Create*, *Read*, *Update*, *Delete*, *List*), you will need to implement a business logic as such:
- * call a given, service-specific API(s) (such as `ImportKeyPair` in the *create* handler, `DeleteKeyPair` in the *delete* handler, etc.);
-* consume data returned by a given API you call in a given handler; moreover:
- * every handler must always return a `ProgressEvent`. For more information on its structure, see [ProgressEvent object schema](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test-progressevent.html);
- * if there are no errors, return a `ProgressEvent` object with `status=OperationStatus.SUCCESS` from a given handler; for example: `return ProgressEvent(status=OperationStatus.SUCCESS)`. Additionally, if the handler is not *delete* or *list*, return a `ResourceModel` object (the model for the resource) with the data you gather with your handler code (from an API call) for the resource. For the *list* handler, instead of a single model, return a list of models for each of your resources of the type you're describing;
- * if the API you call returns an error, or if there is another exception being thrown, return a `ProgressEvent` object with `status=OperationStatus.FAILED`. Considerations to make when you do so include:
- * capture the stacktrace, and the specific error message text from a given exception (`botocore.exceptions.ClientError`, other exceptions, ...). This way, you can show your stacktrace in log statements you write in your handler's code, and return the error message description with a `ProgressEvent` object, so that this information can be made available as part of CloudFormation events (e.g., in the Events pane in the CloudFormation console) to describe to the user the cause of the error;
- * depending on the error you get from the underlying API (for the import key pair example, for a given error from [Error codes for the Amazon EC2 API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html)), you want to map it to a given error from [Handler error codes](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test-contract-errors.html). For example, if an EC2 API returns an `InvalidKeyPair.NotFound` client error you want to return a `HandlerErrorCode.NotFound` handler error with a `ProgressEvent`;
- * if your resource type will require time to stabilize (for example, reaching to a state where the resource is fully available), use a stabilization mechanism on *create*, *update*, and *delete* handlers: you return a `ProgressEvent` with an `OperationStatus.IN_PROGRESS` the first time a handler is called, and for subsequent calls of that handler until your desired state is reached, you drive next steps by checking on the progress status by calling the *read* handler (where, for example, you check for a specific property value to determine creation complete or in progress).
-
-You can see examples of topics described above in the `src/awssamples_ec2_importkeypair/handlers.py` sample resource type. Each handler makes calls to given EC2 API(s), for which there is a relevant set of permissions set in the schema as you have seen earlier.
-
-The sample resource type leverages exception handling mechanism described above, whereas a downstream API error message is captured and returned along with a handler error code mapped to a given EC2 API. Here's an excerpt taken from the `read_handler` function in the sample resource type (if you look at the `_progress_event_failed` function in the sample resource type code, it then consumes input information by logging stacktrace information and by returning a `ProgressEvent` failure):
-
-:::code{language=python showLineNumbers=false showCopyAction=false}
- except botocore.exceptions.ClientError as ce:
- return _progress_event_failed(
- handler_error_code=_get_handler_error_code(
- ce.response['Error']['Code'],
- ),
- error_message=str(ce),
- traceback_content=traceback.format_exc(),
- )
-:::
-
-Even if, for the key pair import use case, a stabilization process is not necessarily needed, the sample resource type illustrates an example of a callback mechanism used in *create*, *update*, and *delete* handlers and driven by the `_is_callback` example function.
-
-
-#### Running unit tests
-
-As part of software development best practices, you want to write *unit tests* to increase your level of confidence that your code works the way you expect. As mentioned in these [notes](https://github.com/aws-cloudformation/aws-cloudformation-samples/tree/main/resource-types/awssamples-ec2-importkeypair/python#unit-tests), the `AWSSamples::EC2::ImportKeyPair` sample resource type includes unit tests in the `src/awssamples_ec2_importkeypair/tests` directory. If you look at the `test_handlers.py` file in that directory (that should be on your machine as part of the repository clone/download choice you made earlier), you will see test utility functions described at the beginning and, about at half-way through the file, unit tests that consume such utility functions to perform tests including validating return values and exceptions being thrown. Objects, that include function calls such as EC2 API calls, are replaced/patched in tests with mock objects calls by leveraging the [unittest.mock](https://docs.python.org/3/library/unittest.mock.html) mock object library.
-
-Let's run unit tests! Make sure you are in the directory that is at the root level of the `AWSSamples::EC2::ImportKeyPair` sample resource type (i.e., inside the `python` directory), and that you have followed prerequisites in the previous topic. Next, choose to run unit tests as follows:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pytest --cov src --cov-report term-missing
-:::
-
-You should get an output indicating unit tests results, along with a total coverage percentage value. Unit tests in the sample resource type leverage a `.coveragerc` file at the root of the project that contains [configuration](https://coverage.readthedocs.io/en/latest/config.html) choices that include a required test coverage value.
-
-
-#### Running contract tests
-
-In subsequent steps on this lab, you will locally test and then submit, to the CloudFormation Registry in your account, the `AWSSamples::EC2::ImportKeyPair` sample resource type as a private extension.
-
-As you build your resource type, and very early in the development process, you want to make sure to leverage the [Resource type handler contract](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test-contract.html), that describes requirements for you to adhere to when you implement the business logic of your handlers. Enforcement of the handler contract is done when you submit a public resource type to the Registry, whereas in that case you are required to pass contract tests: this is important to make sure a high quality bar is maintained on behalf of external customers consuming your resource type.
-
-::alert[Contract tests must pass in order to publish a public resource type, and do not run when you submit a private resource type. As part of best practices though, you should try to adhere to contract tests specifications very early in your development process.]{type="info"}
-
-Let's run contract tests for the sample resource type! First, let's set up test support infrastructure as described on these [notes](https://github.com/aws-cloudformation/aws-cloudformation-samples/tree/main/resource-types/awssamples-ec2-importkeypair/python#contract-tests) for the sample resource type. Contract tests for the sample resource type will create, update, and delete test-only key pair resources in your account. Key pair information, such as name and tags, will be provided in files in the `inputs` directory in the project, and the public key material will be consumed from an exported value of a CloudFormation stack you create. For more information on how to pass test data to contract tests, see [Specifying input data for use in contract tests](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test.html#resource-type-test-input-data).
-
-::alert[Contract tests will make real API calls. Make sure your configuration is set up to point to your test AWS account, so to use either relevant environment credentials or relevant credentials from the Boto3 credential chain.]{type="info"}
-
-First, let's generate an SSH key pair you will use for testing. Open a new terminal console in your machine, and choose an existing or new directory outside the `AWSSamples::EC2::ImportKeyPair` project directory path. When ready, change directory in to the one you chose or created, and create the SSH key pair with the `ssh-keygen` command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-ssh-keygen -t rsa -C "Example key pair for testing" -f example-key-pair-for-testing
-:::
-
-Follow prompts and complete the creation of the key pair. You should now have, in the directory you chose, 2 files: `example-key-pair-for-testing` and `example-key-pair-for-testing.pub`. The former is the private key; the latter the public key portion, which is the one you will use in following steps where, when needed, you will need to provide it's content by opening the public key file, copying its content in the clipboard and pasting it in the command line.
-
-Next, create a CloudFormation stack that will create, for reference, an [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) resource containing the public key material you will provide an input: contract tests will consume the `KeyPairPublicKeyForContractTests` [exported stack output value](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) of this stack. Input files in the `inputs` directory of the sample resource type, in turn, contain `{{KeyPairPublicKeyForContractTests}}` references to the value exported from the stack.
-
-When ready, switch back to the terminal where you cloned or downloaded the sample resource type, and make sure you are in the `aws-cloudformation-samples/resource-types/awssamples-ec2-importkeypair/python/` directory. With the next command, you will choose to create a new stack using the `examples/example-template-contract-tests-input.yaml` example template file: the template requires you to specify the `KeyPairPublicKey` input parameter, for which you will need to specify the content as mentioned earlier. The template also requires `OrganizationName` and `OrganizationBusinessUnitName`, that are set with example default values, `ExampleOrganization` and `ExampleBusinessUnit` respectively, and that will be used if you do not choose to provide values for them. Choose to create the stack as shown next, with a placeholder for the public key file content, where you will need to copy and paste the content of the public key file (the example uses `us-east-1` for the AWS region, change this value as needed):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --region us-east-1 \
- --stack-name example-for-key-pair-contract-tests \
- --template-body file://examples/example-template-contract-tests-input.yaml \
- --parameters ParameterKey=KeyPairPublicKey,ParameterValue='PASTE_CONTENT_OF_example-key-pair-for-testing.pub'
-:::
-
-Wait until the `example-for-key-pair-contract-tests` stack is created, by using the CloudFormation console or the [stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) wait command of the AWS CLI (the example uses `us-east-1` for the AWS region):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --region us-east-1 \
- --stack-name example-for-key-pair-contract-tests
-:::
-
-Next, you will need two terminal consoles opened on your machine; for each one, make sure you are at the root level of the `AWSSamples::EC2::ImportKeyPair` sample resource type project:
-
-* on the first terminal console, make sure Docker is running on your machine, and run `sam local start-lambda`
-* on the second terminal console, run contract tests: `cfn generate && cfn submit --dry-run && cfn test`
-
-For more information on contract tests for each handler (e.g., `contract_create_create`, `contract_create_read`, etc.), see [Contract tests](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/contract-tests.html).
-
-At the end of this process, you should see output indicating contract tests results. Let's move onto the next step!
-
-
-#### Submitting the resource type as a private extension
-
-Let's use the CloudFormation CLI to submit the resource to the registry in your CloudFormation account (the example uses `us-east-1` for the AWS region):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn generate && cfn submit --set-default --region us-east-1
-:::
-
-Wait until the registration finishes, after which you should have the `AWSSamples::EC2::ImportKeyPair` sample resource type registered as a private extension in your account. To verify, choose *Activated extensions* in the CloudFormation console, and then choose *Privately registered*.
-
-Now, let's test the sample resource type with an example template, that is already available as `examples/example-template-import-keypair.yaml` in the repository you cloned or downloaded: if you open the file with a text editor of your choice, you will see how the sample resource type is referenced in the `Resources` section. For `KeyPairPublicKey`, choose to specify the same public key content you used for contract tests. The template also uses default values for `KeyPairName`, `OrganizationName`, and `OrganizationBusinessUnitName`, that will be used unless you specify your own. Choose to create the stack (the example uses `us-east-1` for the AWS region):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --region us-east-1 \
- --stack-name example-key-pair-stack \
- --template-body file://examples/example-template-import-keypair.yaml \
- --parameters ParameterKey=KeyPairPublicKey,ParameterValue='PASTE_CONTENT_OF_example-key-pair-for-testing.pub'
-:::
-
-Wait until the stack creation finishes, after which you should have imported successfully the example key pair using CloudFormation and the sample `AWSSamples::EC2::ImportKeyPair` resource type (the example uses `us-east-1` for the AWS region):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --region us-east-1 \
- --stack-name example-key-pair-stack
-:::
-
-
-
-### Challenge
-
-##### Context
-As part of contract testing, you also have the option of [Testing resource types manually](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test.html#manual-testing), by using the [`sam local invoke`](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-invoke.html) command to issue handler invocations. To manually run tests:
-
-* in one terminal, run `sam local start-lambda` like you did earlier on this lab (from inside the `python` directory of the sample resource type);
-* in another terminal, invoke the handler with e.g., `sam local invoke TestEntrypoint --event sam-tests/YOUR_INPUT_FILE`, where `YOUR_INPUT_FILE` is a JSON-formatted file whose structure is documented [here](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test.html#manual-testing), and that you locally store in a `sam-tests` directory at the project's root level.
-
-::alert[Files you create and edit in the `sam-tests` directory may contain credentials. The `sam-tests/` location should be added to a `.gitignore` file (like the one at the project's root level for the sample resource type you used in this lab) to avoid adding it to a source code repository. Depending on your setup, you might or might not need to add credentials to the files in the `sam-tests` directory.]{type="info"}
-
-##### Challenge
-Create a `sam-tests/example-read.json` file to test the *read* handler of the `AWSSamples::EC2::ImportKeyPair` sample resource type. As an example input, choose the key pair you created in the `example-key-pair-stack` stack earlier. The expected output is a data structure containing properties from the model that the *read* handler for the sample resource type first fetches on your behalf, and that then returns.
-
-:::expand{header="Need a hint?"}
-* Use the [uuid](https://docs.python.org/3/library/uuid.html) module in Python to generate a `UUID4` value to pass to `clientRequestToken`;
-* from the [Read handlers](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test-contract.html#resource-type-test-contract-read) section in the Resource type handler contract documentation [page](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test-contract.html), read content in *Input assumptions* to determine which key and value to pass, as an input, underneath the `desiredResourceState` key in the JSON structure;
-* use an example value for the logical identifier of the resource, such as `MyExampleResource`.
-:::
-
-
-:::expand{header="Want to see the solution?"}
-* Create a `sam-tests/example-read.json` file, by using the structure documented [here](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-test.html#manual-testing);
-* from the Python command line interface, generate a `UUID4` value as in this example:
-
-```shell
->>> import uuid
->>> uuid.uuid4()
-UUID('OUTPUT EDITED: THIS WILL CONTAIN A UUID4 VALUE')
-```
-
-* from the `Outputs` section of the `example-key-pair-stack` CloudFormation stack you created: use the value for `KeyPairId`, and pass it to a new `KeyPairId` key that you create in the JSON file's structure underneath the `desiredResourceState` key;
-* a resulting file structure should look like in the following example:
-
-```json
-{
- "credentials": {
- "accessKeyId": "",
- "secretAccessKey": "",
- "sessionToken": ""
- },
- "action": "READ",
- "request": {
- "clientRequestToken": "REPLACE_WITH_YOUR_UUID4_VALUE_HERE",
- "desiredResourceState": {
- "KeyPairId": "REPLACE_WITH_THE_KEYPAIR_ID"
- },
- "logicalResourceIdentifier": "MyExampleResource"
- },
- "callbackContext": {}
-}
-```
-
-* run `sam local invoke TestEntrypoint --event sam-tests/example-read.json` sample test file; you should see, as an output, a `resourceModel` section with resource property values returned from the *read* handler.
-:::
-
-
-### Clean up
-
-Steps to clean up resources you created follow next (assuming `us-east-1` as the AWS region you chose):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --region us-east-1 \
- --stack-name example-key-pair-stack
-
-aws cloudformation wait stack-delete-complete \
- --region us-east-1 \
- --stack-name example-key-pair-stack
-
-aws cloudformation delete-stack \
- --region us-east-1 \
- --stack-name example-for-key-pair-contract-tests
-
-aws cloudformation wait stack-delete-complete \
- --region us-east-1 \
- --stack-name example-for-key-pair-contract-tests
-
-aws cloudformation deregister-type \
- --region us-east-1 \
- --type-name AWSSamples::EC2::ImportKeyPair \
- --type RESOURCE
-:::
-
-When you use the `cfn submit` command to register a CloudFormation extension, such as resource types, modules, and hooks, the CFN-CLI creates 2 CloudFormation stacks in your account: one to create the execution role for the extension (such as for a resource type extension, or for a hook extension), and one to store infrastructure components for the extension. The CFN-CLI also sets a termination protection on both stacks. The two stacks are called `awssamples-ec2-importkeypair-role-stack`, that is specific for this lab, and `CloudFormationManagedUploadInfrastructure`, that is used by this lab, and by any other extension you are developing or registering using the CFN-CLI with your account.
-
-Follow steps shown next to delete the `awssamples-ec2-importkeypair-role-stack` stack. First, remove its termination protection:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-termination-protection \
- --region us-east-1 \
- --no-enable-termination-protection \
- --stack-name awssamples-ec2-importkeypair-role-stack
-:::
-
-Next, delete the `awssamples-ec2-importkeypair-role-stack` stack:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --region us-east-1 \
- --stack-name awssamples-ec2-importkeypair-role-stack
-
-aws cloudformation wait stack-delete-complete \
- --region us-east-1 \
- --stack-name awssamples-ec2-importkeypair-role-stack
-:::
-
-The other stack, `CloudFormationManagedUploadInfrastructure`, creates a number of resources, that include also an [AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/) key, and two Amazon S3 buckets to store data related to CloudFormation extensions registry submissions, including the resource type ZIP archive that the CFN-CLI created and uploaded on your behalf as you went through this lab. To delete this ZIP archive, start with identifying the name of the S3 bucket whole logical ID in the stack is `ArtifactBucket`. Describe the stack resources as follows:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --query "StackResources[?LogicalResourceId=='ArtifactBucket'].PhysicalResourceId" \
- --output text
-:::
-
-The command above should return the `ArtifactBucket` bucket name; for example, `cloudformationmanageduploadinfra-accesslogsbucket-[...omitted...]`; make a note of it. Use the following command to list the bucket content (make sure to replace the bucket name with the one you identified in the previous step):
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3 ls s3://NAME-OF-YOUR-cloudformationmanageduploadinfrast-artifactbucket-[...]
-:::
-
-The command should show the name of the ZIP file containing the resource type information, with the following pattern: `awssamples-ec2-importkeypair-YYYY-MM-DDTHH-MM-SS.zip`. Make a note of the file name. Since the `ArtifactBucket` bucket has versioning enabled, you'll need to gather information on the version ID of the ZIP file object above (make sure to replace bucket name and file name information as you follow the next example, to reflect your output data):
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3api list-object-versions \
- --bucket YOUR-cloudformationmanageduploadinfrast-artifactbucket \
- --prefix awssamples-ec2-importkeypair-YYYY-MM-DDTHH-MM-SS.zip \
- --query "Versions[*].VersionId" --output text
-:::
-
-This should yield a version ID for that ZIP file in the output, such as `abcdEXAMPLEabcdEXAMPLEabcdEXAMPLE`. Make a note of it, and delete the object version (make sure to replace bucket name, file name, and version ID information in the example to reflect your output data):
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3api delete-object \
- --bucket YOUR-artifactbucket-name \
- --key awssamples-ec2-importkeypair-YYYY-MM-DDTHH-MM-SS.zip \
- --version-id abcdEXAMPLEabcdEXAMPLEabcdEXAMPLE
-:::
-
-If you have performed more than one registry submission for the resource type as part of this lab, you might find in the bucket more object(s), whose name start(s) with `awssamples-ec2-importkeypair-`, and that you would want to remove as well in the same way as shown above.
-
-::alert[The `CloudFormationManagedUploadInfrastructure` stack manages resources used to submit CloudFormation extensions to the registry in your account. **If you are currently using your account to create other CloudFormation extensions, such as other resource types, modules, or hooks, you might find other objects in the S3 bucket(s) managed by the `CloudFormationManagedUploadInfrastructure` stack, that you want to preserve from manual deletion. You would also want to skip the remaining part of this cleanup section**. Otherwise, follow steps shown next.]{type="warning"}
-
-Next, identify the name of the S3 bucket whose logical ID in the stack is `AccessLogsBucket`; describe the stack resources as follows:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --query "StackResources[?LogicalResourceId=='AccessLogsBucket'].PhysicalResourceId" \
- --output text
-:::
-
-The command above should return the `AccessLogsBucket` bucket name; for example, `cloudformationmanageduploadinfra-accesslogsbucket-[...omitted...]`; make a note of it. This bucket might contain objects as part of running this lab; list its content with the following command (make sure to replace the bucket name with the one you identified in the previous step):
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3 ls s3://NAME-OF-YOUR-cloudformationmanageduploadinfra-accesslogsbucket-[...]
-:::
-
-As described on this [page](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerLogs.html#how-logs-delivered), Amazon S3 periodically collects and consolidates access logs when you enable server access logging for your bucket (that is, in this case, the bucket for artifacts using the logs bucket), and then uploads the logs to the target logging bucket. If you do not see objects in the logs bucket above at this time, there might be a chance, depending on your case, that logs might be delivered whilst you are attempting to delete the logs bucket later on, if you choose to do so. You cannot delete a bucket with objects in it; if this is the case, you'll get an error when deleting the stack that created the logs bucket: if you choose to delete logs in your logs bucket, use the same process you chose to use above for objects in the artifacts bucket, before (re)attempting to delete the bucket (or the stack that creates it; see steps below for more information).
-
-Before deleting the `CloudFormationManagedUploadInfrastructure` stack, you'll need to update it to disable the `DeletionPolicy: Retain` and `UpdateReplacePolicy: Retain` for both `AccessLogsBucket` and `EncryptionKey`. Retrieve the template for the stack, and save it to the `CloudFormationManagedUploadInfrastructure.template` file on your machine:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation get-template \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --query TemplateBody \
- --output text > CloudFormationManagedUploadInfrastructure.template
-:::
-
-Open the `CloudFormationManagedUploadInfrastructure.template` file with your text editor, and:
-- replace all occurrences of `DeletionPolicy: Retain` with `DeletionPolicy: Delete`;
-- replace all occurrences of `UpdateReplacePolicy: Retain` with `UpdateReplacePolicy: Delete`.
-
-Save the updated template, and use it to update the stack:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure \
- --template-body file://CloudFormationManagedUploadInfrastructure.template \
- --capabilities CAPABILITY_IAM
-
-aws cloudformation wait stack-update-complete \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure
-:::
-
-Delete the updated template copy on your machine:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-rm CloudFormationManagedUploadInfrastructure.template
-:::
-
-Remove the termination protection from the `CloudFormationManagedUploadInfrastructure` stack:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-termination-protection \
- --region us-east-1 \
- --no-enable-termination-protection \
- --stack-name CloudFormationManagedUploadInfrastructure
-:::
-
-Delete the `CloudFormationManagedUploadInfrastructure` stack:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure
-
-aws cloudformation wait stack-delete-complete \
- --region us-east-1 \
- --stack-name CloudFormationManagedUploadInfrastructure
-:::
-
-### Conclusion
-
-Congratulations! You have walked through a sample resource type implementation in Python, and learned key concepts, expectations and objectives for you to keep in mind when writing your resource types.
diff --git a/content/advanced/resource-types/index.ja.md b/content/advanced/resource-types/index.ja.md
deleted file mode 100644
index 445d74d1f..000000000
--- a/content/advanced/resource-types/index.ja.md
+++ /dev/null
@@ -1,32 +0,0 @@
----
-title: "リソースタイプ"
-weight: 300
----
-
-### はじめに
-
-この章では、開発したリソースタイプを使用して [AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/) の作成、プロビジョニング、管理に関する機能を拡張する方法に焦点を当てます。
-
-リソースタイプは CloudFormation の第一級オブジェクトです。CloudFormation では、他の AWS リソースを管理するのと同様にリソースを管理できます。リソースタイプのソフトウェア開発ライフサイクル (SDLC) プロセスは次のように要約できます。
-
-1. リソースタイプの開発とテストに使用する前提条件となるツールをインストールします。
-2. リソースタイプの開発と必要なテストを実施します。
-3. 準備ができたら、リソースタイプを [AWS CloudFormation レジストリ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/registry.html)に登録します。
-4. CloudFormation を使用してリソースタイプを管理します。他の AWS リソースタイプと同様に、CloudFormation テンプレートにリソースタイプとプロパティを記述します。
-
-::alert[CloudFormation レジストリでは、リソースタイプをプライベート拡張として登録するか、パブリック拡張として登録するかを選択できます。このラボでは、プライベート拡張の例を取り上げます。]{type="info"}
-
-プライベート拡張を登録するとすると、AWS アカウント内の AWS CloudFormation レジストリで使用できるようになります。プライベート拡張を使用すると、テストや検証に使用している AWS アカウント等のサンドボックス環境でリソースタイプの動作をテストできます。プライベート拡張のもう1つの使用例は、企業内で使用されるプライベート/カスタムアプリケーションのコンポーネントをコード化する場合です。これらのコンポーネントは、企業固有のものであったり、独自のロジックを含んでいます。
-
-必要に応じて、リソースタイプを、他の [AWS CloudFormation StackSets を使用する AWS リージョン](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/publish-extension-stacksets.html)にデプロイすることができます。
-
-プライベート拡張の詳細については、[CloudFormationでのプライベートエクステンションの使用](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/registry-private.html)をご参照ください。パブリック拡張については、[Publishing extensions to make them available for public use](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/publish-extension.html) をご参照ください。
-
-::alert[サードパーティの発行元が提供するプライベート拡張やアクティベートされたパブリック拡張を使用する場合のアカウントへの料金については、[AWS CloudFormation の料金](https://aws.amazon.com/jp/cloudformation/pricing/) をご参照ください。これらの料金は、作成したリソースに対して発生する料金に加算されます。]{type="info"}
-
-### キーコンセプト
-
-リソースタイプを開発する際のキーコンセプトは次のとおりです。
-
-* [スキーマ](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-schema.html): ユーザーが入力値を指定できるプロパティや、リソース作成後にのみ使用可能になる読み取り専用プロパティ (リソース ID 等) など、リソースの仕様を記述するドキュメントです。
-* [ハンドラ](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-type-develop.html#resource-type-develop-implement-handlers): リソースタイプを開発するときは、作成、参照、更新、削除、リスト (CRUDL) 操作に関するライフサイクルを、[サポートされた言語](https://github.com/aws-cloudformation/cloudformation-cli#supported-plugins)で実装します。コードには、上記の CRUDL ハンドラー (*create* ハンドラー、*update* ハンドラー等) のリソースタイプに必要な動作 (特定の操作を実行するために呼び出す AWS またはサードパーティ API など) を記述します。
diff --git a/content/advanced/resource-types/index.md b/content/advanced/resource-types/index.md
deleted file mode 100644
index bd24ebac3..000000000
--- a/content/advanced/resource-types/index.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-title: "Resource Types"
-weight: 300
----
-
-### Introduction
-
-This part of the workshop focuses on how you can extend creation, provisioning, and management capabilities of [AWS CloudFormation](https://aws.amazon.com/cloudformation/) with resource types you develop.
-
-A resource type is a first-class object in CloudFormation: you can manage your resource as you would manage any AWS resource with CloudFormation. The Software Development Life Cycle (SDLC) process of a resource type can be summarized as follows:
-
-1. you install prerequisite tools you will use for development and testing of your resource type;
-2. you start to develop and run tests for your resource type;
-3. when ready, you submit the resource type to the [AWS CloudFormation registry](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry.html);
-4. manage your resource type with CloudFormation: you describe the resource type and its properties in your CloudFormation template(s), like you would do with any AWS resource type.
-
-::alert[You have the choice to register your resource type as a private or as a public extension in the CloudFormation registry: this lab covers private extension examples.]{type="info"}
-
-When you submit a private extension, you make it available in the AWS CloudFormation registry in your AWS account: private extensions give you the ability to test the behavior of your resource type in a sandbox environment, such as in an AWS account you own and that you use for testing/experimentation. Another use case for private extensions is for codifying private or custom application components that would be used within an enterprise, but might be company-specific, or contain proprietary logic.
-
-You can choose to deploy your resource type in other [AWS regions using AWS CloudFormation StackSets](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/publish-extension-stacksets.html) as needed.
-
-For more information on private extensions, see [Using private extensions in CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-register.html). For more information on public extensions, see [Publishing extensions to make them available for public use](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/publish-extension.html).
-
-::alert[Please refer to [AWS CloudFormation pricing](https://aws.amazon.com/cloudformation/pricing/) for information on charges to your account when you use private extensions or activated public extensions from third-party publishers. These charges are in addition to any charges incurred for resources that you create.]{type="info"}
-
-
-### Key concepts
-
-Key concepts for developing a resource type include:
-
-* [schema](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-schema.html): a document where you describe your resource specification, such as properties whose input values users can specify, or read-only properties that will only be available after resource creation (for example, a resource ID), et cetera;
-* [handlers](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-develop.html#resource-type-develop-implement-handlers): when you develop a resource type, you describe its life cycle across Create, Read, Update, Delete, List (CRUDL) operations in code you will implement in a [supported language](https://github.com/aws-cloudformation/cloudformation-cli#supported-plugins). In your code, you describe the behavior you wish to have for your resource type (e.g., which AWS or third-party API to call to perform a given operation) in CRUDL handlers mentioned above (e.g., the *create* handler, the *update* handler, et cetera).
diff --git a/content/advanced/resource-types/prerequisites/index.ja.md b/content/advanced/resource-types/prerequisites/index.ja.md
deleted file mode 100644
index 972db3340..000000000
--- a/content/advanced/resource-types/prerequisites/index.ja.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-title: 前提条件
-weight: 310
----
-
-### リソースタイプ開発ツール
-
-次のセクションに進む前に、以下の前提条件からマシンに適切なツールをインストールしてください。
-
-* 次のリンクからご使用のオペレーティングシステムに合う説明に従って [AWS SAM CLI](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-reference.html#serverless-sam-cli) をインストールしてください。SAM CLI をインストールするときは、コントラクトテストの実行に必要な Docker をインストールするための説明に従ってください (まだ Docker をインストールしていない場合のみ)。
-
- - [Linux の AWS SAM CLI](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html)
- - [Windows の AWS SAM CLI](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install-windows.html)
- - [macOS の AWS SAM CLI](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install-mac.html)
-
-* 使用したいサポート対象言語の [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) とプラグインをインストールします。
-
- `pip` を使用して CloudFormation CLI と Python プラグインをインストールします。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- pip install cloudformation-cli cloudformation-cli-java-plugin cloudformation-cli-go-plugin cloudformation-cli-python-plugin cloudformation-cli-typescript-plugin
- :::
-
-::alert[CloudFormation CLI のバージョン 1.0 がすでにインストールされている場合は、バージョン 2.0 にアップグレードし、使用する言語プラグインもアップグレードすることをお勧めします。アップグレードには、前に示した `pip install` コマンドの `--upgrade` オプションを使用し、使用している、または、使用する予定の言語プラグインを含めることができます。詳細については、[ページ](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html#resource-type-setup) の下部にある *Upgrading to CFN-CLI 2.0* をご参照ください。]{type="info"}
-
-* [Python での実装例](../example-in-python) ラボでは、サンプルアプリケーションのユニットテストを実行するために必要な以下のパッケージをインストールします。
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- pip install pytest-cov cloudformation-cli-python-lib
- :::
diff --git a/content/advanced/resource-types/prerequisites/index.md b/content/advanced/resource-types/prerequisites/index.md
deleted file mode 100644
index dcce64d8e..000000000
--- a/content/advanced/resource-types/prerequisites/index.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-title: "Prerequisites"
-weight: 310
----
-
-### Resource Type Development Tools
-Before proceeding to the next section, choose to install the following prerequisites on your machine:
-
-* install the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-reference.html#serverless-sam-cli) by following notes for your operating system in links shown next. When you install the SAM CLI, follow also notes to install Docker (unless you have already installed it), that is needed for running contract tests:
-
- - [AWS SAM CLI on Linux](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html)
- - [AWS SAM CLI on Windows](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install-windows.html)
- - [AWS SAM CLI on macOS](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install-mac.html)
-
-* install the [CloudFormation Command Line Interface (CLI)](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) and plugin(s) for supported languages that you wish to use.
-
- Use `pip` to install the CloudFormation CLI and Python plugin:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- pip install cloudformation-cli cloudformation-cli-java-plugin cloudformation-cli-go-plugin cloudformation-cli-python-plugin cloudformation-cli-typescript-plugin
- :::
-
-::alert[If you already have version 1.0 of the CloudFormation CLI installed, it is recommended to upgrade it to version 2.0, and to upgrade language plugin(s) you use as well. For the upgrade, you can use the `--upgrade` option for the `pip install` command shown previously, and include language plugins you use or plan to use. For more information, see *Upgrading to CFN-CLI 2.0* further down on this [page](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html#resource-type-setup).]{type="info"}
-
-* for the [Example in Python](../example-in-python) lab, install following packages that are needed for running unit tests for the sample application:
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- pip install pytest-cov cloudformation-cli-python-lib
- :::
diff --git a/content/basics/index.ja.md b/content/basics/index.ja.md
deleted file mode 100644
index 6ea63028b..000000000
--- a/content/basics/index.ja.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "初級編"
-weight: 30
----
-
-ワークショップの**初級編**へようこそ!
-
-初級編では、CloudFormation の中核となるコンセプトを紹介します。ここでは最初のテンプレートを構築し、それぞれのラボで改善していきます。また、コンソールからデプロイする方法についても学習します。
-
-途中では、テンプレートがどのような構成か、組み込み関数や他の便利な CloudFormation のコンセプトをどう使うかも紹介します。
diff --git a/content/basics/index.md b/content/basics/index.md
deleted file mode 100644
index 1e220f0fe..000000000
--- a/content/basics/index.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "Basics"
-weight: 30
----
-
-Welcome to the **Basic** part of the workshop.
-
-This part will introduce the core concepts of CloudFormation. You will build an initial template, then improve it in
-each lab. You will also learn how to deploy it from the console.
-
-Along the way, you will be introduced to how a template is structured, how to use intrinsic functions and other useful CloudFormation concepts.
diff --git a/content/basics/operations/helper-scripts/index.ja.md b/content/basics/operations/helper-scripts/index.ja.md
deleted file mode 100644
index 8e27189f0..000000000
--- a/content/basics/operations/helper-scripts/index.ja.md
+++ /dev/null
@@ -1,383 +0,0 @@
----
-title: "ヘルパースクリプト"
-weight: 400
----
-
-_ラボ実施時間 : 15分程度_
-
----
-
-### 概要
-
-このラボでは、CloudFormation [ヘルパースクリプト](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-helper-scripts-reference.html) について学習します。前のラボで学んだことは素晴らしい出発点です。しかし、`UserData` から気づくかもしれませんが手続き型スクリプトは理想的ではありません。シンプルな PHP アプリケーションをデプロイしたが、ユーザーデータにより複雑なアプリを書こうとすることを想像してみてください。それは非常に難しいでしょう。
-
-この問題を解決するために、CloudFormation はヘルパースクリプトを提供しています。これらのヘルパースクリプトは、CloudFormation を強化し、ユースケースに合わせて微調整できるようなテンプレートを可能とします。たとえば、インスタンスを作り直さずにアプリケーションを更新することが可能になります。
-
-ヘルパースクリプトは Amazon Linux にあらかじめインストールされており、`yum install -y aws-cfn-bootstrap` を使用して定期的に更新します。
-
-### カバーするトピック
-
-このラボでは、次のことを学びます。
-
-+ [cfn-init](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-init.html) によるリソースメタデータの取得と解釈、パッケージのインストール、ファイルの作成、サービスの開始を行う方法
-
-+ [cfn-hup](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-hup.html) でメタデータの更新を確認し、変更が検出されたときにカスタムフックを実行する方法
-
-+ [cfn-signal](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-signal.html) を使用してリソースまたはアプリケーションの準備が整ったときに CloudFormation にシグナルを送信する方法
-
-### ラボの開始
-
-1. `code/workspace` ディレクトリに移動します。
-1. `helper-scripts.yaml` ファイルを開きます。
-1. 以下のトピックを進めながら、コードをコピーしてください。
-
-#### 1. _Metadata_ セクションの設定
-
-Amazon EC2 インスタンスのためにメタデータを指定するには、`AWS::CloudFormation::Init` タイプを使用する必要があります。テンプレートが `cfn-init` スクリプトを実行すると、スクリプトはメタデータセクション内のリソースを検索します。テンプレートにメタデータを追加しましょう。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
- WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
-:::
-
-#### 2. cfn-init の設定
-
-`cfn-init` の設定はいくつかのセクションに分かれています。設定セクションは packages、groups、users、sources、files、commands、services の順番に処理されます。
-
-:::alert{type="info"}
-別の順序が必要な場合は、セクションを異なる設定キーに分けてから、[configset](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-init.html?shortFooter=true#aws-resource-init-configsets) で設定キーの順序を指定します。
-:::
-
-:::alert{type="info"}
-以下のコードサンプルのように、インデントを守ることが重要です。`code/solutions/helper-scripts.yaml` のソリューションコードによって、テンプレートをクロスリファレンスもできます。
-:::
-
-##### 1. HTTPD と PHP のパッケージのインストール
-
-インスタンスは Amazon Linux 2 を実行しているので、`yum` パッケージマネージャを使用してパッケージをインストールします。
-
-`packages` キーのコードをテンプレートに追加します。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages:
- yum:
- httpd: []
-:::
-
-##### 2. `index.php` ファイルの作成
-
-`files` キーを使用して EC2 インスタンスにファイルを作成します。コンテンツは、テンプレート内のインラインの指定か、インスタンスが取得できる URL として指定します。
-
-`files` キーのコードをテンプレートに追加します。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages: \
- {...}
- files:
- /var/www/html/index.php:
- content: |
-
-
-
-
-
- EC2 Instance ID:
- Availability Zone:
-
-
-
- mode: 000644
- owner: apache
- group: apache
-:::
-
-##### 3. Apache Web サーバーを有効にして起動する
-
-`services` キーを使用して、インスタンスの起動時にどのサービスを有効または無効にするかを定義できます。Linux システムの場合は、このキーは `sysvinit` キーを使用することでサポートされます。
-
-`services` キーのコードをテンプレートに追加します。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages:
- {...}
- files:
- {...}
- services:
- sysvinit:
- httpd:
- enabled: true
- ensureRunning: true
-:::
-
-##### 4. `cfn-init` スクリプトの実行
-
-メタデータにあるスクリプトはデフォルトでは実行されません。実行するには、UserData セクションで `cfn-init` ヘルパースクリプトを呼び出す必要があります。
-
-以下のコードでは、CloudFormation は最初に `aws-cfn-bootstrap` パッケージを更新して、最新バージョンのヘルパースクリプトを取得します。次に、メタデータからファイルとパッケージをインストールします。
-
-`UserData` プロパティのコードをテンプレートに追加します。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-UserData:
- Fn::Base64:
- !Sub |
- #!/bin/bash -xe
- # Update aws-cfn-bootstrap to the latest
- yum install -y aws-cfn-bootstrap
- # Call cfn-init script to install files and packages
- /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
-:::
-
-::alert[`!Sub` 組み込み関数は `${AWS::StackName}` と `${AWS::Region}` 変数の値を動的に置き換えます。]{type="info"}
-
-#### 3. cfn-hup の設定
-
-`cfn-hup` ヘルパースクリプトをインストールすると、既存の EC2 インスタンスがテンプレートの _UserData_ の変更を適用できるようになります。たとえば、テンプレート内のサンプル PHP アプリケーションを変更し、既存のスタックを更新することで、アプリケーションをデプロイできます。`cfn-hup` を利用しない場合は、EC2 インスタンスを置き換えるか、手動または外部の仕組みで EC2 インスタンスの更新を適用する必要があります。(実際の動作を確認するには、このラボのチャレンジセクションを参照してください)。
-
-1. `AWS::CloudFormation::Init` の `files` セクションに以下の 2 つのファイルを追加します。
-
- + /etc/cfn/cfn-hup.conf
- + /etc/cfn/hooks.d/cfn-auto-reloader.conf
-
-1. 両方のファイルのコードをテンプレートにコピーします。
-
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages:
- {...}
- files:
- /var/www/html/index.php:
- {...}
- /etc/cfn/cfn-hup.conf:
- content: !Sub |
- [main]
- stack=${AWS::StackId}
- region=${AWS::Region}
- interval=1
- mode: 000400
- owner: root
- group: root
- /etc/cfn/hooks.d/cfn-auto-reloader.conf:
- content: !Sub |
- [cfn-auto-reloader-hook]
- triggers=post.update
- path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
- action=/opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
- runas=root
- services:
- {...}
- :::
-
-1. テンプレートの `services` セクションで `cfn-hup` を有効にして起動します。
-
- `services` キーのコードをテンプレートに追加します。
-
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages:
- {...}
- files:
- /var/www/html/index.php:
- {...}
- /etc/cfn/cfn-hup.conf:
- {...}
- /etc/cfn/hooks.d/cfn-auto-reloader.conf:
- {...}
- services:
- sysvinit:
- httpd:
- enabled: true
- ensureRunning: true
- cfn-hup:
- enabled: true
- ensureRunning: true
- files:
- - /etc/cfn/cfn-hup.conf
- - /etc/cfn/hooks.d/cfn-auto-reloader.conf
- :::
-
-#### 4. cfn-signal の設定と CreationPolicy 属性の追加
-
-最後に、全てのサービス (Apache や cfn-hup など) が起動し終えたことを CloudFormation に伝える仕組みが必要です。スタックのリソースの作成完了だけでは、完了ではありません。
-
-別の言い方をすると、AWS CloudFormation はスタックの全てのリソースを作成したら、スタックのステータスを _CREATE\_COMPLETE_ にします。すなわち、インスタンスの中のサービスが失敗しても、 _CREATE\_COMPLETE_ になります。
-
-これを防ぐにはインスタンスに [CreationPolicy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-creationpolicy.html) 属性を追加できます。
-作成ポリシーと併せて、`cfn-signal` ヘルパースクリプトを実行して、すべてのアプリケーションがインストールされ設定されると、AWS CloudFormation に通知します。
-
-1. `WebServerInstance` リソースに `CreationPolicy` プロパティを追加します。
-
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- CreationPolicy:
- ResourceSignal:
- Count: 1
- Timeout: PT10M
- :::
-
-1. `cfn-signal` を UserData パラメータに追加します。
-
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- UserData:
- Fn::Base64:
- !Sub |
- #!/bin/bash -xe
- # Update aws-cfn-bootstrap to the latest
- yum install -y aws-cfn-bootstrap
- # Call cfn-init script to install files and packages
- /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
- # Call cfn-signal script to send a signal with exit code
- /opt/aws/bin/cfn-signal --exit-code $? --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
- :::
-
-#### 5. スタックの作成
-スタックを更新して `UserData` プロパティで行った変更を適用するには、EC2 インスタンスを置き換える必要があります。
-[こちら](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html?shortFooter=true#aws-properties-ec2-instance-properties)で EC2 インスタンスの置き換えをトリガーする属性を確認できます。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body`、`--capabilities` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-helper-scripts \
---template-body file://helper-scripts.yaml \
---capabilities CAPABILITY_IAM
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-helper-scripts/96d87030-e809-11ed-a82c-0eb19aaeb30f"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-1. インスタンスが正常に作成されたことを確認するために、Web ブラウザで `WebsiteURL` を入力します (WebsiteURL は CloudFormation コンソールの _Outputs_ タブから取得できます)。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. `helper-scripts.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックの名前** (例: `cfn-workshop-helper-scripts`) を入力し、**次へ** をクリックします。
-1. **Amazon Machine Image ID** はそのままにしてください。
-1. **EnvironmentType** にはドロップダウンから環境の種類を選択します。例えば **Test** を選択して、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。** の文言のチェックボックスにチェックを入れます。**送信** をクリックします。
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-1. インスタンスが正常に作成されたことを確認するために、Web ブラウザで `WebsiteURL` を入力します (WebsiteURL は CloudFormation コンソールの _Outputs_ タブから取得できます)。
-::::
-:::::
-
-#### チャレンジ
-
-このチャレンジでは、スタックを更新したときに `cfn-hup` がアプリケーションを更新する方法を証明します。AMI ID を表示するように `index.php` ファイルを更新します。
-
-##### 1. `index.php` ファイルの変更
-
-EC2 メタデータの _files_ セクションにある `/var/www/html/index.php` を探してください。
-
-以下のコードを `<\?php {...} ?>` ブロックに追加します。
-
-:::code{language=php showLineNumbers=false showCopyAction=true}
-# Get the instance AMI ID and store it in the $ami_id variable
-$url = "http://169.254.169.254/latest/meta-data/ami-id";
-$ami_id = file_get_contents($url);
-:::
-
-以下のコードを html `` タグに追加してください。
-
-:::code{language=html showLineNumbers=false showCopyAction=true}
-AMI ID:
-:::
-
-##### 2. 新しいテンプレートでスタックを更新
-
-`cfn-hup` はメタデータセクションの変更を検出し、新しいバージョンを自動的にデプロイし、既存のインスタンスを更新します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを更新します。必要な `--stack-name`、`--template-body`、`--capabilities` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-helper-scripts \
---template-body file://helper-scripts.yaml \
---capabilities CAPABILITY_IAM
-:::
-1. `update-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-helper-scripts/96d87030-e809-11ed-a82c-0eb19aaeb30f"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。新しい EC2 インスタンスが作成されないので、すぐ終わるはずです。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-helper-scripts/96d87030-e809-11ed-a82c-0eb19aaeb30f"
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. スタック名 (例: `cfn-workshop-helper-scripts`) をクリックします。
-1. 画面右上の **更新** ボタンをクリックします。
-1. **テンプレートの準備** で、**既存テンプレートを置き換える** を選択します。
-1. **テンプレートの指定** で、 **テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** ボタンをクリックし、作業用ディレクトリに移動します。
-1. `helper-scripts.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **Amazon Machine Image ID** はそのままにしてください。
-1. **EnvironmentType** は選択されている環境のままにします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** ページで、一番下までスクロールし、**AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。** チェックボックスをチェックし、**送信** をクリックします。
-1. ステータスが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-
-##### 3. 変更が正常に展開されたことを確認
-
-プライベートモードで新しいブラウザウィンドウを開き、`WebsiteURL` を入力します (WebsiteURL は CloudFormation コンソールの _Outputs_ タブから取得できます)。下の図のように、AMI ID がページに追加されているはずです。
-
-
-
-### クリーンアップ
-
-作成したリソースをクリーンアップするには、次の手順を実施します。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** で、このラボで作成したスタックを選択します (例: `cfn-workshop-helper-scripts`)。
-1. 右上の **削除** をクリックします。
-1. ポップアップウィンドウで、**削除** をクリックします。
-1. **DELETE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
----
-### まとめ
-
-おめでとうございます! CloudFormation ヘルパースクリプトを使用して EC2 インスタンスを正常にブートストラップしました。
diff --git a/content/basics/operations/helper-scripts/index.md b/content/basics/operations/helper-scripts/index.md
deleted file mode 100644
index 86e217194..000000000
--- a/content/basics/operations/helper-scripts/index.md
+++ /dev/null
@@ -1,401 +0,0 @@
----
-title: "Helper scripts"
-weight: 400
----
-
-_Lab Duration: ~15 minutes_
-
----
-
-### Overview
-In this lab we will look into CloudFormation [Helper Scripts](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-helper-scripts-reference.html).
-What you have learned in a previous lab is a great starting point. However, as you may notice from your `UserData`
-example, procedural scripting is not ideal. You have deployed a simple PHP application, but imagine trying to write much
-more complicated app in userdata. That would be very tricky.
-
-To solve this problem, CloudFormation provides helper scripts. These helper scripts make CloudFormation a lot more
-powerful and enable you to fine tune templates to better fit your use case. For example, you can update application
-configuration without recreating an instance.
-
-The helper scripts come pre-installed on Amazon Linux and can be updated periodically by using `yum install -y aws-cfn-bootstrap`
-
-### Topics Covered
-
-In this lab you will learn:
-
-+ How to retrieve and interpret resource metadata, install packages, create files, and start services with [cfn-init](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-init.html)
-
-+ How to check for updates to metadata and execute custom hooks when changes are detected with [cfn-hup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-hup.html)
-
-+ How to send a signal to CloudFormation when the resource or application is ready with [cfn-signal](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-signal.html)
-
-
-### Start Lab
-
-1. Go to the `code/workspace` directory.
-1. Open the `helper-scripts.yaml` file.
-1. Copy the code as you go through the topics below.
-
-#### 1. Configure _Metadata_ section
-
-You need to use the `AWS::CloudFormation::Init` type to include metadata for an Amazon EC2 instance. When your template
-calls the `cfn-init` script, the script will look for resources in metadata section. Let's add the metadata to your template:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
- WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
-:::
-
-#### 2. Configure cfn-init
-The configuration of `cfn-init` is separated into sections. The configuration sections are processed in the following
-order: packages, groups, users, sources, files, commands, and then services.
-
-:::alert{type="info"}
-If you require a different order, separate your sections into different config keys, and then use a
-[configset](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html?shortFooter=true#aws-resource-init-configsets)
-that specifies the order in which the config keys should be processed.
-:::
-
-:::alert{type="info"}
-It is important to preserve indentation as shown in the code samples below. You can cross-reference your template
-against the solution code `code/solutions/helper-scripts.yaml` file.
-:::
-
-##### 1. Install HTTPD and PHP packages
-
-Your instance is running Amazon Linux 2, so you will use `yum` package manager to install the packages.
-
-Add the code from `packages` key to your template.
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages:
- yum:
- httpd: []
- php: []
-:::
-
-##### 2. Create `index.php` file
-Use the _files_ key to create files on the EC2 instance. The content can either be a specified inline in the template,
-or as a URL that is retrieved by the instance.
-
-Add the code from `files` key to your template.
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages: \
- {...}
- files:
- /var/www/html/index.php:
- content: |
-
-
-
-
-
- EC2 Instance ID:
- Availability Zone:
-
-
-
- mode: 000644
- owner: apache
- group: apache
-:::
-
-##### 3. Enable and start Apache web server
-
-You can use the `services` key to define which services should be enabled or disabled when the instance is launched. On
-Linux systems, this key is supported by using the `sysvinit` key.
-
-Add the code from `services` key to your template.
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages:
- {...}
- files:
- {...}
- services:
- sysvinit:
- httpd:
- enabled: true
- ensureRunning: true
-:::
-
-##### 4. Call `cfn-init` script
-
-The metadata scripts are not executed by default, you need to call `cfn-init` helper script in UserData section to execute it.
-
-In the code below, CloudFormation will first update the `aws-cfn-bootstrap` package to retrieve the latest version of the
-helper scripts. Then, it will install the files and packages from metadata.
-
-Add the code from `UserData` property to your template.
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-UserData:
- Fn::Base64:
- !Sub |
- #!/bin/bash -xe
- # Update aws-cfn-bootstrap to the latest
- yum install -y aws-cfn-bootstrap
- # Call cfn-init script to install files and packages
- /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
-:::
-
-::alert[The intrinsic function `!Sub` will dynamically replace values in `${AWS::StackName}` and `${AWS::Region}` variables.]{type="info"}
-
-#### 3. Configure cfn-hup
-
-Installing the `cfn-hup` helper script enables existing EC2 instances to apply template updates of _UserData_.
-For example, you could change the sample PHP application in the template and deploy this by updating the existing stack.
-Without using `cfn-hup`, you would need to either replace the EC2 instance or manually apply the update outside of
-CloudFormation. (To see this in action, please refer to the exercise section of this lab.)
-
-1. Add two files to the `files` section of the `AWS::CloudFormation::Init`:
-
- + /etc/cfn/cfn-hup.conf
- + /etc/cfn/hooks.d/cfn-auto-reloader.conf
-
-1. Copy the code from both files to your template.
-
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages:
- {...}
- files:
- /var/www/html/index.php:
- {...}
- /etc/cfn/cfn-hup.conf:
- content: !Sub |
- [main]
- stack=${AWS::StackId}
- region=${AWS::Region}
- interval=1
- mode: 000400
- owner: root
- group: root
- /etc/cfn/hooks.d/cfn-auto-reloader.conf:
- content: !Sub |
- [cfn-auto-reloader-hook]
- triggers=post.update
- path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
- action=/opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
- runas=root
- services:
- {...}
- :::
-
-1. Enable and start `cfn-hup` in `services` section of the template.
-
- Add the code from `services` key to your template.
-
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- WebServerInstance:
- Type: AWS::EC2::Instance
- Metadata:
- AWS::CloudFormation::Init:
- config:
- packages:
- {...}
- files:
- /var/www/html/index.php:
- {...}
- /etc/cfn/cfn-hup.conf:
- {...}
- /etc/cfn/hooks.d/cfn-auto-reloader.conf:
- {...}
- services:
- sysvinit:
- httpd:
- enabled: true
- ensureRunning: true
- cfn-hup:
- enabled: true
- ensureRunning: true
- files:
- - /etc/cfn/cfn-hup.conf
- - /etc/cfn/hooks.d/cfn-auto-reloader.conf
- :::
-
-#### 4. Configure cfn-signal and CreationPolicy attribute
-Finally, you need a way to instruct AWS CloudFormation to complete stack creation only after all the services
-(such as Apache and cfn-hup) are running and not after all the stack resources are created.
-
-In other words, AWS CloudFormation sets the status of the stack as _CREATE\_COMPLETE_ after it successfully creates all
-the resources. However, if one or more services failed to start, AWS CloudFormation still sets the stack status as _CREATE\_COMPLETE_.
-
-To prevent this you can add a [CreationPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-creationpolicy.html)
-attribute to the instance. In conjunction with the creation policy, you need to run the `cfn-signal` helper script to
-notify AWS CloudFormation when all the applications are installed and configured.
-
-1. Add Creation policy to `WebServerInstance` resource property.
-
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- CreationPolicy:
- ResourceSignal:
- Count: 1
- Timeout: PT10M
- :::
-
-1. Add the `cfn-signal` to the UserData parameter.
-
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- UserData:
- Fn::Base64:
- !Sub |
- #!/bin/bash -xe
- # Update aws-cfn-bootstrap to the latest
- yum install -y aws-cfn-bootstrap
- # Call cfn-init script to install files and packages
- /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
- # Call cfn-signal script to send a signal with exit code
- /opt/aws/bin/cfn-signal --exit-code $? --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
- :::
-
-#### 5. Create the stack
-Similar to previous labs, create the stack with the updated template. Once CloudFormation completes creating the stack,
-you can then check to see that your script has set up a web server on the EC2 instance.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
- 1. In the **Code Editor terminal** navigate to `code/workspace`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace
- :::
- 1. Use the AWS CLI to create the stack. The required parameters `--stack-name`, `--template-body` and `--capabilities` have been pre-filled for you.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack --stack-name cfn-workshop-helper-scripts \
- --template-body file://helper-scripts.yaml \
- --capabilities CAPABILITY_IAM
- :::
- 1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-helper-scripts/96d87030-e809-11ed-a82c-0eb19aaeb30f"
- :::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and wait for stack status to reach **CREATE_COMPLETE**. You need to periodically select Refresh to see the latest stack status.
- 1. Verify the new instance was deployed and is functional. In a web browser, enter the `WebsiteURL` (you can get the WebsiteURL from the _Outputs_ tab of the CloudFormation console).
-::::
-::::tab{id="local" label="Local development"}
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. In the CloudFormation console, select *Create stack With new resources (standard)*.
-1. In **Prepare template**, select **Template is ready**.
-1. In **Template source**, select **Upload a template file**.
-1. Select the file `helper-scripts.yaml` and click **Next**.
-1. Enter a **Stack name**. For example, choose to specify `cfn-workshop-helper-scripts`.
-1. For **Amazon Machine Image ID** leave the default value in.
-1. For **EnvironmentType** select the environment from drop down list, for example **Test** and click **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and tick **I acknowledge that AWS CloudFormation might create IAM resources** check box, then click on **Submit**.
-1. Wait for stack status to reach **CREATE_COMPLETE**. You need to periodically select Refresh to see the latest stack status.
-1. Verify the new instance was deployed and is functional. In a web browser, enter the `WebsiteURL` (you can get the WebsiteURL from the _Outputs_ tab of the CloudFormation console).
-::::
-:::::
-
-#### Challenge
-
-This exercise will demonstrate how `cfn-hup` updates the application when you update the stack. You will update `index.php` file
- to show AMI ID on the page.
-
-##### 1. Modify `index.php` file
-
-Locate the `/var/www/html/index.php` in the _files_ section of the EC2 metadata
-
-Add the code below to the `<\?php {...} ?>` block:
-
-:::code{language=php showLineNumbers=false showCopyAction=true}
-# Get the instance AMI ID and store it in the $ami_id variable
-$url = "http://169.254.169.254/latest/meta-data/ami-id";
-$ami_id = file_get_contents($url);
-:::
-
-Add the code below to html `` tags:
-
-:::code{language=html showLineNumbers=false showCopyAction=true}
-AMI ID:
-:::
-
-##### 2. Update the stack with a new template:
-
-`cfn-hup` will detect changes in metadata section, and will automatically deploy the new version, updating the current EC2 instance.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. Use the AWS CLI to update the stack. The required parameters have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-helper-scripts \
---template-body file://helper-scripts.yaml \
---capabilities CAPABILITY_IAM
-:::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-helper-scripts/96d87030-e809-11ed-a82c-0eb19aaeb30f"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and wait for stack status to reach **UPDATE_COMPLETE**. You need to periodically select Refresh to see the latest stack status. This should be quick as a new EC2 instance is not being launched.
-::::
-::::tab{id="local" label="Local development"}
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. Click on the stack name, for example `cfn-workshop-helper-scripts`.
-1. In the top right corner click on **Update**.
-1. In **Prepare template**, choose **Replace current template**.
-1. In **Template source**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the file `helper-scripts.yaml` and click **Next**.
-1. For **Amazon Machine Image ID** leave the default value in.
-1. For **EnvironmentType** leave the selected environment in.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and tick **I acknowledge that AWS CloudFormation might create IAM resources** check box, then click on **Submit**.
-1. Wait for stack status to reach **UPDATE_COMPLETE**. You need to periodically select Refresh to see the latest stack status.
-::::
-:::::
-
-##### 3. Verify that changes have been deployed successfully
-
-Open a new browser window in private mode and enter the `WebsiteURL` (you can get the WebsiteURL from the _Outputs_ tab of the CloudFormation console).
-You should see the AMI ID added to the page, similar to the picture below.
-
-
-
-### Clean up
-
-Follow these steps to clean up created resources:
-
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the stack you have created in this lab. For example `cfn-workshop-helper-scripts`.
-1. In the top right corner, click on **Delete**.
-1. In the pop-up window click on **Delete**.
-2. Wait for the stack to reach the **DELETE_COMPLETE** status. You need to periodically select Refresh to see the latest stack status.
-
----
-
-### Conclusion
-
-Congratulations, you have successfully bootstrapped an EC2 instance using CloudFormation Helper Scripts.
diff --git a/content/basics/operations/index.ja.md b/content/basics/operations/index.ja.md
deleted file mode 100644
index 3e03e2f02..000000000
--- a/content/basics/operations/index.ja.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: "オペレーション"
-weight: 20
----
-
-
-
-前の章では、CloudFormation の基礎とさまざまな _テンプレート_ のセクションについて学びました。
-
-Elastic IP を使用して EC2 インスタンスを作成する単純なシナリオを体験しました。
-
-この章では、既存のテンプレートを以下の機能で改善します。
-
-+ Systems Manager Parameter Store を使用して、最新の Amazon Linux 2 AMI を任意のリージョンにデプロイします。
-+ IAM ロールをインスタンスにアタッチし、SSM Session Manager を使用してインスタンスにログインします。
-+ _UserData_ スクリプトを使用してインスタンスをブートストラップします。
-+ `cfn-init` を使用して EC2 インスタンスのブートストラップを支援します。
-
----
-
-### ワークショップでカバーするトピック:
-
-::children
diff --git a/content/basics/operations/index.md b/content/basics/operations/index.md
deleted file mode 100644
index 1d61e8641..000000000
--- a/content/basics/operations/index.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: "Operations"
-weight: 20
----
-
-
-
-In the previous chapter, you learnt the CloudFormation fundamentals and about various _Template_ sections.
-
-You have created an EC2 instance with Elastic IP. This is a simplistic scenario.
-
-In this chapter you will improve the existing template with the following features:
-
-+ Use Systems Manager Parameter Store to deploy the latest Amazon Linux 2 AMI in any region.
-+ Attach an IAM role to the instance and login to it using SSM Session Manager.
-+ Bootstrap the instance using a _UserData_ script.
-+ Use `cfn-init` to assist bootstrapping an EC2 instance.
-
----
-
-### Workshop topics covered:
-
-::children
diff --git a/content/basics/operations/multi-region-latest-ami/index.ja.md b/content/basics/operations/multi-region-latest-ami/index.ja.md
deleted file mode 100644
index c3fd368b5..000000000
--- a/content/basics/operations/multi-region-latest-ami/index.ja.md
+++ /dev/null
@@ -1,122 +0,0 @@
----
-title: "マルチリージョンの最新の AMI"
-weight: 100
----
-
-_ラボ実施時間 : 10分程度_
-
----
-
-### 概要
-現在のテンプレートをさまざまなリージョンにデプロイするユースケースを考えてみましょう。各 AWS リージョンの AMI ID と一致するために、 手動で `AmiId` を変更する必要があります。同じく、Amazon Machine Image にアップデートがある場合、最新のイメージを使用するために、同じ手動処理が発生します。
-
-これを解決するには、CloudFormation テンプレートの既存の _Parameters_ セクションを使用して、System Manager パラメータータイプを定義します。Systems Manager パラメータタイプを使用すると、Systems Manager Parameter Store に保持されているパラメータを参照できます。
-
-### カバーするトピック
-このラボでは、次のことを学びます。
-
-+ CloudFormation で **[AWS Systems Manager Parameter Store](https://aws.amazon.com/jp/blogs/news/query-for-the-latest-amazon-linux-ami-ids-using-aws-systems-manager-parameter-store/)** から最新の Amazon Linux AMI ID を取得する方法。
-
-### ラボの開始
-
-1. `code/workspace` ディレクトリに移動します。
-1. `multi-region-latest-ami.yaml` ファイルを開きます。
-1. `AmiID` パラメータを次のように更新します。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-AmiID:
- Type: AWS::SSM::Parameter::Value
- Description: The ID of the AMI.
- Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
-:::
-
-AWS コンソールに移動し、新しいテンプレートでスタックを更新します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-multi-region-latest-ami \
---template-body file://multi-region-latest-ami.yaml
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-multi-region-latest-ami/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
-1. `multi-region-latest-ami.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックの名前** (例: `cfn-workshop-multi-region-latest-ami`) を入力し、**次へ** をクリックします。
-1. **Amazon Machine Image ID** には `/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2` をコピーします。
-1. **EnvironmentType** にはドロップダウンから環境の種類を選択します。例えば **Test** を選択して、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**送信** をクリックします。
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-
-### チャレンジ
-使用していたものとは別のAWSリージョンにテンプレートをデプロイします。
-
-::::::expand{header="解決策を確認しますか?"}
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。`--region` パラメータは最初にスタックを作成したリージョン以外のリージョンを指定します。例えば、最初に `us-east-1` で作成されていたら、 `us-east-2` を指定します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-multi-region-latest-ami \
---template-body file://multi-region-latest-ami.yaml \
---region us-east-2
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-2:123456789012:stack/cfn-workshop-multi-region-latest-ami/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上のリージョン名 (例: **バージニア北部**) をクリックし、別のリージョンを選択します。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
-1. `multi-region-latest-ami.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックの名前** (例: `cfn-workshop-multi-region-latest-ami`) を入力し、**次へ** をクリックします。
-1. **Amazon Machine Image ID** には `/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2` をコピペします。
-1. **EnvironmentType** にはドロップダウンから環境の種類を選択します。例えば **Test** を選択して、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**送信** をクリックします。
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-:::alert{type="info"}
-AMI ID パラメータを更新する必要がなかったことに注意してください。Systems Manager Parameter Store を利用し CloudFormation をインテグレーションすることで、テンプレートがより汎用的で再利用可能になりました。
-:::
-::::::
-
-### クリーンアップ
-以下の手順の通りに、このラボで作成した [スタックの削除](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html) を行ってください。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** に移動します。
-1. CloudFormation の **スタック** ページで `cfn-workshop-multi-region-latest-ami` を選択します。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-1. CloudFormation のスタックを作成した全てのリージョンで上記の手順を切り返します。
-
----
-### まとめ
-
-おめでとうございます!これで、最新の Amazon Linux AMI を使用するようにテンプレートを正常に更新できました。さらに、テンプレートは、AMI ID パラメータを追加しなくても、どのリージョンにもデプロイできるようになりました。
diff --git a/content/basics/operations/multi-region-latest-ami/index.md b/content/basics/operations/multi-region-latest-ami/index.md
deleted file mode 100644
index ee686dc74..000000000
--- a/content/basics/operations/multi-region-latest-ami/index.md
+++ /dev/null
@@ -1,115 +0,0 @@
----
-title: "Multi region latest AMI"
-weight: 100
----
-
-_Lab Duration: ~10 minutes_
-
----
-
-### Overview
-Consider the use case of deploying your current template in different regions. You would need to manually change `AmiID`
-property in your template to match the AMI ID for each AWS Region. Similarly, if there is an update to the Amazon Machine
-Image, and you would like to use the latest image, the same manual process would apply.
-
-To fix this, you can use the existing _Parameters_ section of your CloudFormation template and define Systems Manager parameter
-type. A Systems Manager parameter type allows you to reference parameters held in the System Manager Parameter Store.
-
-### Topics Covered
-In this Lab, you will learn:
-
-+ How to query **[AWS Systems Manager Parameter Store](https://aws.amazon.com/blogs/compute/query-for-the-latest-amazon-linux-ami-ids-using-aws-systems-manager-parameter-store/)** in CloudFormation to get the latest Amazon Linux AMI ID.
-
-### Start Lab
-
-1. Go to the `code/workspace` directory.
-1. Open the `multi-region-latest-ami.yaml` file.
-1. Update the `AmiID` parameter to:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-AmiID:
- Type: AWS::SSM::Parameter::Value
- Description: The ID of the AMI.
- Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
-:::
-
-Go to the AWS console and create the stack with a new template.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-multi-region-latest-ami \
---template-body file://multi-region-latest-ami.yaml
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-multi-region-latest-ami/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Choose **Create stack (With new resources (Standard))** from the top-right side of the page.
-1. In **Prepare template**, choose **Template is ready**.
-1. In **Template source**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the file `multi-region-latest-ami.yaml` and click **Next**.
-1. Provide a **Stack name**. For example `cfn-workshop-multi-region-latest-ami`.
-1. For **Amazon Machine Image ID** copy and paste in `/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2`
-1. For **EnvironmentType** select the environment from drop down list, for example **Test** and click **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and click on **Submit**.
-1. You can click the **refresh** button a few times until you see in the status **CREATE_COMPLETE**.
-::::
-:::::
-
-### Challenge
-Deploy the template in different AWS Region to the one you have been using.
-
-::::::expand{header="Solution"}
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you.
-Change the value of `--region` flag to the different region you have created your first stack in. For example, if you created the first stack in `us-east-1` change region to `us-east-2`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-multi-region-latest-ami \
---template-body file://multi-region-latest-ami.yaml \
---region us-east-2
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-2:123456789012:stack/cfn-workshop-multi-region-latest-ami/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-
-::::
-:::::
-:::alert{type="info"}
-Notice, that you did not have to update AMI ID parameter. By using CloudFormation's integration with Systems
-Manager Parameter Store, your templates are now more generic and reusable.
-:::
-::::::
-
-### Cleanup
-Follow the steps below to [delete the stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html) you created as a part of this lab:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. On the **Stacks** page in the CloudFormation console, select the `cfn-workshop-multi-region-latest-ami` stack.
-1. In the stack details pane, choose **Delete** to delete the stack, and then choose **Delete** to confirm.
-1. Repeat above steps for all the regions you have used to deploy CloudFormation stacks in.
-
----
-### Conclusion
-
-Congratulations! You have now successfully updated your template to use the latest Amazon Linux AMI. Furthermore, your
-template can now be deployed in any region, without appending AMI ID parameter.
diff --git a/content/basics/operations/session-manager/index.ja.md b/content/basics/operations/session-manager/index.ja.md
deleted file mode 100644
index 9702ad251..000000000
--- a/content/basics/operations/session-manager/index.ja.md
+++ /dev/null
@@ -1,150 +0,0 @@
----
-title: "Session Manager"
-weight: 200
----
-
-_ラボ実施時間 : 15分程度_
-
----
-
-### 概要
-
-[Session Manager](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager.html) はインタラクティブなワンクリックのブラウザベースのターミナルまたは AWS CLI を使用して Amazon EC2 インスタンスを管理できる AWS Systems Manager のフルマネージド機能です。
-
-Session Manager には SSH を使用するよりいくつかの利点があります。
-
-+ SSH キーを管理する必要はありません。
-+ セキュリティグループのインバウンドポートを開く必要はありません。
-+ IAM ポリシーとユーザーを使用して、インスタンスへのアクセスを制御できます。
-+ コマンドとレスポンスは Amazon CloudWatch と S3 バケットに記録できます。
-
-#### セッションマネージャーの仕組み
-
-1. 管理者は IAM に対して認証を行います。
-1. IAM は、適用可能な IAM ポリシーを評価して EC2 インスタンスでセッションを開始することを承認します。
-1. 管理者は AWS マネジメントコンソールまたはターミナル (AWS CLI と追加のプラグインが必要) を使用して、Systems Manager からセッションを開始します。
-1. EC2 インスタンスで実行されている Systems Manager Agent は、AWS Systems Manager に接続し、インスタンスでコマンドを実行します。
-1. Session Manager は CloudWatch Logs または S3 に監査ログを送信します。
-
-::alert[Session Manager が機能するには、EC2 インスタンスがインターネットにアクセスするか、VPC エンドポイントにアクセスする必要があります。]{type="info"}
-
-
-
-### カバーするトピック
-このラボでは次のことを学びます。
-
-+ AWS Systems Manager へのアクセスを許可する EC2 インスタンス用の IAM ロールを作成する方法。
-+ IAM ロールを EC2 インスタンスにアタッチ。
-+ SSM Session Manager を使用してインスタンスにログイン。
-
-### ラボの開始
-
-1. `code/workspace` ディレクトリに移動します。
-1. `session-manager.yaml` ファイルを開きます。
-1. 以下のトピックを進めながら、コードをコピーしてください。
-
-#### 1. EC2 インスタンスに AWS Systems Manager Agent のインストール
-
-SSM Agent は Amazon Linux AMI にあらかじめインストールされているので、次のステップに進むことができます。他のオペレーティングシステムの場合は、AWS ドキュメントの [SSM Agent の使用](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ssm-agent.html) を参照してください。
-
-#### 2. EC2 インスタンスの IAM ロールの作成
-`AmazonSSMManagedInstanceCore` というAWS 管理のポリシーでは、インスタンスが AWS Systems Manager サービスのコア機能の使用を許可しています。Systems Manager Session Manager を使用して EC2 インスタンスに接続できるように利用できます。
-
-```yaml
-SSMIAMRole:
- Type: AWS::IAM::Role
- Properties:
- AssumeRolePolicyDocument:
- Statement:
- - Effect: Allow
- Principal:
- Service:
- - ec2.amazonaws.com
- Action:
- - sts:AssumeRole
- ManagedPolicyArns:
- - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
-```
-
-#### 3. IAM インスタンスプロファイルの作成
-
-インスタンスプロファイルリソースを作成します。
-
-```yaml
-WebServerInstanceProfile:
- Type: AWS::IAM::InstanceProfile
- Properties:
- Path: /
- Roles:
- - !Ref SSMIAMRole
-```
-
-#### 4. IAM インスタンスプロファイルを Amazon EC2 インスタンスにアタッチ
-
-`IAMInstanceProfile` プロパティを使用してロールをインスタンスにアタッチします。
-
-```yaml
-WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- IamInstanceProfile: !Ref WebServerInstanceProfile
- ImageId: !Ref AmiID
- InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref EnvironmentType, InstanceType]
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref EnvironmentType, webserver ] ]
-```
-
-::alert[インスタンスプロファイルは、新しい Amazon EC2 インスタンスの起動時にアタッチすることも、既存の Amazon EC2 インスタンスにアタッチすることもできます。]{type="info"}
-
-#### 5. スタックの更新
-
-AWS コンソールに移動し、新しいテンプレートでスタックを更新します。
-
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. スタック名 (例: **cfn-workshop-ec2**) をクリックします。
-1. 画面右上の **更新** ボタンをクリックします。
-1. **テンプレートの準備** で、**既存テンプレートを置き換える** を選択します。
-1. **テンプレートの指定** で、 **テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** ボタンをクリックし、作業用ディレクトリに移動します。
-1. `session-manager.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **Amazon Machine Image ID** はそのままにしてください。
-1. **EnvironmentType** には、リストされているものとは異なる環境を選択します。たとえば、**Dev** が選択されている場合は、**Test** を選択し、**次へ** をクリックします。
-:::alert{type="info"}
-System Manager が機能するには、インスタンスが次の条件を満たす必要があります。 \
- \- **インターネットまたは VPC エンドポイントへのアクセス。** \
- \- **ロールには正しい権限が付与されています。** \
-環境を変更すると、インスタンスは停止し、再起動します。以前のラボではロールが割り当てられていなかったため、`ssm-agent` の起動するタイムアウトした可能性のあるので、再起動が役に立ちます。
-:::
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** ページで、一番下までスクロールし、**AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。** チェックボックスをチェックし、**スタックの更新** をクリックします。
-1. ステータスが **UPDATE_COMPLETE** になるまで、**リフレッシュ** ボタンを数回クリックします。
-
-### チャレンジ
-
-SSM Session Manager を使用してインスタンスにログインし、`curl` を使用してインスタンスメタデータから AMI ID を取得します。
-
-::expand[ [インスタンスメタデータとユーザーデータ](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) に関する AWS ドキュメントを確認してください。]{header="ヒントが必要ですか?"}
-
-:::expand{header="解決策を確認しますか?"}
-次のコマンドをインスタンスターミナル内に貼り付けます。
-
-::code[curl http://169.254.169.254/latest/meta-data/ami-id]{language=shell showLineNumbers=false showCopyAction=true}
-:::
-
-:::alert{type="warning"}
-このワークショップ以外にも、SSM Session Manager へのアクセスを設定する際には、環境の保護のために追加の手順を実行する必要があります。詳細は以下の推薦事項のドキュメントのリンクをご参照ください。
-:::
-
-##### 推奨事項
-
-+ IAM ポリシーを使用して、EC2 インスタンスでセッションを開始できる IAM ユーザーまたはロールを制限します。
-+ ログを監査するように Amazon CloudWatch Logs または S3 バケットを設定します。
-+ IAM ポリシーを使用して、IAM ユーザーが監査ログ設定を変更できないようにします。
-
-[AWS Systems Manager のセットアップ](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-setting-up.html) ドキュメントをご参照ください。
-
----
-### まとめ
-
-おめでとうございます!Session Manager の設定を完了し、EC2 インスタンスにリモートアクセスできるようになりました。
diff --git a/content/basics/operations/session-manager/index.md b/content/basics/operations/session-manager/index.md
deleted file mode 100644
index 881903044..000000000
--- a/content/basics/operations/session-manager/index.md
+++ /dev/null
@@ -1,160 +0,0 @@
----
-title: "Session manager"
-weight: 200
----
-
-_Lab Duration: ~15 minutes_
-
----
-
-### Overview
-
-[Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html) is a fully managed
-AWS Systems Manager capability that lets you manage your Amazon EC2 instances through an interactive one-click browser-based terminal or via the AWS CLI.
-
-Session Manager has several benefits over using SSH:
-
-+ No need to manage SSH keys.
-+ No need to open up any inbound ports in Security Groups.
-+ You can use IAM policies and users to control access to your instances.
-+ Commands and responses can be logged to Amazon CloudWatch and to an S3 bucket.
-
-#### How Session Manager works
-
-1. The administrator authenticates against IAM.
-1. IAM authorizes to start a session on an EC2 instance by evaluating applicable IAM policies.
-1. The administrator uses the AWS Management Console or the terminal (AWS CLI and additional plugin required) to
- start a session via Systems Manager.
-1. The Systems Manager agent running on the EC2 instance connects to the AWS Systems Manager service
- and executes the commands on the instance.
-1. The Session Manager sends audit logs to CloudWatch Logs or S3.
-
-::alert[The EC2 instance needs access to the internet, or a VPC Endpoint for Session Manager to work.]{type="info"}
-
-
-
-### Topics Covered
-In this Lab, you will learn:
-
-+ How to create IAM role for the EC2 instance which grants access to the AWS Systems Manager.
-+ Attach the IAM role to the EC2 instance.
-+ Log in to instance using SSM Session Manager.
-
-### Start Lab
-
-1. Go to the `code/workspace` directory.
-1. Open the `session-manager.yaml` file.
-1. Copy the code as you go through the topics below.
-
-#### 1. Install the AWS Systems Manager agent on EC2 instance
-
-You can proceed to the next step as SSM Agent is pre-installed on Amazon Linux AMIs. For other operating systems, please
-refer to the AWS documentation for [Working with SSM Agent](https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent.html)
-
-#### 2. Create an IAM role for the EC2 instance
-The AWS managed policy, `AmazonSSMManagedInstanceCore`, allows an instance to use AWS Systems Manager service core
-functionality. This will allow you to connect to the EC2 instance using Systems Manager Session Manager.
-
-```yaml
-SSMIAMRole:
- Type: AWS::IAM::Role
- Properties:
- AssumeRolePolicyDocument:
- Statement:
- - Effect: Allow
- Principal:
- Service:
- - ec2.amazonaws.com
- Action:
- - sts:AssumeRole
- ManagedPolicyArns:
- - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
-```
-
-#### 3. Create an IAM Instance Profile
-
-Create Instance profile resource.
-
-```yaml
-WebServerInstanceProfile:
- Type: AWS::IAM::InstanceProfile
- Properties:
- Path: /
- Roles:
- - !Ref SSMIAMRole
-```
-
-#### 4. Attach the IAM Instance Profile to an Amazon EC2 Instance
-
-Attach the role to the instance with `IamInstanceProfile` property.
-
-```yaml
-WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- IamInstanceProfile: !Ref WebServerInstanceProfile
- ImageId: !Ref AmiID
- InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref EnvironmentType, InstanceType]
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref EnvironmentType, webserver ] ]
-```
-
-::alert[You can attach the instance profile to the new Amazon EC2 instances at launch time, or to existing Amazon EC2 instances.]{type="info"}
-
-#### 5. Update the Stack
-
-Go to the AWS console and update your stack with a new template.
-
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. Click on the stack name, for example **cfn-workshop-ec2**.
-1. In the top right corner click on **Update**.
-1. In **Prepare template**, choose **Replace current template**.
-1. In **Template source**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the file `session-manager.yaml` and click **Next**.
-1. For **Amazon Machine Image ID** leave the default value in.
-1. For **EnvironmentType** select the different environment than is listed. For example if you have **Dev** selected, choose **Test** and click **Next**.
-:::alert{type="info"}
-For System Manager to work, the instance need to meet following conditions:
- \- **Access to the internet, or a VPC Endpoint.** \
- \- **Role attached with correct permission.** \
-By changing the environment, instance will be stopped and started again. This will help to start `ssm-agent` which may have timed-out as the role wasn't attached in a previous lab.
-:::
-
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and tick **I acknowledge that AWS CloudFormation might create IAM resources** check box, then click on **Update stack**.
-1. You can click the **refresh** button a few times until you see in the status **UPDATE_COMPLETE**.
-
-### Challenge
-
-Log in to instance using SSM Session Manager and retrieve the AMI ID from instance metadata using `curl`
-
-::expand[Review the AWS documentation for [Instance Metadata and User Data](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html?shortFooter=true#instancedata-data-retrieval).]{header="Need a hint?"}
-
-:::expand{header="Want to see the solution?"}
-Paste the following command inside the instance terminal:
-
-::code[curl http://169.254.169.254/latest/meta-data/ami-id]{language=shell showLineNumbers=false showCopyAction=true}
-
-
-:::
-
-:::alert{type="warning"}
-Outside this workshop you should take additional steps to configure and secure access to SSM Session Manager. See
-recommendations and documentation link below for further details.
-:::
-
-##### Recommendations:
-
-+ Use IAM policies to restrict which IAM user or role can start a session on an EC2 instance.
-+ Configure Amazon CloudWatch Logs and/or S3 bucket to audit logs.
-+ Use IAM policies to make sure IAM users are not able to modify the audit log settings.
-
-Please refer to the [Setting Up AWS Systems Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-setting-up.html)
-documentation.
-
----
-### Conclusion
-
-Congratulations! You have configured Session Manager and now have remote access to your EC2 instance.
diff --git a/content/basics/operations/troubleshooting-provisioning-errors/index.ja.md b/content/basics/operations/troubleshooting-provisioning-errors/index.ja.md
deleted file mode 100644
index f82e141bd..000000000
--- a/content/basics/operations/troubleshooting-provisioning-errors/index.ja.md
+++ /dev/null
@@ -1,193 +0,0 @@
----
-title: "プロビジョニングエラーのトラブルシューティング"
-weight: 500
----
-
-_ラボ実施時間 : 25分程度_
-
----
-
-### 概要
-CloudFormation テンプレートの開発を繰り返す中で、CloudFormation [スタック](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stacks.html) を作成することで、テンプレートに記述されているリソースのプロビジョニングを検証できます。テンプレート内のリソースの構成に誤ったプロパティ値を指定した場合、デフォルトではスタックは最後に確認された安定した状態にロールバックし、すべてのスタックのリソースはロールバックされます。
-
-10 個のリソースを記述したテンプレートの例からスタックの作成を検証してみましょう。この例では、9 つのリソースが正常に作成されますが、10 番目のリソースの作成は失敗します。デフォルトでは、正常にプロビジョニングされた 9 つのリソースを含め、スタックはロールバックされます。
-
-開発サイクルを早めるために、スタックの作成および更新操作、または[変更セット](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html)操作の際に正常にプロビジョニングされたリソースの状態を[保持](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stack-failure-options.html)することが出来ます。この機能を使用すると、スタックのロールバックが一時停止され、正常にプロビジョニングされたリソースの状態を保持します。その状態で設定のトラブルシューティングと修正ができ、準備ができたらプロビジョニング操作を再開できます。
-
-### カバーするトピック
-このラボを修了すると、次のことができるようになります。
-
-* 正常にデプロイされたリソースの状態を保持しながら、プロビジョニングエラーをトラブルシューティングする方法を理解する。
-* [AWS リソースおよびプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)に移動して、特定のリソースのリソースプロパティと戻り値を確認できます。
-
-
-### Start Lab
-サンプルの CloudFormation テンプレートには、誤ったリソース設定が含まれています。これを修正するには、*スタック障害オプション* の一部として *正常にプロビジョニングされたリソースを保存* を選択して、正常にプロビジョニングされるサンプルの `DeadLetterQueue` [Amazon SQS](https://aws.amazon.com/jp/sqs/) キューリソースの状態を保存されるようにします。
-
-テンプレートに別の SQS キューが記述されており、設定エラーがあるため、スタックの作成操作は失敗します。テンプレートのエラーをトラブルシューティングして修正したら、更新されたテンプレートを使用してスタックの作成操作を再開できます。
-
-### ラボの開始
-
-最初は、次の手順を実施してください。
-1. `code/workspace/troubleshooting-provisioning-errors` ディレクトリに移動します。
-1. お気に入りのテキストエディターで `sqs-queues.yaml` CloudFormation テンプレートを開きます。
-1. テンプレート内のサンプル SQS キューの設定をよく確認してください。この例では次のポイントにフォーカスして進みます。
- 1. *ソース* キューと [*デッドレター* キュー](https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html) (DLQ) を作成します。正常に処理できない `SourceQueue` のメッセージが `DeadLetterQueue` に流れるようにします。テンプレートでは、`SourceQueue` の [RedrivePolicy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#cfn-sqs-queue-redrivepolicy) で `DeadLetterQueue` の [Amazon リソースネーム](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference-arns.html) (ARN) を参照します。DLQ が先に作成され、*ソース* キューがその ARN を参照できるようになります。
- 2. この例では、両方のキューを [First-In-First-Out](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#cfn-sqs-queue-fifoqueue) (FIFO) キューとして記述します。*ソース* キューと *デッドレター* [キュー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#cfn-sqs-queue-redrivepolicy)を記述する場合、両方のキューは同じタイプ (*standard* または *FIFO*) でなければなりません (後者はこのラボの例です)。サンプルテンプレートには、`FIFOQueue` プロパティ値に両方のキューに設定すべき `true` ではなく、片方を違う設定にしていることにご注目ください。さらに、FIFO キューを記述する場合、その名前には `.fifo` サフィックスを含める必要があります。`SourceQueue` の `QueueName` には `.fifo` サフィックスが含まれていますが、標準キュー (つまり、`FIFOQueue` が `false` に設定されている) として設定されるため、エラーになります。
-
-前述のエラーを含む `sqs-queues.yaml` テンプレートを使用してスタックのロールバックの一時停止機能を利用し、エラーを修正してスタックの作成を完了させます。
-
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-
-
-1. **Code Editor のターミナル** で `code/workspace/troubleshooting-provisioning-errors` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/troubleshooting-provisioning-errors
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-troubleshooting-provisioning-errors --template-body file://sqs-queues.yaml --disable-rollback
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-troubleshooting-provisioning-errors/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックのステータスが **CREATE_FAILED** ステータスであることを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動し、使用したい [AWS リージョン](https://docs.aws.amazon.com/ja_jp/awsconsolehelpdocs/latest/gsg/select-region.html) を選択します。
-1. 画面の右上の **スタックの作成** プルダウンを開き、**新しいリソースを使用 (標準)** をクリックします。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** ボタンをクリックし、作業用ディレクトリに移動します。前述の `sqs-queues.yaml` テンプレートを選択し、**次へ** を選択します。
-1. スタック名を指定します (例: `cfn-workshop-troubleshooting-provisioning-errors`)。同じページで、`QueueNamePrefix` パラメーターのデフォルト値をそのまま使用し、**次へ** を選択します。
-1. **スタックの失敗オプション** で、**正常にプロビジョニングされたリソースの保持** を選択します。**次へ** を選択します。
-1. 次のページで、ページの下部までスクロールし、**送信** をクリックします。
-1. スタックが `CREATE_FAILED` ステータスになるまで、スタック作成ページを更新します。
-::::
-:::::
-
-前述のエラーが原因で、スタックの作成が失敗しました。リストからスタックの名前を選択します (例: `cfn-workshop-troubleshooting-provisioning-errors`)。**リソース** タブで、`DeadLetterQueue` リソースが `CREATE_COMPLETE` ステータスで、`SourceQueue` リソースが `CREATE_FAILED` ステータスの状態を確認出来ます。また、失敗したリソースの `CREATE_FAILED` メッセージをクリックすると、関連エラーを確認出来ます。
-
-同じスページには、次の図に示すように、次に行うステップを選択できるオプションも表示されます。
-
-
-
-目標は、テンプレートのエラーをトラブルシューティングして修正し、プロビジョニングを再開して `SourceQueue` リソースを作成することです。このプロセスの一環として、先に正常に作成された `DeadLetterQueue` の状態を保持します。次のステップ:
-
-テキストエディターで `sqs-queues.yaml` テンプレートを開き、`SourceQueue` リソースを探し、`FifoQueue: false` を `FifoQueue: true` に変更します。完了したら、変更を保存します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace/troubleshooting-provisioning-errors` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/troubleshooting-provisioning-errors
-:::
-1. AWS CLI でスタックを更新します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-troubleshooting-provisioning-errors --template-body file://sqs-queues.yaml --disable-rollback
-:::
-1. `update-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-troubleshooting-provisioning-errors/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. 前の図に示した **スタックのロールバックが一時停止されました** の枠の中の **更新** ボタンをクリックします。
-1. **テンプレートの準備** で、**既存テンプレートを置き換える** を選択し、更新したテンプレートを設定した上で **次へ** を選択します。
-1. **パラメータ** ページで **次へ** を選択します。
-1. **スタックオプションの設定** ページで、**スタックの失敗オプション** セクションを探します。スタックの作成時に選択した **正常にプロビジョニングされたリソースの保持** オプションは引き続き選択されているはずです。ページを下にスクロールして、**次へ** を選択します。
-1. 次に、**送信** を選択します。
-::::
-:::::
-
-スタックが `UPDATE_COMPLETE` ステータスになるまでページを更新します。スタックの **リソース** タブでは、`SourceQueue` リソースが `CREATE_COMPLETE` ステータスになっているはずです。
-
-::alert[変更不可能な更新タイプ (つまり、置換が必要な[プロパティの値を変更](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html)した場合) はサポートされていません。詳細については、[スタックのロールバックを一時停止する条件](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stack-failure-options.html#stack-failure-options-conditions) をご参照ください。]{type="info"}
-
-おめでとうございます!CloudFormation の一時停止無効化ロールバック機能を使用してプロビジョニングエラーをトラブルシューティングする方法を学びました!
-
-::alert[このラボでは、AWS CloudFormation コンソールを使用してこの機能を学習しました。[AWS Command Line Interface](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-welcome.html) での使用方法については、ドキュメントの [正常にプロビジョニングされたリソースを保持する (AWS CLI)](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stack-failure-options.html#stack-failure-options-cli) をご参照ください。]{type="info"}
-
-### チャレンジ
-`sqs-queues.yaml` テンプレートに 2 つの [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html) パラメータリソースを追加することとします。パラメータごとに、先に作成したキューの ARN を保存することとします。そのためには、`Fn::GetAtt` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html)を使用して、関連する SQS キューリソースの必要な[戻り値](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#aws-resource-sqs-queue-return-values)を取得します。また、各パラメーターの値が ARN であることを検証するために、`AllowedPattern` で定義されている正規表現パターンを定義します。手順は以下の通りです。
-
-* 最初に、次の設定例を `sqs-queues.yaml` テンプレートに追加してください。
-
-```yaml
- DeadLetterQueueParameter:
- Type: AWS::SSM::Parameter
- Properties:
- AllowedPattern: ^arn:aws([-a-z0-9-]*[a-z0-9])*:sqs:[a-z0-9-]+:[0-9]{12}:[a-zA-Z0-9_-]{1,80}(\.fifo){0,1}$
- Description: Parameter for the DeadLetterQueue ARN value
- Name: workshop-example-dead-letter-queue
- Type: String
- Value: !GetAtt DeadLetterQueue.Arn
-
- SourceQueueParameter:
- Type: AWS::SSM::Parameter
- Properties:
- AllowedPattern: ^arn:aws([-a-z0-9-]*[a-z0-9])*:sqs:[a-z0-9-]+:[0-9]{12}:[a-zA-Z0-9_-]{1,80}(\.fifo){0,1}$
- Description: Parameter for the SourceQueue ARN value
- Name: workshop-example-source-queue
- Type: String
- Value: !GetAtt SourceQueue.QueueName
-```
-
-* 変更をファイルに保存します。次に、AWS CloudFormation コンソールを使用して[スタックを更新](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-direct.html)します。その際、**テンプレートの準備** で **既存テンプレートを置き換える** を選択し、更新したテンプレートをアップロードします。**スタックオプションの設定** ページでは、**正常にプロビジョニングされたリソースの保持** オプションが引き続き選択されているはずです。
-* スタックの更新操作は失敗します。スタックの **リソース** タブを見ると、2 つの新しいリソースのうちの 1 つが正常に作成され、もう 1 つは `CREATE_FAILED` ステータスになっているはずです。
-* テンプレートに貼り付けたスニペットのエラーをトラブルシューティングして修正します。
-* スタックの更新を再開した後に、スタックが `UPDATE_COMPLETE` ステータスになり、以前は `CREATE_FAILED` ステータスだったリソースが `CREATE_COMPLETE` ステータスになることを確認します。
-
-:::expand{header="ヒントが必要ですか?"}
-* AWS CloudFormation コンソールのスタックの「イベント」ペインでエラーを調べてください。
-* この SQS リソースの[ドキュメントページ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#aws-resource-sqs-queue-return-values)を開き、SQS キューの ARN を取得するために、`Fn::GetAtt` でどの戻り値を利用すべきかを判断してください。この情報に基づいて、先ほど貼り付けたスニペット内の関連する構成が想定どおりであるかどうかを確認します。
-:::
-
-::::::expand{header="解決策を確認しますか?"}
-* テンプレートの中で、`SourceQueueParameter` リソースの `Value: !GetAtt 'SourceQueue.QueueName'` を `Value: !GetAtt 'SourceQueue.Arn'` に変更してください。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace/troubleshooting-provisioning-errors` に移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/troubleshooting-provisioning-errors
- :::
-1. AWS CLI でスタックを更新します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-troubleshooting-provisioning-errors --template-body file://sqs-queues.yaml --disable-rollback
- :::
-1. `update-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-troubleshooting-provisioning-errors/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. スタック名 (例: `cfn-workshop-troubleshooting-provisioning-errors`) をクリックします。
-1. 画面右上の **更新** ボタンをクリックします。
-1. **テンプレートの準備** で、**既存テンプレートを置き換える** を選択します。
-1. **テンプレートの指定** で、 **テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** ボタンをクリックし、作業用ディレクトリに移動します。
-1. `sqs-queues.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** ページで、一番下までスクロールし、**送信** をクリックします。
-1. ステータスが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-* 完全なソリューションを含むテンプレートは、`code/solutions/troubleshooting-provisioning-errors` ディレクトリにあります。
-::::::
-
-### クリーンアップ
-このラボで作成したリソースのクリーンアップを行うために、以下の手順を実施してください。
-1. このラボで作成したスタック (例: `cfn-workshop-troubleshooting-provisioning-errors`) を選択します。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-1. スタックが **DELETE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-
----
-### まとめ
-素晴らしいです!プロビジョニングエラーのトラブルシューティング方法と、作成した SQS キューの例を使って AWS ドキュメントのリソースプロパティ参照情報を検索する方法を学びました。
diff --git a/content/basics/operations/troubleshooting-provisioning-errors/index.md b/content/basics/operations/troubleshooting-provisioning-errors/index.md
deleted file mode 100644
index 921f01ee1..000000000
--- a/content/basics/operations/troubleshooting-provisioning-errors/index.md
+++ /dev/null
@@ -1,188 +0,0 @@
----
-title: "Troubleshooting provisioning errors"
-weight: 500
----
-
-_Lab Duration: ~25 minutes_
-
----
-
-### Overview
-As you iterate on the development of your CloudFormation template, you can test provisioning of resources described in your template by creating a CloudFormation [stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html). If you specify incorrect property values for resource configurations in the template, by default the stack will roll back to the last-known stable state, and all stack resources will be rolled back.
-
-Let's take an example where you create a stack off of a template, in which you describe 10 resources. In this example, 9 resources are described as successfully created, and the creation of the tenth resource fails: by default, the stack will roll back, including the 9 resources that were successfully provisioned.
-
-To speed up development cycles, you can choose to [preserve](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stack-failure-options.html) the state of resources that have been successfully provisioned as part of stack create and update operations, and of [change set](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html) operations. When you choose to use this functionality, the stack rollback is paused to preserve the state of successfully provisioned resources; then, you can start troubleshooting and fixing your configurations, and resume provisioning operations when you are ready.
-
-### Topics Covered
-By the end of this lab, you will be able to:
-
-* Understand how to troubleshoot provisioning errors, whilst preserving the state of successfully deployed resources
-* Navigate to the [AWS resource and property types reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) to discover resource properties, and return values for a given resource
-
-### Start Lab
-An example CloudFormation template contains an incorrect resource configuration. To correct this, you will choose to *preserve successfully provisioned resources* as part of *stack failure options* to preserve the state of an example `DeadLetterQueue` [Amazon SQS](https://aws.amazon.com/sqs/) queue resource, to be successfully provisioned.
-
-The creation operation for the stack will fail because another SQS queue is described in the template, and has a configuration error. Once you troubleshoot and fix the error in the template, you can resume the stack creation operation with the updated template.
-
-To get started, follow steps shown next:
-1. Change directory to the `code/workspace/troubleshooting-provisioning-errors` directory.
-2. Open the `sqs-queues.yaml` CloudFormation template in your favorite text editor.
-3. Familiarize yourself with the configuration of the sample SQS queues in the template; your intents, in this example, are to:
- 1. create a *source* queue and a [*dead-letter* queue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html) (DLQ): have your `SourceQueue` target your `DeadLetterQueue` for messages that cannot be successfully processed. In the template, reference the [Amazon Resource Name](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) (ARN) for `DeadLetterQueue` in the [redrive policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#aws-sqs-queue-redrive) for `SourceQueue`: your DLQ will then be created first, so that your *source* queue can then reference its ARN;
- 2. describe both queues as [First-In-First-Out](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#aws-sqs-queue-fifoqueue) (FIFO) queues in this example. When you describe a *source* queue and a *dead-letter* [queue](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#aws-sqs-queue-redrive), both queues must be of the same type: either *standard* or *FIFO* (the latter is the example for this lab). Note, that the example template contains different configuration for the two `FifoQueue` property values, instead of the expected value of `true` for both. Moreover, when you describe a FIFO queue, its name must contain a `.fifo` suffix: whilst `SourceQueue` contains the `.fifo` suffix in its `QueueName`, it is configured as a standard queue (i.e., with `FifoQueue` set to `false`), thus resulting in an error.
-
-Use the `sqs-queues.yaml` template, that contains the error mentioned earlier, to test the stack rollback pause functionality, then fix the error, and complete the stack creation:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/troubleshooting-provisioning-errors`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/troubleshooting-provisioning-errors
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-troubleshooting-provisioning-errors --template-body file://sqs-queues.yaml --disable-rollback
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-troubleshooting-provisioning-errors/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_FAILED**.
-::::
-
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/), and [choose a Region](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/select-region.html) you wish to use.
-1. From **Create stack**, choose **With new resources (standard)**.
-1. From **Prepare template**, choose **Template is ready**.
-1. From **Template source**, choose Upload a template file. Choose the `sqs-queues.yaml` template mentioned earlier, and then choose Next.
-1. Specify a stack name: for example, `cfn-workshop-troubleshooting-provisioning-errors`. On the same page, accept the default value for the `QueueNamePrefix` parameter, and choose **Next**.
-1. In **Stack failure options**, select **Preserve successfully provisioned resources**. Choose **Next**.
-1. Choose **Submit** in the next page.
-1. Refresh the stack creation page until you see your stack in the `CREATE_FAILED` status.
-::::
-:::::
-
-The stack creation has failed, because of the error mentioned earlier. Select the name of your stack from the list (for example, `cfn-workshop-troubleshooting-provisioning-errors`): in the **Resources** tab, note that the `DeadLetterQueue` resource is in the `CREATE_COMPLETE` status, and the `SourceQueue` resource is in `CREATE_FAILED` status, along with a relevant error in the **Status reason** column.
-
-In the same stack view page, you will also see options from which you can choose next steps to take, as shown in the following picture:
-
-
-
-Your goal is to troubleshoot and fix the error in the template, and resume provisioning, to create the `SourceQueue` resource. As part of this process, preserve the state of your `DeadLetterQueue` that has been created successfully earlier. Next steps:
-
- With the `sqs-queues.yaml` template opened in your editor, find `SourceQueue` resource, and change `FifoQueue: false` into `FifoQueue: true`. When done, save your changes.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/troubleshooting-provisioning-errors`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/troubleshooting-provisioning-errors
-:::
-1. Use the AWS CLI to update the stack. The required parameter `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-troubleshooting-provisioning-errors --template-body file://sqs-queues.yaml --disable-rollback
-:::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-troubleshooting-provisioning-errors/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. In the **Stack rollback paused** view shown in the picture earlier, choose **Update**.
-1. In **Prepare template**, choose **Replace current template**, and choose to upload the template you just updated.
-1. Choose **Next** in the **Parameters** page.
-1. In the **Configure stack options** page, locate the **Stack failure options** section: the **Preserve successfully provisioned resources** option you chose at stack creation should still be selected. Scroll down on the page, and choose **Next**.
-1. Next, choose **Submit**.
-::::
-:::::
-
-Refresh the page until you see your stack in the `UPDATE_COMPLETE` status. In the **Resources** tab for your stack, your `SourceQueue` resource should now be in the `CREATE_COMPLETE` status.
-
-::alert[Immutable update types (that is, when you [change the value for a property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html) that requires a replacement), are not supported. For more information, see [Conditions to pause stack rollback](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stack-failure-options.html#stack-failure-options-conditions).]{type="info"}
-
-Congratulations! You have learned how to troubleshoot provisioning errors with the pause disable rollback functionality of CloudFormation!
-
-::alert[In this lab, you have used the AWS CloudFormation Console to learn this functionality: for information on how to use it in the [AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html), see [Preserve successfully provisioned resources (AWS CLI)](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stack-failure-options.html#stack-failure-options-cli) in the documentation.]{type="info"}
-
-### Challenge
-You choose to describe two [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) resources in your `sqs-queues.yaml` template. For each parameter, you choose to store the ARN of a queue you created earlier: for this, you reference the value you need by using the `Fn::GetAtt` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html) to get the [return value](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#aws-properties-sqs-queues-return-values) of the relevant SQS resource attribute you need. You also choose to validate that you are specifying an SQS ARN as the parameter value, by validating its format against an example regular expression pattern defined in `AllowedPattern` for each parameter. Steps:
-
-* first, copy and paste the example configuration shown next by appending it to your `sqs-queues.yaml` template:
-
-```yaml
- DeadLetterQueueParameter:
- Type: AWS::SSM::Parameter
- Properties:
- AllowedPattern: ^arn:aws([-a-z0-9-]*[a-z0-9])*:sqs:[a-z0-9-]+:[0-9]{12}:[a-zA-Z0-9_-]{1,80}(\.fifo){0,1}$
- Description: Parameter for the DeadLetterQueue ARN value
- Name: workshop-example-dead-letter-queue
- Type: String
- Value: !GetAtt DeadLetterQueue.Arn
-
- SourceQueueParameter:
- Type: AWS::SSM::Parameter
- Properties:
- AllowedPattern: ^arn:aws([-a-z0-9-]*[a-z0-9])*:sqs:[a-z0-9-]+:[0-9]{12}:[a-zA-Z0-9_-]{1,80}(\.fifo){0,1}$
- Description: Parameter for the SourceQueue ARN value
- Name: workshop-example-source-queue
- Type: String
- Value: !GetAtt SourceQueue.QueueName
-```
-
-* Save your changes to the file. Next,
-
-[update your stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-direct.html) by using the AWS CloudFormation Console using the same procedure you followed in previous step to update stack. When you do so, choose **Replace current template** in **Prepare template**, and upload the template you just updated. In the **Configure stack options** page, the **Preserve successfully provisioned resources** option should still be selected.
-* The stack update operation will fail: when you look into the **Resources** tab for your stack, you should see that one of the two new resources has been created successfully, and the other new one should be in a `CREATE_FAILED` status instead.
-* Troubleshoot and fix the error in the snippet you pasted into your template.
-* Resume the stack update: verify your stack will be in the `UPDATE_COMPLETE` status, and the resource that was previously in the `CREATE_FAILED` status will be in a `CREATE_COMPLETE` status.
-
-:::expand{header="Need a hint?"}
-* Inspect the error in the `Events` pane for your stack in the AWS CloudFormation Console.
- * Navigate to this SQS resource documentation [page](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#aws-properties-sqs-queues-return-values), and determine which one of the available return values you need to get, with `Fn::GetAtt`, the SQS queue ARN. Use this information to validate if the relevant configuration in the snippet you pasted earlier is the one you expect.
-:::
-
-::::::expand{header="Want to see the solution?"}
-* Update your template: change `Value: !GetAtt 'SourceQueue.QueueName'` into `Value: !GetAtt 'SourceQueue.Arn'` for the `SourceQueueParameter` resource.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/troubleshooting-provisioning-errors`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/troubleshooting-provisioning-errors
- :::
-1. Use the AWS CLI to update the stack. The required parameter `--template-body` have been pre-filled for you.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-troubleshooting-provisioning-errors --template-body file://sqs-queues.yaml --disable-rollback
- :::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-troubleshooting-provisioning-errors/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Click on the stack name, for example **cfn-workshop-troubleshooting-provisioning-errors**.
-1. In the top right corner click on **Update**.
-1. In **Prepare template**, choose **Replace current template**.
-1. In **Template source**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the file `sqs-queues.yaml ` and click **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and click on **Submit**.
-1. You can click the **refresh** button a few times until you see in the status **UPDATE_COMPLETE**.
-::::
-:::::
-* Note: the template with the full solution is available in the `code/solutions/troubleshooting-provisioning-errors` directory.
-::::::
-
-### Cleanup
-Choose to follow cleanup steps shown next to clean up resources you created with this lab:
-1. Choose the stack you have created on this lab, for example `cfn-workshop-troubleshooting-provisioning-errors`.
-2. In the top right corner, select **Delete**.
-3. In the pop-up window, select **Delete**.
-4. Wait for the stack to reach the **DELETE_COMPLETE** status. You need to periodically select **Refresh** to see the latest stack status.
-
----
-### Conclusion
-Great work! You learned how to troubleshoot provisioning errors, and how to locate resource property reference information in the AWS documentation with examples for SQS queues you created.
diff --git a/content/basics/operations/user-data/index.ja.md b/content/basics/operations/user-data/index.ja.md
deleted file mode 100644
index 6c12ca290..000000000
--- a/content/basics/operations/user-data/index.ja.md
+++ /dev/null
@@ -1,191 +0,0 @@
----
-title: "ユーザーデータ"
-weight: 300
----
-
-_ラボ実施時間 : 10分程度_
-
----
-
-### 概要
-
-AWS CloudFormation を使用して、Amazon EC2 インスタンスにアプリケーションを自動的にインストール、設定、および起動できます。そうすることで、直接インスタンスに接続しなくても、デプロイメントの複製や既存のインストールの更新を簡単に行うことができます。時間と労力を大幅に節約できます。
-
-### カバーするトピック
-このラボでは、**[UserData](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html)** プロパティを使用して、簡単な PHP アプリケーションを含む Apache Web サーバーをデプロイします。
-
-+ まず、EC2 インスタンスをブートストラップして、Web サーバーとコンテンツをインストールします。
-+ 次に、EC2 **セキュリティグループ** を作成し、ポート 80 でインスタンスへのアクセスを許可します。
-+ 最後に、Web サーバーによって提供されるコンテンツを表示します。
-
-次の図は、実装するアーキテクチャの大まかな概要を示しています。
-
-
-
-### ラボの開始
-
-1. `code/workspace` ディレクトリに移動します。
-1. `user-data.yaml` ファイルを開きます。
-1. 以下のトピックを進めながら、コードをコピーしてください。
-
-
-#### 1. セキュリティグループの作成
-
-まず、セキュリティグループを作成します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=75}
-WebServerSecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: 'Enable HTTP access via port 80'
-:::
-
-Apache Web サーバーはポート 80 でコンテンツを提供するので、セキュリティグループの `SecurityGroupIngress` 属性にインターネットからのアクセスを許可するイングレスルールを作成する必要があります。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=79 highlightLines=83-87}
-WebServerSecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: 'Enable HTTP access via port 80'
- SecurityGroupIngress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
-:::
-
-最後に、セキュリティグループを EC2 インスタンスに関連付けます。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=63 highlightLines=69-70}
-WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- IamInstanceProfile: !Ref EC2InstanceProfile
- ImageId: !Ref AmiID
- InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref EnvironmentType, InstanceType]
- SecurityGroupIds:
- - !Ref WebServerSecurityGroup
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref EnvironmentType, webserver ] ]
-:::
-
-:::alert{type="info"}
-_セキュリティグループ_ プロパティを変更したため、CloudFormation スタックに存在している EC2 インスタンスが _置換_ されます。[こちら](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html?shortFooter=true#aws-properties-ec2-instance-properties)で EC2 インスタンスの更新時に[置換](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement)が必要になるプロパティを確認できます。
-:::
-
-
-#### 2. インスタンスに Apache Web サーバーをインストール
-
-それでは、Apache と PHP アプリケーションをインストールするための bash スクリプトを書いてみましょう。
-
-:::alert{type="info"}
-ユーザーデータのスクリプトは **root** ユーザーとして実行されるため、スクリプトで `sudo` コマンドを使用する必要はありません。\
-**UserData** は、CloudFormation から EC2 インスタンスに渡されるときに Base64 でエンコードされている必要があります。`Fn::Base64` 組み込み関数を使用して入力文字列をエンコードします。
-:::
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=74}
-UserData:
- Fn::Base64: |
- #!/bin/bash
- yum update -y
- yum install -y httpd php
- systemctl start httpd
- systemctl enable httpd
- usermod -a -G apache ec2-user
- chown -R ec2-user:apache /var/www
- chmod 2775 /var/www
- find /var/www -type d -exec chmod 2775 {} \;
- find /var/www -type f -exec chmod 0664 {} \;
- # PHP script to display Instance ID and Availability Zone
- cat << 'EOF' > /var/www/html/index.php
-
-
-
-
-
- EC2 Instance ID:
- Availability Zone:
-
-
-
- EOF
-:::
-
-#### 3. CloudFormation の _Outputs_ に **WebsiteURL** を追加
-
-以下のコードをコピーして、CloudFormation テンプレートの _Outputs_ セクションに貼り付けます。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=132}
-WebsiteURL:
- Value: !Sub http://${WebServerEIP}
- Description: Application URL
-:::
-
-#### 4. スタックの更新
-
-前のラボと同様に、更新されたテンプレートでスタックを作成します。CloudFormation がスタックの作成を完了すると、スクリプトが EC2 インスタンスに Web サーバーをセットアップしたことを確認できます。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body`、`--capabilities` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-user-data \
---template-body file://user-data.yaml \
---capabilities CAPABILITY_IAM
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-user-data/96d87030-e809-11ed-a82c-0eb19aaeb30f"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
-1. `user-data.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックの名前** (例: `cfn-workshop-user-data`) を入力し、**次へ** をクリックします。
-1. **Amazon Machine Image ID** はそのままにします。
-1. **EnvironmentType** は選択されている値をそのままにして、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。** の文言のチェックボックスにチェックを入れます。**送信** をクリックします。
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-
-Web ブラウザで `WebsiteURL` を入力します (WebsiteURL は CloudFormation コンソールの _Outputs_ タブから取得できます)。
-
-
-
-下の図のようなページが表示されるはずです。
-
-
-
-### クリーンアップ
-
-以下の手順の通りに、作成したリソースのクリーンアップを実施してください。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** に移動します。
-1. CloudFormation の **スタック** ページで `cfn-workshop-user-data` を選択します。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-1. スタックが **DELETE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-
----
-### まとめ
-
-おめでとうございます! EC2 インスタンスのブートストラップに成功しました。次のセクションでは、CloudFormation _ヘルパースクリプト_ という手法で Amazon EC2 にソフトウェアをインストールしてサービスを開始する方法を学びます。
diff --git a/content/basics/operations/user-data/index.md b/content/basics/operations/user-data/index.md
deleted file mode 100644
index 478cdd003..000000000
--- a/content/basics/operations/user-data/index.md
+++ /dev/null
@@ -1,197 +0,0 @@
----
-title: "User data"
-weight: 300
----
-
-_Lab Duration: ~10 minutes_
-
----
-
-### Overview
-
-You can use AWS CloudFormation to automatically install, configure, and start applications on Amazon EC2 instances. Doing
-so enables you to easily replicate deployments and update existing installations without connecting directly to the
-instance, which can save you a lot of time and effort.
-
-### Topics Covered
-In this lab you will deploy an Apache Web server with a simple PHP application via **[UserData](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html)** property.
-
-+ First, you will bootstrap EC2 instance to install web server and content.
-+ Then you will create an EC2 **Security Group** and allow access on port 80 to the instance.
-+ Finally, you will view the content served by the web server.
-
-The following diagram provides a high-level overview of the architecture you will implement.
-
-
-
-### Start Lab
-
-1. Go to the `code/workspace` directory.
-1. Open the `user-data.yaml` file.
-1. Copy the code as you go through the topics below.
-
-#### 1. Create Security Group
-
-Begin by creating a Security Group.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=75}
-WebServerSecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: 'Enable HTTP access via port 80'
-:::
-
-As the Apache web server will serve content on port 80, you will need to create an ingress rule `SecurityGroupIngress`
-in the security group to allow access from the Internet.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=79 highlightLines=83-87}
-WebServerSecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: 'Enable HTTP access via port 80'
- SecurityGroupIngress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
-:::
-
-Finally, associate the security group with the EC2 instance.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=63 highlightLines=69-70}
-WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- IamInstanceProfile: !Ref EC2InstanceProfile
- ImageId: !Ref AmiID
- InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref EnvironmentType, InstanceType]
- SecurityGroupIds:
- - !Ref WebServerSecurityGroup
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref EnvironmentType, webserver ] ]
-:::
-
-:::alert{type="info"}
-The EC2 instance in the CloudFormation stack will be _replaced_ as a result of modifying the _Security Group_ property.
-You can find the properties where updates require [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement)
-of EC2 instances [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html?shortFooter=true#aws-properties-ec2-instance-properties).
-:::
-
-#### 2. Install Apache web server on the instance
-
-Now, let's write a bash script to install the Apache and the PHP application.
-
-:::alert{type="info"}
-User data scripts are executed as the **root** user, so there is no need to use `sudo` commands in the script.\
-**UserData** must be Base64 encoded when passed from CloudFormation to EC2 instance. Use `Fn::Base64` intrinsic function to encode the input string.
-:::
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=74}
-UserData:
- Fn::Base64: |
- #!/bin/bash
- yum update -y
- yum install -y httpd php
- systemctl start httpd
- systemctl enable httpd
- usermod -a -G apache ec2-user
- chown -R ec2-user:apache /var/www
- chmod 2775 /var/www
- find /var/www -type d -exec chmod 2775 {} \;
- find /var/www -type f -exec chmod 0664 {} \;
- # PHP script to display Instance ID and Availability Zone
- cat << 'EOF' > /var/www/html/index.php
-
-
-
-
-
- EC2 Instance ID:
- Availability Zone:
-
-
-
- EOF
-:::
-
-#### 3. Add the **WebsiteURL** to CloudFormation _Outputs_
-
-Copy and paste the code below to the _Outputs_ section of the CloudFormation template.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=132}
-WebsiteURL:
- Value: !Sub http://${WebServerEIP}
- Description: Application URL
-:::
-
-#### 4. Create the Stack
-
-Similar to previous labs, create the stack with the updated template. Once CloudFormation completes creating the stack,
-you can then check to see that your script has set up a web server on the EC2 instance.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. Use the AWS CLI to create the stack. The required parameters `--stack-name`, `--template-body` and `--capabilities` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-user-data \
---template-body file://user-data.yaml \
---capabilities CAPABILITY_IAM
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-user-data/96d87030-e809-11ed-a82c-0eb19aaeb30f"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and wait for stack status to reach **CREATE_COMPLETE**. You need to periodically select Refresh to see the latest stack status.
-::::
-::::tab{id="local" label="Local development"}
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. Choose **Create stack** _With new resources (Standard)_ from the top-right side of the page.
-1. In **Prepare template**, choose **Template is ready**.
-1. In **Template source**, choose **Upload a template file**.
-1. Choose the **Choose file** button and navigate to your workshop directory.
-1. Select the file `user-data.yaml` and click **Next**.
-1. Provide a **Stack name**. For example `cfn-workshop-user-data`.
-1. For **Amazon Machine Image ID** leave the default value in.
-1. For **EnvironmentType** leave the selected environment in.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and tick **I acknowledge that AWS CloudFormation might create IAM resources** check box, then click on **Submit**.
-1. Wait for stack status to reach the **CREATE_COMPLETE**. You need to periodically select Refresh to see the latest stack status.
-::::
-:::::
-
-In a web browser, enter the `WebsiteURL` (you can get the WebsiteURL from the _Outputs_ tab of the CloudFormation console).
-
-
-
-You should see a page similar to the picture below:
-
-
-
-### Clean up
-
-Follow these steps to clean up created resources:
-
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the stack you have created in this lab. For example `cfn-workshop-user-data`.
-1. In the top right corner, select **Delete**.
-1. In the pop-up window, select **Delete**.
-1. Wait for the stack to reach the **DELETE_COMPLETE** status. You need to periodically select **Refresh** to see the latest stack status.
-
----
-
-### Conclusion
-
-Congratulations, you have successfully bootstrapped an EC2 instance! In the next section you will learn a different way
-to install software and start services on Amazon EC2 - CloudFormation _Helper Scripts_.
diff --git a/content/basics/templates/flipping-formats-and-cleanup/index.ja.md b/content/basics/templates/flipping-formats-and-cleanup/index.ja.md
deleted file mode 100644
index 72b7e4f1e..000000000
--- a/content/basics/templates/flipping-formats-and-cleanup/index.ja.md
+++ /dev/null
@@ -1,155 +0,0 @@
----
-title: "フォーマット変換とクリーンアップ"
-weight: 1000
----
-
-_ラボ実施時間 : 10分程度_
-
-_チャレンジ : 15分程度_
-
----
-
-### 概要
-AWS CloudFormation [テンプレート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-formats.html) は JSON 形式または YAML 形式で記述できます。好みに応じてどちらかを選択できます。詳細については、[AWS CloudFormation テンプレート形式](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-formats.html) を参照してください。
-
-このラボでは、JSON 形式のテンプレートから YAML 形式への切り替えの例を見ていきます。このタスクを簡単に実行するため [cfn-flip](https://github.com/awslabs/aws-cfn-template-flip) というツールを使用できます。また、`cfn-flip` を使用して、サンプルテンプレートの独自のクリーンアップアクションを実行します。
-
-### カバーするトピック
-このラボを修了すると、`cfn-flip` を使用して以下のことができるようになります。
-
-* JSON 形式から YAML 形式への切り替え、およびその逆も可能です。
-* サンプルテンプレートに対して独自のクリーンアップアクションを実行できます。
-
-### ラボの開始
-`pip` で `cfn-flip` を [インストール](https://github.com/awslabs/aws-cfn-template-flip#installation)します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install cfn-flip
-:::
-
-または、macOS では [Homebrew](https://brew.sh/) を使っている場合は以下の通りにインストールできます。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-brew install cfn-flip
-:::
-
-インストールが完了したら、以下のコマンドを実行して `cfn-flip` を実行できることを確認します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-flip --version
-:::
-
-それでは、JSON 形式のテンプレート例を YAML に変換してみましょう。以下の手順に沿って、このラボで使用するテンプレートを特定してください。
-1. `code/workspace/flipping-formats-and-cleanup` ディレクトリに移動します。
-1. お気に入りのテキストエディターで `example_parameter.json` CloudFormation テンプレートを開きます。
-1. `example_parameter.json` ファイルの内容を確認します。このテンプレートは、[AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html) パラメータの `AWS::SSM::Parameter` リソースタイプを記述しています。このサンプルテンプレートに対して以下の作業を行います。
- - [Ref](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) 組み込み関数を使用して、テンプレートの `ParameterValue` 入力パラメータを参照することにより、Parameter Store パラメータに保存する値を指定します。このテンプレートからスタックを作成するときは、指定した値を `ParameterValue` への入力として渡します。
- - `Ref` を使用して、パラメータストアパラメータに割り当てたい名前を参照します。この名前は、テンプレートからスタックを作成するときに `ParameterName` テンプレートパラメータで指定できます。
- - Parameter Store パラメータに説明を追加します。今回は、[Fn::Join](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html) 組込み関数を使用して文字列の断片を結合します。文字列の断片には、パラメータストアパラメータの名前への参照が含まれます。サンプルテンプレートでは、_delimiter_ に示されているように、`" "` 文字列の断片はスペースで区切られています。`Fn::Join` 関数の 1 つ目の[パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html#intrinsic-function-reference-join-parameters)です。
-
-::alert[`Fn::Sub` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) でも文字列を結合することもできます。このラボの後半では、`cfn-flip` を使用して `Fn::Join` 関数の宣言を `Fn::Sub` に変換する方法を紹介します。]{type="info"}
-
-次にサンプルテンプレートの抜粋で学習したポイントに焦点を当てて要約します。
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[...]
- "Parameters": {
- "ParameterName": {
- "Description": "Name you wish to specify for your SSM Parameter.",
-[...]
- },
- "ParameterValue": {
- "Description": "Value you wish to specify for your SSM Parameter.",
-[...]
- }
- },
- "Resources": {
- "MyParameter": {
- "Type": "AWS::SSM::Parameter",
- "Properties": {
- "Name": {
- "Ref": "ParameterName"
- },
- "Type": "String",
- "Value": {
- "Ref": "ParameterValue"
- },
- "Description": {
- "Fn::Join": [
- " ",
- [
- "My",
- {
- "Ref": "ParameterName"
- },
- "example parameter"
- ]
-[...]
-:::
-
-次に、`cfn-flip` を使用してテンプレートを JSON 形式から YAML 形式に変換します。JSON 形式の `example_parameter.json` テンプレートが置かれているディレクトリから次のコマンドを実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-flip example_parameter.json example_parameter.yaml
-:::
-
-::alert[`cfn-flip` ツールは入力テンプレートのフォーマット (この場合は JSON) を自動的に検出し、それに応じて反対の出力フォーマット (この例では YAML) に変換します。`cfn-flip` に YAML または JSON に変換するように明示的に指示するには、それぞれ `-y` (または `--yaml`) オプションか `-j` (または `--json`) オプションを指定してください。`cfn-flip` は入力テンプレートの形式が逆の形式であることを仮定します。詳細については、コマンドラインから `cfn-flip --help` を実行してください。]{type="info"}
-
-実行の結果として、同じディレクトリに `example_parameter.yaml` という名前の新しいテンプレートが作成されたはずです。お気に入りのテキストエディタでテンプレートを開きます。`cfn-flip` で YAML に変換した要素を確認できますか?
-
-以下の例は `example_parameter.yaml` テンプレートからの抜粋です。JSON 形式のテンプレートで見た `Fn::Join` 組込み関数が、YAML の短縮形である `!Join` に変換されたとわかります。`cfn-flip` が可能な限り[短縮形式の関数宣言を使用する](https://github.com/awslabs/aws-cfn-template-flip#about)仕様だからです。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-[...]
-Parameters:
- ParameterName:
- Description: Name you wish to specify for your SSM Parameter.
-[...]
- ParameterValue:
- Description: Value you wish to specify for your SSM Parameter.
-[...]
-Resources:
- MyParameter:
- Type: AWS::SSM::Parameter
- Properties:
- Name: !Ref 'ParameterName'
- Type: String
- Value: !Ref 'ParameterValue'
- Description: !Join
- - ' '
- - - My
- - !Ref 'ParameterName'
- - example parameter
-:::
-
-`cfn-flip` を使って、YAML から JSON に変換することもできます。詳細またはその他の `cfn-flip` の機能を確認するには、以下のコマンドを実行してください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-flip --help
-:::
-
-::alert[テンプレートを YAML 形式で記述する場合、行の先頭に `#` 文字を使用することにより、テンプレートにコメントを記述することができます。`cfn-flip` を使用して YAML から JSON に変換すると、YAML のコメントは JSON 形式の出力テンプレートに追加されません。JSON がコメントの記述をサポートしていないからです (詳細は、 をご参照ください)。]{type="info"}
-
-おめでとうございます!これで、CloudFormation テンプレートを JSON 形式から YAML 形式に変換し、その他の `cfn-flip` 機能を見つける方法も学びました。
-
-### チャレンジ
-`cfn-flip` ツールを使うと、[Fn::Join](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html) 組み込み関数から [Fn::Sub](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) への変換など、テンプレートに対して独自のクリーンアップアクションを実行することもできます。このラボセクションでは、先ほど JSON 形式から変換した `example_parameter.yaml` テンプレートでこの機能を使用することとします。
-
-このチャレンジは、`example_parameter.yaml` テンプレートに対して独自のクリーンアップアクションを実行し、クリーンアップしたテンプレートの出力をワークスペースの `example_parameter_updated.yaml` という新しいファイルに保存することに挑戦します。出力テンプレートを JSON に変換するのではなく、同じ YAML 形式を維持する必要があることに注目してください。
-
-まず `cfn-flip` に渡す必要のあるオプションを見つけてから、入力テンプレートに対して `cfn-flip` を実行し、出力テンプレートが `Fn::Join` 組み込み関数の短縮形式ではなく `Fn::Sub` 組み込み関数の短縮形式を使用していることを確認します。
-
-::expand[`cfn-flip --help` と入力して `cfn-flip` の使い方を表示すると、そのタスクに使いたい 2 つのオプションが分かります。この 2 つのオプションはどれですか?]{header="ヒントが必要ですか?"}
-
-:::expand{header="解決策を確認しますか?"}
-同じフォーマット (この場合は YAML) を維持したり、独自のクリーンアップアクションを実行したりするには、`cfn-flip` に `-n -c` (または `--no-flip --clean`) の 2 つのオプションを使用してください。ワークスペースで以下のコマンドを実行します。
-::code[cfn-flip -n -c example_parameter.yaml example_parameter_updated.yaml]{language=shell showLineNumbers=false showCopyAction=true}
-
-できあがった `example_parameter_updated.yaml` テンプレートをお気に入りのテキストエディタで開きます。次のテンプレートの抜粋に示されているように、`!Join` (短縮形式) の代わりに `!Sub` (短縮形式) が使用されていることがわかります。
-::code[Description: !Sub 'My ${ParameterName} example parameter']{language=yaml showLineNumbers=false showCopyAction=true}
-:::
-
----
-### まとめ
-
-素晴らしいです!`cfn-flip` を使用して JSON 形式の CloudFormation テンプレートを YAML 形式に変換する方法 (とその逆)、および特定のテンプレートに対して独自のクリーンアップアクションを実行する方法を学びました。
diff --git a/content/basics/templates/flipping-formats-and-cleanup/index.md b/content/basics/templates/flipping-formats-and-cleanup/index.md
deleted file mode 100644
index a54bfda79..000000000
--- a/content/basics/templates/flipping-formats-and-cleanup/index.md
+++ /dev/null
@@ -1,155 +0,0 @@
----
-title: "Flipping formats and cleanup"
-weight: 1000
----
-
-_Lab Duration: ~10 minutes_
-
-_Challenge: ~15 minutes._
-
----
-
-### Overview
-You can write AWS CloudFormation [templates](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-formats.html) in JSON or YAML formats: you choose either one or the other depending on your preference. For more information, see [AWS CloudFormation template formats](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-formats.html).
-
-In this module, you will look into an example of switching from a JSON-formatted template into a YAML format: you will use the [cfn-flip](https://github.com/awslabs/aws-cfn-template-flip) tool as an option to easily perform this task. You will also use `cfn-flip` to perform opinionated cleanup actions for an example template.
-
-### Topics Covered
-By the end of this lab, you will be able to use `cfn-flip` as an option to:
-
-* Flip from JSON to YAML formats, and vice versa.
-* Perform opinionated cleanup actions on an example template.
-
-### Start Lab
-[Install](https://github.com/awslabs/aws-cfn-template-flip#installation) `cfn-flip` with `pip`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install cfn-flip
-:::
-
-Alternatively, if you are using [Homebrew](https://brew.sh/) on macOS:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-brew install cfn-flip
-:::
-
-When you are done with the installation, verify you can run `cfn-flip` by running the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-flip --version
-:::
-
-Let's now convert an example JSON-formatted template into YAML. Follow steps below to locate the template you will use, in this lab, for the task:
-1. Change directory to the `code/workspace/flipping-formats-and-cleanup` directory.
-2. Open the `example_parameter.json` CloudFormation template in your favorite text editor.
-3. Read the content of the `example_parameter.json` file: this template describes an `AWS::SSM::Parameter` resource type for an [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) parameter. With this example template, you:
- - specify the value you wish to store for your Parameter Store parameter by using the [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) intrinsic function to reference the input `ParameterValue` template parameter. When you create a stack from this template, you pass in your desired value as an input to `ParameterValue`;
- - use `Ref` to reference the name you wish to assign to your Parameter Store parameter, that you specify in the `ParameterName` template parameter when you create a stack from the template;
- - add a description for your Parameter Store parameter: in this example, you choose to use the [Fn::Join](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html) intrinsic function to concatenate string fragments, one of which contains the reference to the name of your Parameter Store parameter. In the example template, string fragments are separated by a space, as indicated in the `" "` _delimiter_, that is the first [parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html#intrinsic-function-reference-join-parameters) you are passing here to the `Fn::Join` function.
-
-::alert[You can also join strings with the `Fn::Sub` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html). Later on in this lab, you will learn how to use `cfn-flip` to convert from `Fn::Join` function declarations into `Fn::Sub`.]{type="info"}
-
-Example template excerpts, that focus on points you just learned, are summarized next:
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[...]
- "Parameters": {
- "ParameterName": {
- "Description": "Name you wish to specify for your SSM Parameter.",
-[...]
- },
- "ParameterValue": {
- "Description": "Value you wish to specify for your SSM Parameter.",
-[...]
- }
- },
- "Resources": {
- "MyParameter": {
- "Type": "AWS::SSM::Parameter",
- "Properties": {
- "Name": {
- "Ref": "ParameterName"
- },
- "Type": "String",
- "Value": {
- "Ref": "ParameterValue"
- },
- "Description": {
- "Fn::Join": [
- " ",
- [
- "My",
- {
- "Ref": "ParameterName"
- },
- "example parameter"
- ]
-[...]
-:::
-
-Next, use `cfn-flip` to convert your template from the JSON format into YAML. Run the following command from the directory where the `example_parameter.json` JSON-formatted template is located:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-flip example_parameter.json example_parameter.yaml
-:::
-
-::alert[The `cfn-flip` tool automatically detects the format of your input template (in your case, JSON), and will convert it into the opposite output format accordingly (in this example, into YAML). To explicitly tell `cfn-flip` to convert into YAML or into JSON (and to have `cfn-flip` assume the input template uses the opposite format), choose the `-y` (or `--yaml`) option or the `-j` (or `--json`) option, respectively. For more information, run ` cfn-flip --help` from the command line.]{type="info"}
-
-As a result, you should now have a new template, in the same directory, called `example_parameter.yaml`. Open the template in your favorite text editor: can you recognize elements that you converted into YAML with `cfn-flip`?
-
-Excerpts from the `example_parameter.yaml` template are shown next. You will note that the `Fn::Join` intrinsic function, which you saw in the JSON-formatted template, is now represented in its YAML short form, `!Join`; this is because `cfn-flip` [makes use of short form function declarations](https://github.com/awslabs/aws-cfn-template-flip#about) where possible:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-[...]
-Parameters:
- ParameterName:
- Description: Name you wish to specify for your SSM Parameter.
-[...]
- ParameterValue:
- Description: Value you wish to specify for your SSM Parameter.
-[...]
-Resources:
- MyParameter:
- Type: AWS::SSM::Parameter
- Properties:
- Name: !Ref 'ParameterName'
- Type: String
- Value: !Ref 'ParameterValue'
- Description: !Join
- - ' '
- - - My
- - !Ref 'ParameterName'
- - example parameter
-:::
-
-With `cfn-flip` you can also convert from YAML to JSON. For more information, and to discover other `cfn-flip` features, run the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-flip --help
-:::
-
-::alert[When you write your templates in YAML format, you can choose to specify YAML comments in your template content by using the `#` character at the beginning of a line. When you use `cfn-flip` to convert from YAML into JSON, your YAML comments are not added to your output template in JSON format. This is because JSON does not support comments (see for more information).]{type="info"}
-
-Congratulations! You have converted your CloudFormation template from the JSON format to YAML, and learned how to discover other `cfn-flip` features!
-
-### Challenge
-The `cfn-flip` tool gives you also the ability to perform opinionated cleanup actions on your template, including converting from the [Fn::Join](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html) intrinsic function into using [Fn::Sub](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html). In this lab section, you choose to use this functionality in the `example_parameter.yaml` template you converted earlier from the JSON format.
-
-Your task is to perform opinionated cleanup actions on the `example_parameter.yaml` template, and store the cleaned up template output in a new file in your workspace, called `example_parameter_updated.yaml`. Please note that you want to maintain the same YAML format for the output template, instead of converting it to JSON.
-
-Start with finding which options you need to pass to `cfn-flip` first, then run `cfn-flip` against the input template, and verify the output template uses the short form for the `Fn::Sub` intrinsic function instead of the short form for the `Fn::Join` intrinsic function.
-
-::expand[Print the `cfn-flip` usage with: `cfn-flip --help` to find which two options you want to use for the task. Which are these two options?]{header="Need a hint?"}
-
-:::expand{header="Want to see the solution?"}
-Use the two following options: `-n -c` (or `--no-flip --clean`) for `cfn-flip` to maintain the same format (in this case, YAML), and to perform opinionated cleanup actions. Run the following command in your workspace:
-::code[cfn-flip -n -c example_parameter.yaml example_parameter_updated.yaml]{language=shell showLineNumbers=false showCopyAction=true}
-
-Open the resulting `example_parameter_updated.yaml` template with your favorite text editor: you should see that `!Sub` (short format) is now used, instead of `!Join` (short format) as shown in the following template excerpt:
-::code[Description: !Sub 'My ${ParameterName} example parameter']{language=yaml showLineNumbers=false showCopyAction=true}
-:::
-
----
-### Conclusion
-
-Great work! You have learned how to use `cfn-flip` to convert JSON-formatted CloudFormation templates into YAML (and vice versa), and to perform opinionated cleanup actions on a given template.
diff --git a/content/basics/templates/index.ja.md b/content/basics/templates/index.ja.md
deleted file mode 100644
index f74d398f5..000000000
--- a/content/basics/templates/index.ja.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-title: "テンプレート"
-weight: 10
----
-
-
-
-このセクションでは、AWS CloudFormation の基本となる概念を紹介します。
-
-* CloudFormation を使うことで、テキストファイルでインフラストラクチャをモデル化することができます。作成・設定したい AWS リソースを [JSON](https://json.org/) や [YAML](https://yaml.org/) で定義できます。
-
-* CloudFormation はインフラストラクチャのプロビジョニングと更新を安全かつ管理された方法で自動化します。エラーにつながる手動のステップや操作がありません。
-
-* CloudFormation は追加の費用なく使うことができます。アプリケーションの実行に必要な AWS リソースに対してのみ料金がかかります。
-
----
-
-### ワークショップでカバーするトピック:
-
-::children
diff --git a/content/basics/templates/index.md b/content/basics/templates/index.md
deleted file mode 100644
index 02453c1b2..000000000
--- a/content/basics/templates/index.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: "Templates"
-weight: 10
----
-
-
-
-In this section, you will be introduced to the basic concepts of AWS CloudFormation.
-
-* CloudFormation allows you to model your infrastructure in a text file. You can use [JSON](https://json.org/) or
- [YAML](https://yaml.org/) to describe what AWS resources you want to create and configure.
-
-* CloudFormation automates the provisioning and updating of your infrastructure in a safe and controlled manner.
- There are no manual steps or controls that can lead to errors.
-
-* CloudFormation is available at no additional charge. You pay only for the AWS resources needed to run your applications.
-
----
-
-### Workshop topics covered:
-
-::children
diff --git a/content/basics/templates/intrinsic-functions/index.ja.md b/content/basics/templates/intrinsic-functions/index.ja.md
deleted file mode 100644
index 529f59ab1..000000000
--- a/content/basics/templates/intrinsic-functions/index.ja.md
+++ /dev/null
@@ -1,214 +0,0 @@
----
-title: "組み込み関数"
-weight: 400
----
-
-_ラボ実施時間 : 10分程度_
-
----
-
-### 概要
-
-このラボではテンプレートで **[組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)** の使い方を紹介します。
-
-組み込み関数はスタックの管理を行いやすくする内蔵の関数です。組み込み関数が無いと、 **[テンプレートとスタック](../template-and-stack/)** で見た S3 テンプレートのような、とても基礎的なテンプレートのみに限定されてしまいます。
-
-### カバーするトピック
-
-このラボでは、以下の作業を行います。
-
-+ **[Ref](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html)** 関数を使って、パラメータをリソースのプロパティに動的に設定
-+ **[Fn::Join](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html)** 関数を使ったインスタンスのタグ付け
-+ **[Fn::Sub](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html)** 関数を使って、インスタンスにタグを追加
-
-### ラボの開始
-
-1. `code/workspace/` ディレクトリへ移動します。
-1. `intrinsic-functions.yaml` ファイルを開きます。
-1. 以下のトピックを進めながら、コードをコピーしていきます。
-
-:::alert{type="info"}
-組み込み関数はテンプレートの一部で使うことができます。組み込み関数が使えるのは、**リソースプロパティ、出力、メタデータ属性、および更新ポリシー属性** です。
-:::
-
-#### Ref
-
-前のラボでは、AMI ID を EC2 のリソースプロパティに「ハードコード」しています。もっと柔軟性が高いようにテンプレートを改善します。`AmiID` を変数とし、実行時にリソースプロパティにわたすようにします。
-
-1. まず、`AmiID` という新しいパラメータを作成し、テンプレート内の `Parameters` セクションに追加します。
-
- ```yaml
- AmiID:
- Type: AWS::EC2::Image::Id
- Description: 'The ID of the AMI.'
- ```
-
-1. `Ref` 組み込み関数を使い、`AmiID` パラメータの入力値を EC2 リソースのプロパティに渡します。
-
- ```yaml
- Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- # Use !Ref function in ImageId property
- ImageId: !Ref AmiID
- InstanceType: !Ref InstanceType
- ```
-
-#### Fn::Join
-
-AWS リソースの管理を容易にするため、任意にメタデータを **タグ** の形式で各リソースに付与することができます。タグとは、お客様が指定できる独自のキーと任意の値によって、目的、所有者、環境や他の目的にリソースを分類できるような単純なラベルです。ここではインスタンスに名前をつけるために、**Fn::Join** 組み込み関数を使いましょう。
-
-1. `Tags` プロパティを `Properties` セクションに追加します。
-1. Reference `InstanceType` パラメータを参照し、単語 _webserver_ をハイフン `-` で繋いだ文字列を `Tags` プロパティに追加します。
-
- ```yaml
- Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref AmiID
- InstanceType: !Ref InstanceType
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref InstanceType, webserver ] ]
- ```
-
-#### EC2 スタックの作成
-
-それでは、スタックを作成しましょう。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。`ParameterValue` の **MyAmiId** 値を先ほど `resources.yaml` で記載した値に置き換えます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-intrinsic-functions --template-body file://intrinsic-functions.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-intrinsic-functions/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
-1. `intrinsic-functions.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックの名前** (例:`cfn-workshop-intrinsic-functions`) を入力し、**次へ** をクリックします。
-1. **Type of EC2 Instance** はデフォルトの値をそのまま使います。
-1. **Amazon Machine Image ID** には、`resources.yaml` ファイルにハードコードした AMI ID からコピーして貼り付けて、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**送信** をクリックします。
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-
-**スタックの作成結果の確認方法**
-
-1. **[AWS EC2 console](https://console.aws.amazon.com/ec2)** のリンクをブラウザの新しいタブで開きます。
-1. 左側のメニューで、**インスタンス** をクリックします。
-1. **t2.micro-webserver** のインスタンス名を選択します。
-1. **タグ** タブを開き `Name` キーと `t2.micro-webserver` の値が表示されるはずです。
- 
-
-### チャレンジ
-`Fn::Sub` 組み込み関数を使って、インスタンスタイプを `InstanceType` という名前のついたタグを追加してください。
-
-`Fn::Sub` 組み込み関数の YAML の短縮形は `!Sub` です。
-
-::expand[**[Fn::Sub](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html)** 関数の AWS ドキュメントをご確認ください]{header="ヒントが必要ですか?"}
-
-::::::expand{header="解決策を確認しますか?"}
-テンプレートに `InstanceType` タグを追加します。
-
-```yaml
-Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref AmiID
- InstanceType: !Ref InstanceType
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref InstanceType, webserver ] ]
- - Key: InstanceType
- Value: !Sub ${InstanceType}
-```
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを更新します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。`ParameterValue` の **MyAmiId** 値を先ほど `resources.yaml` で記載した値に置き換えます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-intrinsic-functions --template-body file://intrinsic-functions.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
-:::
-1. `update-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-intrinsic-functions/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. スタック名 (例: `cfn-workshop-intrinsic-functions`) をクリックします。
-1. 画面右上の **更新** ボタンをクリックします。
-1. **テンプレートの準備** で、**既存テンプレートを置き換える** を選択します。
-1. **テンプレートの指定** で、 **テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックし、作業用ディレクトリに移動します。
-1. `intrinsic-functions.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **Type of EC2 Instance** はデフォルトの値をそのまま使います。
-1. **Amazon Machine Image ID** には、`resources.yaml` ファイルにハードコードした AMI ID からコピーして貼り付けて、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** ページで、一番下までスクロールし、**送信** をクリックします。
-1. スタックが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-最後に、EC2 コンソールでインスタンスの **タグ** タブで `InstanceType` タグが作られていることを確認します。
-::::::
-
-**Ref と Fn::Sub との比較**
-
-組み込み関数 Ref は、指定されたパラメーターまたはリソースの値を返します。テンプレートでリソースを宣言していて、別のテンプレートリソースを名前で指定する必要がある場合は、Ref を使用してそのリソースを参照できます。ほとんどは、Ref はリソースの名前を返します。
-
-YAML テンプレートの構文
-```
-Ref: logicalName
-```
-短縮形の構文 :
-```
-!Ref logicalName
-```
-
-組み込み関数 Fn::Sub は、入力文字列の変数を指定した値に置き換えます。テンプレートでは、この関数を使用して、スタックを作成または更新するまでに使用できない値を含むコマンドまたは出力を作成できます。
-
-YAML テンプレートの構文
-```
-Fn::Sub:
- - String
- - Var1Name: Var1Value
- Var2Name: Var2Value
-```
-
-### クリーンアップ
-
-以下の手順の通りに、このラボで作成したリソースを削除します。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** に移動します。
-1. CloudFormation の **スタック** ページで作成したスタック (例: `cfn-workshop-intrinsic-functions`) を選択します。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-1. スタックが **DELETE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-
----
-
-### まとめ
-おめでとうございます!これで無事にテンプレートで組み込み関数を使うことができました。
diff --git a/content/basics/templates/intrinsic-functions/index.md b/content/basics/templates/intrinsic-functions/index.md
deleted file mode 100644
index 4fb0ecc51..000000000
--- a/content/basics/templates/intrinsic-functions/index.md
+++ /dev/null
@@ -1,219 +0,0 @@
----
-title: "Intrinsic functions"
-weight: 400
----
-
-_Lab Duration: ~10 minutes_
-
----
-
-### Overview
-
-This lab shows how to use **[Intrinsic Functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)** in your template.
-
-Intrinsic functions are built-in functions that help you manage your stacks. Without them, you will be limited to very
-basic templates, similar to the S3 template you have seen in a **[Lab01](../template-and-stack)**.
-
-### Topics Covered
-
-In this Lab, you will:
-
-+ Use the **[Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html)** function to dynamically assign parameter values to a resource property.
-+ Tag an instance with **[Fn::Join](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html)** function.
-+ Add a tag to the instance using **[Fn::Sub](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html)** function.
-
-### Start Lab
-
-1. Go to the `code/workspace` directory.
-1. Open the `intrinsic-functions.yaml` file.
-1. Copy the code as you go through the topics below.
-
-:::alert{type="info"}
-Intrinsic functions can only be used in certain parts of a template. You can use intrinsic functions in
-**resource properties, outputs, metadata attributes, and update policy attributes**.
-:::
-
-#### Ref
-
-In the last lab you have "hard coded" an AMI ID directly into the EC2 Resource property. You will now amend this to make
-your template more flexible. Let's convert `AmiID` to variable and pass it to resource property at the runtime.
-
-1. First, create a new parameter called `AmiID` and put it in the `Parameters` section of your template.
-
- ```yaml
- AmiID:
- Type: AWS::EC2::Image::Id
- Description: 'The ID of the AMI.'
- ```
-
-1. Use the intrinsic function `Ref` to pass the `AmiID` parameter input to the EC2 resource property.
-
- ```yaml
- Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- # Use !Ref function in ImageId property
- ImageId: !Ref AmiID
- InstanceType: !Ref InstanceType
- ```
-
-#### Fn::Join
-
-To help you manage your AWS resources, you can optionally assign your own metadata to each resource in the form
-of **tags**. Each tag is a simple label consisting of a customer-defined key, and an optional value that can help you
-to categorize resources by purpose, owner, environment, or other criteria. Let's use the intrinsic function **Fn::Join** to name your instance.
-
-1. Add property `Tags` to the `Properties` section.
-1. Reference `InstanceType` parameter and add a word _webserver_, delimited with dash `-` to the tags' property.
-
- ```yaml
- Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref AmiID
- InstanceType: !Ref InstanceType
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref InstanceType, webserver ] ]
- ```
-
-#### Create EC2 stack
-
-Now it is time to create your stack.
-
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you. Replace the `ParameterValue` **MyAmiId** with the value you have hardcoded in `resources.yaml` file earlier.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-intrinsic-functions --template-body file://intrinsic-functions.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-intrinsic-functions/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. Select **Create stack** (_With new resources (Standard)_ if you have clicked in the top right corner).
-1. In **Prepare template**, choose **Template is ready**.
-1. In **Template source**, choose **Upload a template file**.
-1. Select **Choose file** button and navigate to your workshop directory.
-1. Select the file `intrinsic-functions.yaml` and click **Next**.
-1. Provide a **Stack name**. For example `cfn-workshop-intrinsic-functions`.
-1. For **Type of EC2 Instance** leave the default value in.
-1. For **Amazon Machine Image ID** copy and paste AMI ID you have hardcoded in `resources.yaml` file and click **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and click on **Submit**.
-1. You can click the **refresh** button a few times until you see in the status **CREATE_COMPLETE**.
-::::
-:::::
-
-
-**To see the result of the stack creation:**
-
-1. Open **[AWS EC2 console](https://console.aws.amazon.com/ec2)** link in a new tab of your browser.
-1. In the left-hand pane, click on **Instances**.
-1. Select the instance with a name **t2.micro-webserver**
-1. Go to the **Tags** tab, you should see there a key `Name` with a value `t2.micro-webserver`.
- 
-
-### Challenge
-Create another tag named `InstanceType` and use the `Fn::Sub` intrinsic function to return the type of the instance.
-
-The syntax for the YAML short form of the `Fn::Sub` intrinsic function is `!Sub`.
-
-::expand[Check out the AWS Documentation for **[Fn::Sub](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html)** function.]{header="Need a hint?"}
-
-::::::expand{header="Want to see the solution?"}
-Add the `InstanceType` tag to your template.
-```yaml
-Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref AmiID
- InstanceType: !Ref InstanceType
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref InstanceType, webserver ] ]
- - Key: InstanceType
- Value: !Sub ${InstanceType}
-```
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. Use the AWS CLI to update the stack. The required parameter `--template-body` have been pre-filled for you. Replace the `ParameterValue` **MyAmiId** with the value you have hardcoded in `resources.yaml` file earlier.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-intrinsic-functions --template-body file://intrinsic-functions.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
-:::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-intrinsic-functions/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. Select the stack name, for example **cfn-workshop-intrinsic-functions**.
-1. In the top right corner click on **Update**.
-1. In **Prepare template**, choose **Replace current template**.
-1. In **Specify template**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the file `intrinsic-functions.yaml` and click **Next**.
-1. For **Type of EC2 Instance** leave the default value in.
-1. For **Amazon Machine Image ID** copy and paste AMI ID you have hardcoded in `resources.yaml` file and click **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and click on **Submit**.
-1. You can click the **refresh** button a few times until you see in the status **UPDATE_COMPLETE**.
-::::
-:::::
-To Verify, Go to the **Tags** tab on EC2 Console, verify that `InstanceType` tag has been created.
-::::::
-
-**Comparison between Ref and Fn::Sub**
-
-The intrinsic function Ref returns the value of the specified parameter or resource. When you are declaring a resource in a template and you need to specify another template resource by name, you can use the Ref to refer to that other resource. In general, Ref returns the name of the resource.
-
-Syntax for YAML template
-```
-Ref: logicalName
-```
-Syntax for the short form:
-```
-!Ref logicalName
-```
-The intrinsic function Fn::Sub substitutes variables in an input string with values that you specify. In your templates, you can use this function to construct commands or outputs that include values that aren't available until you create or update a stack.
-
-Syntax for YAML template
-```
-Fn::Sub:
- - String
- - Var1Name: Var1Value
- Var2Name: Var2Value
-```
-
-### Clean up
-
-Follow these steps to clean up created resources:
-
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the stack you have created in this lab. For example `cfn-workshop-intrinsic-functions`.
-1. In the top right corner, select **Delete**.
-1. In the pop-up window, select **Delete**.
-1. Wait for the stack to reach the **DELETE_COMPLETE** status. You need to periodically select **Refresh** to see the latest stack status.
-
----
-
-### Conclusion
-Congratulations! You now have successfully used intrinsic functions in your template.
diff --git a/content/basics/templates/linting-and-testing/index.ja.md b/content/basics/templates/linting-and-testing/index.ja.md
deleted file mode 100644
index 5ea372349..000000000
--- a/content/basics/templates/linting-and-testing/index.ja.md
+++ /dev/null
@@ -1,234 +0,0 @@
----
-title: "静的解析とテスト"
-weight: 900
----
-
-_ラボ実施時間 : 15分程度_
-
-_チャレンジ : 3分程度_
-
----
-
-### 概要
-ソフトウェア開発ライフサイクル (Software Development Life Cycle, SDLC) の早い段階において CloudFormation テンプレートの静的解析 (lint) とテストをしておくことはベストプラクティスです。まず、自身のワークステーションで lint とテストのアクションを実行します。次に、テンプレートの lint とテストをパイプラインの継続的インテグレーション (Continuous Integration, CI) のフェーズに組み込みます。CI フェーズをコードプロモーションの最初の導入口として使うのです。
-
-このラボでは、自身のワークステーションから lint とテストのワークフローを実行する例にフォーカスします。[AWS CloudFormation Resource Specification](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html) に対してテンプレートの検証を行う [cfn-lint](https://github.com/aws-cloudformation/cfn-lint) のツールや、指定したリージョンにスタックを作成することでテストを行うことができる [taskcat](https://github.com/aws-ia/taskcat) に慣れることができます。
-
-### カバーするトピック
-このラボの修了でに次のことができるようになります。
-
-* テンプレートを検証するための `cfn-lint` を使えるようになります。
-* 検証エラーを見つけ修正する方法を理解できるようになります。
-* `taskcat` を使って指定したリージョンにスタックを作成してテンプレートをテストできるようになります。
-
-### 事前準備
-
-#### lint のための事前準備
-お好きな方法で `cfn-lint` を[インストールします](https://github.com/aws-cloudformation/cfn-lint#install)。例えば、次のように `pip` で `cfn-lint` をインストールできます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install cfn-lint
-:::
-
-::alert[このラボでは、`cfn-lint` をコマンドラインから実行します。他には、`cfn-lint` の IDE プラグインをこの[ページ](https://github.com/aws-cloudformation/cfn-lint#editor-plugins)のリストからインストールし、サポートされているエディタで `cfn-lint` からフィードバックを得られます。]{type="info"}
-
-インストールが完了したら、`cfn-lint` を実行できることを確認してください。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-lint --version
-:::
-
-#### テストの前提条件
-
-`pip` で `taskcat` を [インストール](https://aws-ia.github.io/taskcat/docs/INSTALLATION/)します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install taskcat
-:::
-
-::alert[この [note](https://aws-ia.github.io/taskcat/docs/INSTALLATION/#windows) によると、`taskcat` は Windows ではサポートされていません。Windows 10 を使用している場合は、この [ページ](https://aws-ia.github.io/taskcat/docs/INSTALLATION/#windows) の指示に従って、[Windows Subsystem for Linux](https://learn.microsoft.com/ja-jp/windows/wsl/about) (WSL) 環境内に `taskcat` をインストールしてください。]{type="info"}
-
-インストールが完了したら、`taskcat` を実行できることを確認します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-taskcat --version
-:::
-
-### ラボの開始
-
-#### テンプレートの lint
-
-このセクションでは、設定の検証を行うために、サンプルの CloudFormation テンプレートに対して `cfn-lint` を実行します。ゴールは、開発ライフサイクルの初期において、[AWS CloudFormation Resource Specification](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html) に対してテンプレートの内容の検証を行い、指定した値の妥当性をチェックし、多くのベストプラクティスのチェックに対してテンプレートを検証する機会になります。
-
-1. `code/workspace/linting-and-testing` ディレクトリに移動します。
-2. `vpc-and-security-group.yaml` CloudFormation テンプレートをお好きなエディタで開きます。サンプルテンプレートには、VPC の例と、その VPC を参照する VPC セキュリティグループの例が記載されています。このラボのスコープをシンプルにし、lint のユースケースにフォーカスするため、サンプルのテンプレートは他の VPC 関連のリソース (サブネット、インターネットゲートウェイ、ルートテーブル、ルートリソースなど) の記述をしていません。
-3. テンプレートに対し、`cfn-lint` を実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-lint vpc-and-security-group.yaml
-:::
-
-出力にエラーが表示されることをご確認ください。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-E3004 Circular Dependencies for resource SecurityGroup. Circular dependency with [SecurityGroup]
-[...]
-:::
-
-サンプルのテンプレートは循環依存 (circular dependency) のエラーを含んでいます。このようなエラーは、リソースプロパティの _値_ で、リソース自身の[論理 ID](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) を参照しているときに起きます。サンプルテンプレートを見てみると、`AWS::EC2::SecurityGroup` [タイプ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html) の `SecurityGroup` リソースで循環依存を持っていることがわかります。次のテンプレートの抜粋で示されているように、`SourceSecurityGroupId` プロパティは `SecurityGroup` リソース自身を参照しているからです。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-[...]
- SecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Example Security Group
- SecurityGroupIngress:
- - Description: Example rule to allow tcp/443 traffic from SecurityGroup
- FromPort: 443
- ToPort: 443
- IpProtocol: tcp
- SourceSecurityGroupId: !Ref SecurityGroup
-[...]
-:::
-
-この循環依存を解消するためには、セキュリティグループの `SecurityGroupIngress` に関連した設定を `AWS::EC2::SecurityGroupIngress` [タイプ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-ingress.html) の新しいリソースに移植します。テンプレートに追加するこのリソースの `SourceSecurityGroupId` プロパティ値には、`SecurityGroup` リソースを参照します。お好みのテキストエディタで `vpc-and-security-group.yaml` テンプレートを開き、`SecurityGroup` リソースの宣言ブロック全体を次の内容で置き換えてください。
-
-```yaml
- SecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Example Security Group
- SecurityGroupEgress:
- - Description: Example rule limiting egress traffic to 127.0.0.1/32
- CidrIp: 127.0.0.1/32
- IpProtocol: "-1"
- VpcId: !Ref Vpc
-
- SecurityGroupIngress:
- Type: AWS::EC2::SecurityGroupIngress
- Properties:
- Description: Example rule to allow tcp/443 traffic from SecurityGroup
- FromPort: 443
- ToPort: 443
- GroupId: !Ref SecurityGroup
- IpProtocol: tcp
- SourceSecurityGroupId: !Ref SecurityGroup
-```
-
-できたら、ファイルを保存してテンプレートを再び `cfn-lint` で検証し、エラーが修正されたことを確かめます。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-lint vpc-and-security-group.yaml
-:::
-
-おめでとうございます!`cfn-lint` ツールをテンプレートに対して実行し、ツールが検出したエラーを発見し修正しました!
-
-#### テンプレートのテスト
-
-`taskcat` を使用して、指定する AWS リージョンでテンプレートからスタックを作成し、テンプレートをテストします。`taskcat` で使いたいテスト設定値は [config files](https://aws-ia.github.io/taskcat/docs/usage/GENERAL_USAGE/#config-files) を使って記述できます。その設定プロパティは以下の通りに指定できます。
-
-* **[general](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#general) スコープ:** すべてのプロジェクトを対象としたグローバルスコープ。このユースケースでは、ホームディレクトリに `~/.taskcat.yml` ファイルを作成します。
-* **[project](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#project) スコープ:** プロジェクトのルートディレクトリに `.taskcat.yml` 設定ファイルを作成します。プロジェクトレベルのスコープで [tests](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#tests) 設定ディレクティブを使用することもできます。
-
-まず、`code/workspace/linting-and-testing` ディレクトリにある `.taskcat.yml` ファイルで _project_ と _tests_ のスコープを設定します。このファイルをお好みのテキストエディターで開き、以下のファイルの抜粋のように、`vpc-and-security-group.yaml` テンプレートをテストしたい AWS [regions](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#project_regions) の名前を指定します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-[...]
- regions:
- - us-east-1
- - us-east-2
-[...]
-:::
-
-完了したら、変更したファイルを保存します。
-
-::alert[`taskcat` の [要件](https://aws-ia.github.io/taskcat/docs/INSTALLATION/#requirements) の一部として、`Dockerfile` を使用して AWS Lambda 関数を構築する場合は Docker が必要になります。この機能はこのラボでは必要ありません。この機能は、`.taskcat.yml` ファイルの `package_lambda` [設定](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#project_package_lambda) が `false` に設定されているため無効になっています。]{type="info"}
-
-次に、`~/.taskcat.yml` 設定ファイルを __プロジェクトのバージョン管理パスの外にあるホームディレクトリ__ に作成します。このファイルには、すべてのプロジェクトについて構成設定を保存するので、バージョンコントロールに追加しません。なぜなら、使用する可能性がある機密値も含まれるからです。__機密値をバージョン管理に保存しないでください__。
-
-::alert[CloudFormation テンプレートから機密値を参照する方法については、[SSM Secure String パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm-secure-strings)と [Secrets Manager のシークレット](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-secretsmanager)を参照してください。]{type="info"}
-
-::alert[下位のスコープ (たとえば、`tests`) で記述した構成設定の値は、上位のスコープ (`project` や `general` など) よりも [優先](https://aws-ia.github.io/taskcat/docs/usage/GENERAL_USAGE/#precedence) になります。__逆に動作する `parameters` 設定は例外です__。つまり、`general` スコープで設定 `parameters` 設定の値が下位のスコープよりも優先されます。この後に `general` スコープの `parameters` の記述を説明します。]{type="info"}
-
-ホームディレクトリに新しく `~/.taskcat.yml` ファイルを作成します。このファイルには、`taskcat` がテストするテンプレートをアップロードするS3バケットの名前と、`VpcIpV4Cidr` サンプルテンプレートパラメータの `172.16.0.0/16` の値の例を指定します。
-::: code {language=shell showLineNumbers=False showCopyAction=True}
-~/.taskcat.yml をタッチしてください
-:::
-
-作成したファイルに次のコンテンツを追加します。必ず `YOUR_ACCOUNT_ID` にはご利用の [AWS アカウント ID](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/console_account-alias.html#FindingYourAWSId) に置き換えてください。
-
-```yaml
-general:
- s3_bucket: tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID
- parameters:
- VpcIpv4Cidr: 172.16.0.0/16
-```
-
-次に、AWS CLI を使用して、ファイルに指定した名前のバケットを作成します (ここも `YOUR_ACCOUNT_ID` を自分の値に置き換えてください)。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3 mb s3://tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID
-:::
-
-::alert[必要に応じて _general_、_project_、および _tests_ スコープで `s3_bucket` コンフィギュレーション設定を指定できます。`s3_bucket` プロパティを指定しない場合、テストを起動すると `taskcat` が自動的にバケットを作成します。]{type="info"}
-
-バケットを作成したら、次のコマンドを実行してテストを開始します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-taskcat test run
-:::
-
-`taskcat` がテストの実行を終了すると、`code/workspace/linting-and-testing/taskcat_outputs/index.html` ファイルにテストが正常に終了したことを確認できるレポートが出力されます。
-
-`code/solutions/linting-and-testing` パスには、`vpc-and-security-group.yaml`、`.taskcat.yml`、`.gitignore` というワークスペースファイル (必要に応じて更新してください) があります。
-
-> おめでとうございます!`taskcat` を使用して CloudFormation テンプレートのテストを 1 つ (または複数) のリージョンで実行しました!
-
-#### テンプレートテスト:ラボリソースのクリーンアップ
-
-[AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/) を使用して、このラボで作成したテスト用のリソースを削除します。まず、次の例のように、`taskcat` が S3 バケットにアップロードした *テンプレートファイルオブジェクトを削除します* (注意: `YOUR_ACCOUNT_ID` を自分の値に置き換えてください)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3api delete-object --bucket tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID --key linting-and-testing-workshop/vpc-and-security-group.yaml
-:::
-
-`vpc-and-security-group.yaml` と同じディレクトリに、このラボの _Challenge_ セクションで利用する別のテンプレート (`sqs-queue.yaml`) があります。先ほど行ったテスト実行の際に、`taskcat` がこのファイルもバケットにアップロードしてくれました。次の例に示すように、バケットから削除してください (`YOUR_ACCOUNT_ID` を自分の値に置き換えてください)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3api delete-object --bucket tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID --key linting-and-testing-workshop/sqs-queue.yaml
-:::
-
-次に、このラボ用に作成した**バケットを削除します**。この時点で、バケットには他のオブジェクトは含まれていないはずです。次のコマンドを実行します。必ず `YOUR_ACCOUNT_ID` を自分の値に置き換えてください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3api delete-bucket --bucket tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID
-:::
-
-必要に応じて、ホームディレクトリに作成した `~/.taskcat.yml` ファイルも削除してください。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-rm ~/.taskcat.yml
-:::
-
-### チャレンジ
-
-`AWS::SQS::Queue` [リソースタイプ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html) を記述したサンプルテンプレートのエラーを発見し修正してください。
-
-* 次のパスのテンプレートファイルを特定してください: `code/workspace/linting-and-testing/sqs-queue.yaml`
-* `cfn-lint` を使ってテンプレートのエラーを発見してください。
-* 問題を修正し、見つけた問題を修正したことを `cfn-lint` で確認してください。
-
-:::expand{header="ヒントが必要ですか?"}
-* `code/workspace/linting-and-testing` ディレクトリから, `cfn-lint sqs-queue.yaml` を実行し、サンプルテンプレートのエラーを見つけます。
-* `cfn-lint` コマンドの出力を参照し、`DelaySeconds` プロパティに指定する値を SQS のリソースドキュメント [ページ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#cfn-sqs-queue-delayseconds) から確認してください。
-* SQS キュー[プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#aws-resource-sqs-queue-properties)で利用可能な名前を確認してください。
-* SQS キューの[戻り値](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#aws-resource-sqs-queue-return-values) で利用可能な _属性_ 名を確認してください。
-:::
-
-:::expand{header="解決策を確認しますか?"}
-* `DelaySeconds` に `0` (デフォルト) か `900` を指定してください。
-* テンプレートの SQS リソースプロパティの `Tag` を `Tags` で置き換えてください。
-* キュー名を返すために、`Fn::GetAtt` で指定した属性を `Name` から `QueueName` に置き換えてください。
-* `code/workspace/linting-and-testing` ディレクトリで `cfn-lint sqs-queue.yaml` を実行し、これ以上エラーが出ないことを確認してください。
-
-完全な解答は `code/solutions/linting-and-testing/sqs-queue.yaml` のサンプルテンプレートで確認できます。
-:::
-
----
-### まとめ
-
-すばらいい!ワークステーションから `cfn-lint` と `taskcat` をコマンドラインから使ってサンプルテンプレートの検証を行いました。また、`cfn-lint` を使ってサンプルテンプレートのエラーを見つけ、`cfn-lint` から提供されたエラー情報を使ってテンプレートの問題を解決しました。より早いフィードバックループのために、`cfn-lint` はこの[ページ](https://github.com/aws-cloudformation/cfn-lint#editor-plugins)で示されているように、たくさんのコードエディタと統合することを選択できます。
diff --git a/content/basics/templates/linting-and-testing/index.md b/content/basics/templates/linting-and-testing/index.md
deleted file mode 100644
index ae642b456..000000000
--- a/content/basics/templates/linting-and-testing/index.md
+++ /dev/null
@@ -1,232 +0,0 @@
----
-title: "Linting and testing"
-weight: 900
----
-
-_Lab Duration: ~15 minutes_
-
-_Challenge: ~3 minutes._
----
-
-### Overview
-It is a best practice to lint and test your CloudFormation templates in early phases of the Software Development Life Cycle (SDLC). First, you run linting and testing actions for your templates on your workstation; next, you add template linting and testing practices to the Continuous Integration (CI) phase of your pipelines: you use the CI phase as an initial gating step for code promotion.
-
-In this lab, you will focus on an example linting and testing workflow you will run from your workstation. You will familiarize with tools such as [cfn-lint](https://github.com/aws-cloudformation/cfn-lint) to validate your template against the [AWS CloudFormation Resource Specification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html), and with [taskcat](https://github.com/aws-ia/taskcat), a tool that gives you the ability to test your templates by creating stacks off, of your templates, in regions you specify.
-
-### Topics Covered
-By the end of this lab, you will be able to:
-
-* Use `cfn-lint` to validate your templates.
-* Understand how to detect and fix validation issues.
-* Use `taskcat` to test your template by creating stacks in regions you specify.
-
-### Prerequisites
-
-#### Prerequisites for linting
-Choose to [install](https://github.com/aws-cloudformation/cfn-lint#install) `cfn-lint` with a method of your choice. For example, you can install `cfn-lint` with `pip`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install cfn-lint
-:::
-
-::alert[In this lab, you will invoke `cfn-lint` via the command line. You can also install an IDE plugin for `cfn-lint` from the ones listed on this [page](https://github.com/aws-cloudformation/cfn-lint#editor-plugins), to get feedback from `cfn-lint` in the supported editor.]{type="info"}
-
-After you have completed the installation, verify you can run `cfn-lint`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-lint --version
-:::
-
-#### Prerequisites for testing
-
-[Install](https://aws-ia.github.io/taskcat/docs/INSTALLATION/) `taskcat` with `pip`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install taskcat
-:::
-
-::alert[As per this [note](https://aws-ia.github.io/taskcat/docs/INSTALLATION/#windows), `taskcat` is not supported on Windows. If you are using Windows 10, follow instructions on this [page](https://aws-ia.github.io/taskcat/docs/INSTALLATION/#windows) to install `taskcat` inside a [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/about) (WSL) environment.]{type="info"}
-
-After you have completed the installation, verify you can run `taskcat`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-taskcat --version
-:::
-
-### Start Lab
-
-#### Template linting
-
-In this section, you will run `cfn-lint` against an example CloudFormation template to validate your configuration. Your goal is to validate, very early in the development life cycle, your template content against the [AWS CloudFormation Resource Specification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html) to check for valid values you can specify, and to also have an opportunity to validate the template against a number of best-practice checks:
-
-1. Change directory to the `code/workspace/linting-and-testing` directory.
-2. Open the `vpc-and-security-group.yaml` CloudFormation template in your favorite text editor. The sample template describes an example VPC and an example VPC Security Group that references the VPC. _Note that to keep a simple scope in this lab, that focuses on example linting use cases, the example template does not describe other VPC-related resources such as subnets, Internet Gateway, route table, and route resources._
-3. Run `cfn-lint` against the template:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-lint vpc-and-security-group.yaml
-:::
-
-In the output, you note an error:
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-E3004 Circular Dependencies for resource SecurityGroup. Circular dependency with [SecurityGroup]
-[...]
-:::
-
-The example template contains a circular dependency error: you get this type of error when you, in a resource property _value_, reference the [logical ID](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) of the resource itself. When you look at the sample template, you see it has a circular dependency for the `SecurityGroup` resource of the `AWS::EC2::SecurityGroup` [type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html), because the `SourceSecurityGroupId` property references the `SecurityGroup` resource itself, as shown in the following template excerpt:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-[...]
- SecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Example Security Group
- SecurityGroupIngress:
- - Description: Example rule to allow tcp/443 traffic from SecurityGroup
- FromPort: 443
- ToPort: 443
- IpProtocol: tcp
- SourceSecurityGroupId: !Ref SecurityGroup
-[...]
-:::
-
-To fix the circular dependency, move the `SecurityGroupIngress` related configuration of your Security Group into a new resource of the `AWS::EC2::SecurityGroupIngress` [type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-ingress.html): for the `SourceSecurityGroupId` property value of this resource you will add to your template, you will reference the `SecurityGroup` resource. With the `vpc-and-security-group.yaml` template opened in your favorite text editor, replace the whole `SecurityGroup` resource declaration block with content below:
-
-```yaml
- SecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Example Security Group
- SecurityGroupEgress:
- - Description: Example rule limiting egress traffic to 127.0.0.1/32
- CidrIp: 127.0.0.1/32
- IpProtocol: "-1"
- VpcId: !Ref Vpc
-
- SecurityGroupIngress:
- Type: AWS::EC2::SecurityGroupIngress
- Properties:
- Description: Example rule to allow tcp/443 traffic from SecurityGroup
- FromPort: 443
- ToPort: 443
- GroupId: !Ref SecurityGroup
- IpProtocol: tcp
- SourceSecurityGroupId: !Ref SecurityGroup
-```
-
-When done, save the file and validate the template again with `cfn-lint` to verify you fixed the error:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-lint vpc-and-security-group.yaml
-:::
-
-> Congratulations! You have run the `cfn-lint` tool against your template, and you found and fixed an error detected by the tool!
-
-#### Template testing
-You will now use `taskcat` to test your template by creating stacks off of it, in AWS regions you choose. You can describe test configuration values you wish to use with `taskcat` by using [config files](https://aws-ia.github.io/taskcat/docs/usage/GENERAL_USAGE/#config-files), whose configuration properties you have the choice to specify:
-
-* **[general](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#general) scope:** a global scope for all of your projects. For this use case, you create a `~/.taskcat.yml` file in your home directory;
-* **[project](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#project)-specific scope:** you create a `.taskcat.yml` configuration file in your project's root directory. You can also use [tests](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#tests) configuration directives at the project-level scope.
-
-Start with configuring _project_ and _tests_ scopes in the `.taskcat.yml` file located in the `code/workspace/linting-and-testing` directory. Open this file with your favorite test editor, and specify name(s) of AWS [regions](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#project_regions) where you want to test your `vpc-and-security-group.yaml` template, as shown in the file excerpt below:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-[...]
- regions:
- - us-east-1
- - us-east-2
-[...]
-:::
-
-When done, save the file with your changes.
-
-::alert[As part of [requirements](https://aws-ia.github.io/taskcat/docs/INSTALLATION/#requirements) for `taskcat`, you will need Docker if you are building AWS Lambda functions with a `Dockerfile`. You will not need this functionality for this lab, and this functionality has been disabled with the `package_lambda` configuration [setting](https://aws-ia.github.io/taskcat/docs/schema/taskcat_schema/#project_package_lambda) set to `false` in the `.taskcat.yml` file.]{type="info"}
-
-Next, you will create a `~/.taskcat.yml` configuration file __in your home directory, that is outside your projects' version control path__. In this file you will store, for all of your projects, configuration settings that you do not want to add to version control. This also includes any sensitive values you might have: __do not store sensitive values in version control__.
-
-::alert[For information on how to reference sensitive values from your CloudFormation templates, see [SSM secure string parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm-secure-strings) and [Secrets Manager secrets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-secretsmanager).]{type="info"}
-
-::alert[Values you pass to a given configuration setting you describe at a more specific scope (for example, in `tests`) will take [precedence](https://aws-ia.github.io/taskcat/docs/usage/GENERAL_USAGE/#precedence) over less specific scopes (such as `project` and `general`), __with the exception to the `parameters` setting that works the opposite way__ (that is, a `parameters` setting you describe in the `general` scope will have precedence over more specific scopes). You will see how `parameters` is described in a `general` section next.]{type="info"}
-
-**Create a new** `~/.taskcat.yml` file in your home directory. In this file, you will specify the name of your S3 bucket into which `taskcat` will upload your template to be tested, and an example value of `172.16.0.0/16` for the `VpcIpv4Cidr` example template parameter.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch ~/.taskcat.yml
-:::
-
-Add following content to the file you just created and, when you do so, make sure you replace the `YOUR_ACCOUNT_ID` example placeholder with your [AWS account ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/console_account-alias.html#FindingYourAWSId):
-```yaml
-general:
- s3_bucket: tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID
- parameters:
- VpcIpv4Cidr: 172.16.0.0/16
-```
-
-Next, use the AWS CLI to create your bucket whose name you just specified in the file (replace `YOUR_ACCOUNT_ID` with your value here as well):
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3 mb s3://tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID
-:::
-
-::alert[You can specify the `s3_bucket` configuration setting in _general_, _project_, and _tests_ scopes as needed. When you do not specify an `s3_bucket` property, `taskcat` will automatically create a bucket for you when you launch a test run.]{type="info"}
-
-After you have created the bucket, run the following command to start testing:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-taskcat test run
-:::
-
-Once `taskcat` has finished running tests, you should find successful test results in reports available in the `code/workspace/linting-and-testing/taskcat_outputs/index.html` file.
-
-You can find following workspace files (with updates, as needed): `vpc-and-security-group.yaml`, `.taskcat.yml`, and `.gitignore` in the `code/solutions/linting-and-testing` path.
-
-> Congratulations! You have run tests for your CloudFormation template in one (or more regions) with `taskcat`!
-
-
-#### Template testing: lab resources cleanup
-
-You can use the [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/) to remove resources you created in this lab for testing. First, **delete the template file object** that `taskcat` has uploaded for you into your S3 bucket, as in the following example (please note: replace `YOUR_ACCOUNT_ID` with your value):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3api delete-object --bucket tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID --key linting-and-testing-workshop/vpc-and-security-group.yaml
-:::
-
-In the same project workspace directory where you found the `vpc-and-security-group.yaml` example, there is another template (`sqs-queue.yaml`) that you will troubleshoot in the _Challenge_ section of this lab. As part of the test run you did earlier, `taskcat` has uploaded this file for you as well in your bucket: remove it from your bucket, as shown in the following example (replace `YOUR_ACCOUNT_ID` with your value):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3api delete-object --bucket tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID --key linting-and-testing-workshop/sqs-queue.yaml
-:::
-
-Next, **delete your bucket** you created for this lab. At this point, your bucket should not contain other objects. Run the following command, and make sure to replace `YOUR_ACCOUNT_ID` with your value:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3api delete-bucket --bucket tcat-linting-and-testing-workshop-YOUR_ACCOUNT_ID
-:::
-
-If needed, delete the `~/.taskcat.yml` file you created in your home directory as well.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-rm ~/.taskcat.yml
-:::
-
-### Challenge
-
-Find and fix errors in an example template that describes an `AWS::SQS::Queue` [resource type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html):
-
-* locate the template file available at this path: `code/workspace/linting-and-testing/sqs-queue.yaml`;
-* use `cfn-lint` to find errors in the template;
-* fix issues, and verify with `cfn-lint` that you have fixed issues you found.
-
-:::expand{header="Need a hint?"}
-* From the `code/workspace/linting-and-testing` directory, run `cfn-lint sqs-queue.yaml` to find errors in the example template;
-* refer to the `cfn-lint` command output, and to the SQS resource’s documentation [page](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#cfn-sqs-queue-delayseconds) for values you can specify for the `DelaySeconds` property;
-* see names for available SQS queue [properties](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#aws-resource-sqs-queue-properties);
-* see names of available _attributes_ for SQS queue [return values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#aws-resource-sqs-queue-return-values).
-:::
-
-:::expand{header="Want to see the solution?"}
-* Specify a value between `0` (default) and `900` for `DelaySeconds`;
-* replace `Tag` with `Tags` in the SQS resource property section of the template;
-* replace `Name` with `QueueName` as the attribute you specify for `Fn::GetAtt` to return the name of the queue;
-* from the `code/workspace/linting-and-testing` directory, run `cfn-lint sqs-queue.yaml` to verify there are no more errors.
-
-You can find the full solution in the `code/solutions/linting-and-testing/sqs-queue.yaml` example template.
-:::
-
----
-### Conclusion
-
-Great work! You have performed validation of example templates on your workstation using `cfn-lint` and `taskcat`, by using the command line. You have also used `cfn-lint` to find errors in an example template, and used error information provided by `cfn-lint` to fix template issues. For a faster feedback loop, you can choose to integrate `cfn-lint` with a number of code editors, as shown on this [page](https://github.com/aws-cloudformation/cfn-lint#editor-plugins).
diff --git a/content/basics/templates/mappings/index.ja.md b/content/basics/templates/mappings/index.ja.md
deleted file mode 100644
index 8721cbe4d..000000000
--- a/content/basics/templates/mappings/index.ja.md
+++ /dev/null
@@ -1,232 +0,0 @@
----
-title: "マッピング"
-weight: 600
----
-
-_ラボ実施時間 : 10分程度_
-
----
-
-### 概要
-
-このラボでは、**[マッピング](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html)** を紹介します。_マッピング_セクションは、CloudFormation テンプレートのトップレベルセクションで、テンプレートで参照できるキーと値のマップを定義します。
-
-
-
-マッピングセクションの簡単な例を以下に紹介します。`AnExampleMap` という 1 つのマップが含まれています。\
-`AnExampleMap` には、`TopLevelKey01`、`TopLevelKey02` と `TopLevelKey03` という 3 つのトップレベルキーが含まれています。\
-各トップレベルキーには、1 つ以上の `Key: Value` ペアが含まれています。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-Mappings:
- AnExampleMap:
- TopLevelKey01:
- Key01: Value01
- Key02: Value02
-
- TopLevelKey02:
- AnotherKey: AnExampleValue
-
- TopLevelKey03:
- AFinalKey: ADifferentValue
-:::
-
-### カバーされるトピック
-このラボでは、次のタスクを行います。
-
-+ _Test_ や _Prod_ などの環境タイプのマッピングを作成します。各環境タイプは異なるインスタンスタイプにマップされます。
-+ マッピングで必要な値を見つけ、EC2 リソースのプロパティセクションから参照します。
-
-### ラボの開始
-
-はじめに、自分のテンプレートに `Mappings` セクションを追加します。
-
-:::alert{type="info"}
-このラボのテンプレートは `code/workspace` にあります\
-編集前のテンプレートは `/workspace/mappings.yaml` です\
-最終的なテンプレートは `/solutions/mappings.yaml` です
-:::
-
-#### 1. _環境タイプ_ パラメータの追加から始めましょう
-
-このセクションでは、`Test` と `Prod` の 2 つの環境を定義します。新しいパラメーター名には `EnvironmentType` を使用します。
-
-テンプレートの _Parameters_ セクションで、`InstanceType` パラメータを以下のコードに置き換えてください。`InstanceType` パラメータはもう必要ありません。代わりにマッピングを使用します。
-
-```yaml
-Parameters:
- EnvironmentType:
- Description: 'Specify the Environment type of the stack.'
- Type: String
- Default: Test
- AllowedValues:
- - Test
- - Prod
- ConstraintDescription: 'Specify either Test or Prod.'
-```
-
-::alert[テンプレートの _ParameterGroups_ と _ParameterLabels_ セクションから `InstanceType` の削除も忘れないでください。]{type="info"}
-
-#### 2. 次に、マッピングセクションに _EnvironmentToInstanceType_ を作成します
-
-マップには、環境ごとに 1 つずつ、合計 2 つのトップレベルキーを含みます。各トップレベルキーには、`InstanceType` というセカンドレベルキーが 1 つ含まれています。
-
-```yaml
-Mappings:
- EnvironmentToInstanceType: # Map Name
- Test: # Top level key
- InstanceType: t2.micro # Second level key
- Prod:
- InstanceType: t2.small
-```
-
-#### 3. 次に、_InstanceType_ プロパティを変更します
-
-組み込み関数 `Fn::FindInMap` を使用すると、CloudFormation は `EnvironmentToInstanceType` マップから値を探し、`InstanceType` プロパティにセットします。
-
-```yaml
-Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref AmiID
- InstanceType: !FindInMap
- - EnvironmentToInstanceType # Map Name
- - !Ref EnvironmentType # Top Level Key
- - InstanceType # Second Level Key
-```
-
-#### 4. 次に、_Tags_ プロパティを更新します
-
-`InstanceType` パラメータを削除したので、タグを更新する必要があります。タグプの値に `EnviromentType` を参照します。
-
-```yaml
-Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref EnvironmentType, webserver ] ]
-```
-
-#### 5. 最後に、ソリューションをデプロイします
-
-テンプレートにマッピングセクションを追加したので、AWS コンソールに移動して CloudFormation スタックを作成します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。`ParameterValue` の **MyAmiId** 値を先ほど `resources.yaml` で記載した値に置き換えます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-mappings --template-body file://mappings.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-mappings/f5a16f40-eb42-11ed-8ce8-1246a18a4ddd"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
-1. `mappings.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックの名前** (例: `cfn-workshop-mappings`) を入力し、**次へ** をクリックします。
-1. **Amazon Machine Image ID** はそのままにしてください。
-1. **EnvironmentType** にはドロップダウンから環境の種類を選択します。例えば **Test** を選択して、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**送信** をクリックします。
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::::
-
-### チャレンジ
-
-テンプレートに `Dev` というもう一つの環境タイプを追加します。`Dev` キー名と `InstanceType: t2.nano` という名前と値のペアが含まれている必要があります。
-
-`EnvironmentType` パラメータで許可される値のリストに `Dev` を追加することを忘れないでください。
-
-:::expand{header="ヒントが必要ですか?"}
-1. `Parameters` セクションには
- * `Dev` を `EnvironmentType` の AllowedValues リストに追加
-1. `Mappings` セクションには
- * `Dev` のトップレベルキーを追加
- * 名前と値のペア `InstanceType: t2.nano` を追加
-:::
-
-::::::expand{header="解決策を確認しますか?"}
-```yaml
-Parameters:
- EnvironmentType:
- Description: 'Specify the Environment type of the stack.'
- Type: String
- Default: Test
- AllowedValues:
- - Dev
- - Test
- - Prod
- ConstraintDescription: 'Specify either Dev, Test or Prod.'
-
-Mappings:
- EnvironmentToInstanceType: # Map Name
- Dev:
- InstanceType: t2.nano
- Test: # Top level key
- InstanceType: t2.micro # Second level key
- Prod:
- InstanceType: t2.small
-```
-
-完全なソリューションは、`code/solutions/mappings.yaml` ファイルにあります。
-
-ソリューションの動作を確認するために、以下のステップを実施します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを更新します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。`ParameterValue` の **MyAmiId** 値を先ほど `resources.yaml` で記載した値に置き換えます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-mappings --template-body file://mappings.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId" ParameterKey="EnvironmentType",ParameterValue="Dev"
-:::
-1. `update-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-mappings/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. スタック名 (例: `cfn-workshop-ec2`) をクリックします。
-1. 画面右上の **更新** ボタンをクリックします。
-1. **テンプレートの準備** で、**既存テンプレートを置き換える** を選択します。
-1. **テンプレートの指定** で、 **テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックし、作業用ディレクトリに移動します。
-1. `mappings.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **Amazon Machine Image ID** はそのままにしてください。
-1. **EnvironmentType** にはプールダウンから **Dev** 環境を選択し、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** ページで、一番下までスクロールし、**送信** をクリックします。
-1. スタックが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-::alert[タイプを変更する前に EC2 インスタンスを停止する必要があるため、インスタンスタイプを変更するとダウンタイムが発生します。]{type="info"}
-::::::
-
-### クリーンアップ
-
-以下の手順で作成したリソースの削除を行います。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** に移動します。
-1. CloudFormation の **スタック** ページで `cfn-workshop-mappings` を選択します。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-1. スタックが **DELETE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-
----
-
-### まとめ
-
-素晴らしいです!これで、マッピングを使用してより柔軟な CloudFormation テンプレートを作成する方法を学習できました。
diff --git a/content/basics/templates/mappings/index.md b/content/basics/templates/mappings/index.md
deleted file mode 100644
index 08c0a8514..000000000
--- a/content/basics/templates/mappings/index.md
+++ /dev/null
@@ -1,235 +0,0 @@
----
-title: "Mappings"
-weight: 600
----
-
-_Lab Duration: ~10 minutes_
-
----
-
-### Overview
-
-This lab will introduce **[Mappings](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html)**.
-A _Mappings_ section is a top level section of a CloudFormation template. It is used to define maps, their keys and
-values which can be then referenced in your template.
-
-
-
-Here is a simplified example of a Mappings section. It contains one Map, `AnExampleMap`. \
-`AnExampleMap` contains three top level keys, `TopLevelKey01`, `TopLevelKey02` and `TopLevelKey03`. \
-Each top level key contains one or more `Key: Value` pairs.
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-Mappings:
- AnExampleMap:
- TopLevelKey01:
- Key01: Value01
- Key02: Value02
-
- TopLevelKey02:
- AnotherKey: AnExampleValue
-
- TopLevelKey03:
- AFinalKey: ADifferentValue
-:::
-
-### Topics Covered
-In this Lab, you will:
-
-+ Create a mapping for environment type such as _Test_ or _Prod_. Each environment type will be mapped to different instance type.
-+ Find the required value in mappings and reference it in properties section of the EC2 resource.
-
-### Start Lab
-
-You will now add a `Mappings` section to your own template.
-
-:::alert{type="info"}
-The templates for this lab can be found in `code/workspace`\
-The starting template is `/workspace/mappings.yaml` \
-The final template is `/solutions/mappings.yaml`
-:::
-
-#### 1. Let's start with creating _EnvironmentType_ parameter
-
-This section will define two possible environments, `Test` and `Prod`. It will use a new parameter, `EnvironmentType`.
-
-In the _Parameters_ section of the template. Replace the `InstanceType` parameter with the code below (you will not need the `InstanceType `parameter anymore. You will use the mapping instead).
-
-```yaml
-Parameters:
- EnvironmentType:
- Description: 'Specify the Environment type of the stack.'
- Type: String
- Default: Test
- AllowedValues:
- - Test
- - Prod
- ConstraintDescription: 'Specify either Test or Prod.'
-```
-
-::alert[Don't forget to remove `InstanceType` from the _ParameterGroups_ and _ParameterLabels_ sections of the template.]{type="info"}
-
-#### 2. Next, create _EnvironmentToInstanceType_ in the mapping section
-
-The map contains two top level keys, one for each environment. Each top level key contains a single `InstanceType` second level key.
-
-```yaml
-Mappings:
- EnvironmentToInstanceType: # Map Name
- Test: # Top level key
- InstanceType: t2.micro # Second level key
- Prod:
- InstanceType: t2.small
-```
-
-#### 3. Next, modify the _InstanceType_ property
-
-Using the intrinsic function `Fn::FindInMap`, CloudFormation will look up the value in the `EnvironmentToInstanceType`
-map and will return the value back to `InstanceType` property.
-
-```yaml
-Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref AmiID
- InstanceType: !FindInMap
- - EnvironmentToInstanceType # Map Name
- - !Ref EnvironmentType # Top Level Key
- - InstanceType # Second Level Key
-```
-
-#### 4. Next, update the _Tags_ property
-
-As you have deleted the `InstanceType` parameter, you will need to update the tag. Reference `EnviromentType` in the tag property.
-
-```yaml
-Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref EnvironmentType, webserver ] ]
-```
-
-#### 5. Finally, Deploy the solution
-
-Now that you have added a Mappings section to your template, go to the AWS console and create your CloudFormation Stack.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you. Replace the `ParameterValue` **MyAmiId** with the value you have hardcoded in `resources.yaml` file earlier.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-mappings --template-body file://mappings.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-mappings/f5a16f40-eb42-11ed-8ce8-1246a18a4ddd"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. In the CloudFormation console, select *Create stack With new resources (standard)*.
-1. In **Prepare template**, select **Template is ready**.
-1. In **Template source**, select **Upload a template file**.
-1. Select the file `mappings.yaml` and click **Next**.
-1. Enter a **Stack name**. For example, choose to specify `cfn-workshop-mappings`.
-1. For **Amazon Machine Image ID** leave the default value in.
-1. For **EnvironmentType** select the environment from drop down list, for example **Test** and click **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and click on **Submit**.
-1. You can click the **refresh** button a few times until you see in the status **CREATE_COMPLETE**.
-::::
-:::::
-
-
-### Challenge
-
-Add another Environment, `Dev`, to your template. It will need to contain `Dev` key name, and name-value pair `InstanceType: t2.nano`.
-
-Don't forget to add `Dev` to the list of allowed values for the `EnvironmentType` parameter.
-
-:::expand{header="Need a hint?"}
-1. In a `Parameters` section
- * Add `Dev` to the `EnvironmentType` AllowedValues list.
-1. In a `Mappings` section
- * Add a top level key of `Dev`.
- * Add a name-value pair `InstanceType: t2.nano`.
-:::
-
-::::::expand{header="Expand to see the solution"}
-```yaml
-Parameters:
- EnvironmentType:
- Description: 'Specify the Environment type of the stack.'
- Type: String
- Default: Test
- AllowedValues:
- - Dev
- - Test
- - Prod
- ConstraintDescription: 'Specify either Dev, Test or Prod.'
-
-Mappings:
- EnvironmentToInstanceType: # Map Name
- Dev:
- InstanceType: t2.nano
- Test: # Top level key
- InstanceType: t2.micro # Second level key
- Prod:
- InstanceType: t2.small
-```
-
-See `code/solutions/mappings.yaml` for the full solution.
-
-To test that your solution works, Follow below steps:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. Use the AWS CLI to update the stack. The required parameter `--template-body` have been pre-filled for you. Replace the `ParameterValue` **MyAmiId** with the value you have hardcoded in `resources.yaml` file earlier.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-mappings --template-body file://mappings.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId" ParameterKey="EnvironmentType",ParameterValue="Dev"
-:::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-mappings/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. Click on the stack name, for example **cfn-workshop-ec2**.
-1. In the top right corner click on **Update**.
-1. In **Prepare template**, choose **Replace current template**.
-1. In **Template source**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the file `mappings.yaml` and click **Next**.
-1. For **Amazon Machine Image ID** leave the default value in.
-1. For **EnvironmentType** select the environment **Dev** from drop down list and click **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and click on **Submit**.
-1. You can click the **refresh** button a few times until you see in the status **UPDATE_COMPLETE**.
-::::
-:::::
-::alert[Changing the instance type will cause some downtime as EC2 instance has to be stopped before changing the type.]{type="info"}
-::::::
-
-### Clean up
-
-Follow these steps to clean up created resources:
-
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the stack you have created in this lab. For example `cfn-workshop-mappings`.
-1. In the top right corner, select **Delete**.
-1. In the pop-up window, select **Delete**.
-1. Wait for the stack to reach the **DELETE_COMPLETE** status. You need to periodically select **Refresh** to see the latest stack status.
-
----
-
-### Conclusion
-
-Great work! You have now successfully learned how to use mappings to create more flexible CloudFormation templates.
diff --git a/content/basics/templates/outputs/index.ja.md b/content/basics/templates/outputs/index.ja.md
deleted file mode 100644
index ec6846f06..000000000
--- a/content/basics/templates/outputs/index.ja.md
+++ /dev/null
@@ -1,171 +0,0 @@
----
-title: "出力"
-weight: 700
----
-
-_ラボ実施時間 : 10分程度_
-
----
-
-### 概要
-
-このラボでは、**[出力](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html)** について学びます。_出力_ はスタック内のリソースの情報にアクセス可能にするセクションです。例えば、作成された EC2 インスタンスのパブリック DNS 名を出力することができます。
-
-さらに、出力値は他のスタックにインポートできます。クロススタック参照と呼びます。
-
-##### YAML 形式:
-_出力_ のセクションは `Outputs` のキー名とコロンから始まります。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-Outputs:
- Logical ID:
- Description: Information about the value
- Value: Value to return
- Export:
- Name: Value to export
-:::
-
-::alert[1 つのテンプレートで使用できる出力値の最大数については、[AWS CloudFormation のクォータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html)の出力の欄を参照してください。]{type="info"}
-
-### カバーするトピック
-このラボでは、次のことを実施します。
-
-+ Output セクションをテンプレートに作成し、インスタンスのパブリック DNS 名を出力します。
-+ Elastic IP リソースを作成し、EC2 インスタンスにアタッチします。
-+ AWS コンソールの CloudFormation で出力値をどのように見るかを学びます。
-
-### ラボの開始
-
-1. `code/workspace/` ディレクトリへ移動します。
-1. `outputs.yaml` ファイルを開きます。
-1. 以下のトピックを進みながら、コードをコピーしていきます。\
-インスタンスの _PublicDnsName_ を取得するには、`Fn::GetAtt` 組み込み関数を使う必要があります。
-1. まずは使用可能な属性について、[AWS ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#aws-properties-ec2-instance-return-values) を確認しましょう。_PublicDnsName_ は `Fn::GetAtt` で入手できるプロパティであることを確認できます。
-
- 以下のセクションをテンプレートに追加してください。
- ```yaml
- Outputs:
- EC2PublicDNS:
- Description: 'Public DNS of EC2 instance'
- Value: !GetAtt WebServerInstance.PublicDnsName
- ```
-
-1. この新しいテンプレートでスタックを作成します。
-
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **Code Editor のターミナル** で `code/workspace` に移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace
- :::
- 1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。`ParameterValue` の **MyAmiId** 値を先ほど `resources.yaml` で記載した値に置き換えます。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack --stack-name cfn-workshop-outputs --template-body file://outputs.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
- :::
- 1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-outputs/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
- 1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
- 1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
- 1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
- 1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
- 1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
- 1. `outputs.yaml` ファイルを指定し、**次へ** をクリックします。
- 1. **スタックの名前** (例: `cfn-workshop-outputs`) を入力し、**次へ** をクリックします。
- 1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
- 1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**送信** をクリックします。
- 1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
- ::::
- :::::
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)の _出力_ タブから出力値を確認します。
-
-### チャレンジ
-
-この練習問題では、Elastic IP リソースを作成し、EC2 インスタンスにアタッチします。そして、Elastic IP の出力値をテンプレートの _Outputs_ セクションに追加します。
-引き続き、`outputs.yaml` テンプレートを使用してください。
-
-1. `AWS::EC2::EIP` リソースを作成し、既存の EC2 インスタンスにアタッチしてください。
-1. `ElasticIP` と呼ばれる論理 ID を作成し、テンプレートの Outputs セクションに追加してください。
-1. テンプレートの変更をテストするために、スタックを更新してください。
-
-::expand[[AWS::EC2::EIP リソース](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-eip.html) の AWS ドキュメントを確認してください。]{header="ヒントが必要ですか?"}
-
-::::::expand{header="解決策を確認しますか?"}
- ```yaml
- Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref AmiID
- InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref EnvironmentType, InstanceType]
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref EnvironmentType, webserver ] ]
-
- WebServerEIP:
- Type: 'AWS::EC2::EIP'
- Properties:
- Domain: vpc
- InstanceId: !Ref WebServerInstance
-
- Outputs:
- WebServerPublicDNS:
- Description: 'Public DNS of EC2 instance'
- Value: !GetAtt WebServerInstance.PublicDnsName
-
- WebServerElasticIP:
- Description: 'Elastic IP assigned to EC2'
- Value: !Ref WebServerEIP
- ```
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace
- :::
-1. AWS CLI でスタックを更新します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。`ParameterValue` の **MyAmiId** 値を先ほど `resources.yaml` で記載した値に置き換えます。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-outputs --template-body file://outputs.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
- :::
-1. `update-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-outputs/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)の _出力_ タブから出力値を確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. スタック名 (例: `cfn-workshop-outputs`) をクリックします。
-1. 画面右上の **更新** ボタンをクリックします。
-1. **テンプレートの準備** で、**既存テンプレートを置き換える** を選択します。
-1. **テンプレートの指定** で、 **テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックし、作業用ディレクトリに移動します。
-1. `outputs.yaml` を指定し、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** ページで、一番下までスクロールし、**送信** をクリックします。
-1. スタックが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)の _出力_ タブから出力値を確認します。
-::::
-:::::
-::::::
-
-### クリーンアップ
-
-以下の手順で作成したリソースの削除を行います。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** に移動します。
-1. CloudFormation の **スタック** ページで `cfn-workshop-outputs` を選択します。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-1. スタックが **DELETE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-
----
-
-### まとめ
-
-すばらしいです!これで CloudFormation テンプレートで **出力** を使う方法を学ぶことができました。
diff --git a/content/basics/templates/outputs/index.md b/content/basics/templates/outputs/index.md
deleted file mode 100644
index fc07da24c..000000000
--- a/content/basics/templates/outputs/index.md
+++ /dev/null
@@ -1,174 +0,0 @@
----
-title: "Outputs"
-weight: 700
----
-
-_Lab Duration: ~10 minutes_
-
----
-
-### Overview
-
-In this lab you will learn about **[Outputs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html)**.
-_Outputs_ enable you to get access to information about resources within a stack. For example, you can output an EC2
-instance's Public DNS name once it is created.
-
-Furthermore, output values can be imported into other stacks. These are known as cross-stack references.
-
-##### YAML Syntax:
-The _Outputs_ section consists of the key name `Outputs`, followed by a colon.
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-Outputs:
- Logical ID:
- Description: Information about the value
- Value: Value to return
- Export:
- Name: Value to export
-:::
-
-::alert[For the maximum number of outputs you can declare in your template, see Outputs in [AWS CloudFormation quotas](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html).]{type="info"}
-
-### Topics Covered
-In this Lab, you will:
-
-+ Create an Output section in your template and return Public DNS name of the instance.
-+ Create Elastic IP resource and attach it to the EC2 instance.
-+ Learn how to view outputs from within CloudFormation in AWS console.
-
-### Start Lab
-
-1. Go to the `code/workspace` directory.
-1. Open the `outputs.yaml` file.
-1. Copy the code as you go through the topics below.
-1. To get the _PublicDnsName_ of the instance, you will need to use `Fn::GetAtt` intrinsic function. Let's first check
- the [AWS Documentation](https://docs.aws.amazon.com/en_pv/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#aws-properties-ec2-instance-return-values) for available attributes. You can see that _PublicDnsName_ is valid return value for `Fn::GetAtt` function.
-
- Add the section below to your template:
- ```yaml
- Outputs:
- EC2PublicDNS:
- Description: 'Public DNS of EC2 instance'
- Value: !GetAtt WebServerInstance.PublicDnsName
- ```
-
-1. Create the stack with new template.
-
-:::::tabs{variant="container"}
-
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you. Replace the `ParameterValue` **MyAmiId** with the value you have hardcoded in `resources.yaml` file earlier.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-outputs --template-body file://outputs.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-outputs/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. Choose **Create stack** (_With new resources (Standard)_) from the top-right side of the page.
-1. In **Prepare template**, choose **Template is ready**.
-1. In **Specify template**, choose **Upload a template file**.
-1. Select the **Choose file** button and navigate to your workshop directory.
-1. Select the file `outputs.yaml` and click **Next**.
-1. Provide a **Stack name**. For example `cfn-workshop-outputs`.
-1. Choose to accept default values for **Configure stack options**; choose **Next**.
-1. On the **Review ** page, scroll to the bottom and choose **Submit**.
-1. Use the **refresh** button to update the page as needed, until you see the stack has the **CREATE_COMPLETE** status.
-::::
-:::::
-
-View the output value on the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation), in the _Outputs_ tab.
-
-
-### Challenge
-
-In this exercise, you should assign an Elastic IP to your EC2 instance. Then, add an output of the Elastic IP to the
-_Outputs_ section of the template. You should continue using the `outputs.yaml` template.
-
-1. Create an `AWS::EC2::EIP` resource and attach it to your existing EC2 instance.
-1. Create a logical ID called `ElasticIP` and add it to the Outputs section of the template.
-1. Update the stack to test changes in your template.
-
-::expand[Check out the AWS Documentation for [AWS::EC2::EIP resource](https://docs.aws.amazon.com/en_pv/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-eip.html)]{header="Need a hint?"}
-
-::::::expand{header="Want to see the solution?"}
- ```yaml
- Resources:
- WebServerInstance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref AmiID
- InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref EnvironmentType, InstanceType]
- Tags:
- - Key: Name
- Value: !Join [ '-', [ !Ref EnvironmentType, webserver ] ]
-
- WebServerEIP:
- Type: 'AWS::EC2::EIP'
- Properties:
- Domain: vpc
- InstanceId: !Ref WebServerInstance
-
- Outputs:
- WebServerPublicDNS:
- Description: 'Public DNS of EC2 instance'
- Value: !GetAtt WebServerInstance.PublicDnsName
-
- WebServerElasticIP:
- Description: 'Elastic IP assigned to EC2'
- Value: !Ref WebServerEIP
- ```
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace
- :::
-1. Use the AWS CLI to update the stack. The required parameter `--template-body` have been pre-filled for you. Replace the `ParameterValue` **MyAmiId** with the value you have hardcoded in `resources.yaml` file earlier.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-outputs --template-body file://outputs.yaml --parameters ParameterKey="AmiID",ParameterValue="MyAmiId"
- :::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-outputs/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-1. View the output value on the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation), in the _Outputs_ tab.
-::::
-::::tab{id="local" label="Local development"}
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. Click on the stack name, for example **cfn-workshop-outputs**.
-1. In the top right corner click on **Update**.
-1. In **Prepare template**, choose **Template is ready**.
-1. In **Specify template**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the file `outputs.yaml` and click **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and click on **Submit**.
-1. You can click the **refresh** button a few times until you see in the status **UPDATE_COMPLETE**.
-1. View the output value on the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation), in the _Outputs_ tab.
-::::
-:::::
-::::::
-
-### Clean up
-
-Follow these steps to clean up created resources:
-
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the stack you have created in this lab. For example `cfn-workshop-outputs`.
-1. In the top right corner, select **Delete**.
-1. In the pop-up window, select **Delete stack**.
-1. Wait for the stack to reach the **DELETE_COMPLETE** status. You need to periodically select **Refresh** to see the latest stack status.
-
----
-
-### Conclusion
-Great work! You have now successfully learned how to use **Outputs** in CloudFormation template.
diff --git a/content/basics/templates/pseudo-parameters/index.ja.md b/content/basics/templates/pseudo-parameters/index.ja.md
deleted file mode 100644
index c64799980..000000000
--- a/content/basics/templates/pseudo-parameters/index.ja.md
+++ /dev/null
@@ -1,277 +0,0 @@
----
-title: "擬似パラメータ"
-weight: 500
----
-
-_ラボ実施時間 : 15分程度_
-
----
-
-### 概要
-このラボでは、**[擬似パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html)** を使って再利用可能なテンプレートの作り方について学びます。
-
-### カバーされるトピック
-このラボの完了までに次のことができるようになります。
-
-+ 疑似パラメータを活用してテンプレートの可搬性のベストプラクティスに則れるようになります。
-+ 疑似パラメータを活用するいくつかのサンプルユースケースを理解できます。
-
-CloudFormation テンプレートを使うとき、目的とすべきことの 1 つは AWS アカウントとリージョンをまたがってテンプレートを再利用しやすくするため、モジュラー化と再利用可能な CloudFormation テンプレートを作ることです。[CloudFormation パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)に加えて、[疑似パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html)を使うようにテンプレートを作ることもできます。疑似パラメータとは CloudFormation で定義されたパラメータです。
-
-疑似パラメータはパラメータと同じ様に使えます。例えば、[Ref 組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html)の引数として使うことができます。
-
-このモジュールでは、次の 3 つの疑似パラメータを使います。
-
-* [AWS::AccountId](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html#cfn-pseudo-param-accountid) - テンプレートからスタックを作る際に使用する AWS アカウントのアカウント ID を返します。
-* [AWS::Region](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html#cfn-pseudo-param-region) - テンプレートからスタックを作る際に使用するリージョンを返します。
-* [AWS::Partition](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html#cfn-pseudo-param-partition) - AWS パーティション名を返します。パーティションは、標準の AWS リージョンの場合、`aws` です。中国 (北京および寧夏) リージョンのパーティションは `aws-cn` で、AWS GovCloud (US-West) リージョンのパーティションは `aws-us-gov` です。
-
-::alert[利用可能な疑似パラメータについては、ドキュメントの [擬似パラメータ参照](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html)を参照してください。]{type="info"}
-
-それでは疑似パラメータを活用する方法について例を見ていきましょう。
-
-### ラボの開始
-* `code/workspace/pseudo-parameters` ディレクトリへ移動します。
-* `pseudo-parameters.yaml` ファイルを開きます。
-* ラボの以下のステップに沿って、テンプレートの内容を更新します。
-
-次の例では、[AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html#what-is-a-parameter) を使って、データベースのユーザ名など集中的に設定情報を保存します。このために、CloudFormation テンプレートでユーザ名の値を保存する `AWS::SSM::Parameter` リソースを記述します。
-
-そして、この Parameter Store の値を取得する [AWS Lambda 関数](https://aws.amazon.com/lambda/)に許可したいアクションを記述した IAM ポリシーを作成します。まず IAM ポリシーの記述からはじめ、作成した SSM パラメータを参照します。そのためには SSM パラメータの [Amazon リソースネーム (ARN)](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-arns-and-namespaces.html) を知る必要があります。
-
-まず、リソース (この場合は SSM パラメータ) の戻り値のセクションを確認します。関連する[ドキュメントページ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html#aws-resource-ssm-parameter-return-values)で、`Ref` がパラメータ名を返すことと、`Fn::GetAtt` がタイプや値を返すことを確認することができます。今日の時点では、そのリソースタイプの ARN は出力値として返すことができないので、ARN を構築するために擬似パラメータを活用することができます。
-
-擬似パラメータを使って、以下の例のような ARN を組み立てます。例えば、`dbUsername` と呼ばれるサンプルパラメータがあり、`us-east-1` リージョンで、`111122223333` AWS アカウントで構築をすることとします。サンプルパラメータの ARN は次の例のポリシースニペットのように組み立てられます。
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "ssm:GetParameters"
- ],
- "Resource": "arn:aws:ssm:us-east-1:111122223333:parameter/dbUsername"
- }
- ]
-}
-:::
-それでは、CloudFormation テンプレートに必要なリソースの記述をしていきます。
-
-まず、SSM パラメータの値として使えるように、テンプレートに[テンプレートパラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)を定義します。`Parameters` セクションに `DatabaseUsername` というテンプレートパラメータとします。
-
-`Resources` セクションでは `Ref` 組み込み関数を使ってテンプレートパラメータを参照します。下記の内容をコピーし、`pseudo-parameters.yaml` ファイルの既存の内容に追加します。
-```yaml
-Parameters:
- DatabaseUsername:
- AllowedPattern: ^[a-z0-9]{5,12}$
- Type: String
- Default: alice
- Description: Value to be used with the dbUsername SSM parameter. The default value is set to 'alice', which users can override when creating a CloudFormation stack.
-```
-
-次に、SSM パラメータの記述をしましょう。`Name` プロパティに `dbUsername` を指定し、`Value` プロパティに `Ref` を使って `DatabaseUsername` テンプレートパラメータを参照するように定義します。
-
-次のコードを既存のファイルの内容に追加してください。
-```yaml
-Resources:
- BasicParameter:
- Type: AWS::SSM::Parameter
- Properties:
- Name: dbUsername
- Type: String
- Value: !Ref DatabaseUsername
- Description: SSM Parameter for database username.
-```
-
-次に、上記で定義した SSM パラメータを参照するための IAM ロールとポリシーを指定します。
-次の内容をコピーし、`pseudo-parameters.yaml` ファイル の `Resources` セクションに追加してください。
-```yaml
-DemoRole:
- Type: AWS::IAM::Role
- Properties:
- AssumeRolePolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Effect: Allow
- Principal:
- Service:
- - lambda.amazonaws.com
- Action:
- - sts:AssumeRole
- Path: /
- Policies:
- - PolicyName: ssm-least-privilege
- PolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Effect: Allow
- Action: ssm:GetParameter
- Resource: '*'
-```
-
-上のスニペットの例では、デプロイする予定の Lambda 関数に関連付けする [実行ロール](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-intro-execution-role.html)を記述しています。このロールは Lambda 関数が SSM パラメータに対して `GetParameter` の実行を許可するものです。最小権限のベストプラクティスに沿うためには、IAM ポリシーのアクションのスコープを狭くし、上記で定義した SSM パラメータにはこの Lambda 関数からのアクセスしか許可しないようにする必要があります。
-
-上記の `Resource` 定義で `Resource: '*'` を使う代わりに、`AWS::Partition`、`AWS::Region`、`AWS::AccountId` 擬似パラメータを使って、組み立てるパラメータの ARN を指定します。[Fn::Sub](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) 組み込み関数は指定の文字列内の変数をその値に置換する関数です。この組み込み関数 (YAML 短縮形は `!Sub`) を使って、それぞれの擬似パラメータの値を置換していきます。組み立てる ARN には、Parameter Store リソースの名前も指定するので、`BasicParameter` というテンプレート内で記述している Parameter Store の[論理 ID](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) を参照します。
-
-`DemoRole` の `Policies` セクションを特定し、`Resouce: *` を含むすべての行を次で置き換えてください。
-```yaml
-Resource: !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${BasicParameter}'
-```
-
-最後に、`pseudo-parameters.yaml` テンプレートファイルの `Resources` セクションに以下のサンプルスニペットを追加します。このスニペットは、上記で定義した IAM ロールを使って、定義したばかりの SSM パラメータの読み取り権限を持つ Lambda 関数を定義しています。この Lambda 関数は `dbUsername` という SSM パラメータにアクセスできるかをテストするために、Lambda 関数を実行します。
-```yaml
-DemoLambdaFunction:
- Type: AWS::Lambda::Function
- Properties:
- Handler: index.lambda_handler
- Role: !GetAtt DemoRole.Arn
- Runtime: python3.12
- Code:
- ZipFile: |
- import boto3
- client = boto3.client('ssm')
-
- def lambda_handler(event, context):
- response = client.get_parameter(Name='dbUsername')
- print(f'SSM dbUsername parameter value: {response["Parameter"]["Value"]}')
-```
-上記の内容を使って、テンプレートを更新してください。次に [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation) を開き、このテンプレートを使ってスタックを作成してください。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace/pseudo-parameters` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/pseudo-parameters
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body`、`--capabilities` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-pseudo-parameters --template-body file://pseudo-parameters.yaml --capabilities CAPABILITY_NAMED_IAM
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-pseudo-parameters/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** ボタンをクリックし、作業用ディレクトリに移動します。
-1. `pseudo-parameters.yaml` を指定し、**次へ** をクリックします。
-1. **スタックの名前** (例: `cfn-workshop-pseudo-parameters`) を入力し、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** ページで、一番下までスクロールし、**AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。** チェックボックスをチェックし、**送信** をクリックします。
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::::
-
-CloudFormation コンソールのスタック画面で、リソースタブで作成されたリソースを確認できます。
-
-
-
-記述した IAM の許可が期待どおりであることを確認します。上記の画像に表示されているように、CloudFormation スタックの _リソース_ タブに `pseudo-parameters.yaml` テンプレートに記述した `DemoRole` を確認できます。`DemoRole` の物理 ID のリンクをクリックして開きます。ポリシー名の下のインラインポリシー `ssm-least-privilege` を展開します。
-
-
-
-CloudFormation テンプレートで記述した IAM ポリシーが表示されるはずです。パラメータの ARN も期待通りに組み立てられていることを確認してください。
-
-
-
-_リソース_ タブには、テンプレートで記述した Lambda 関数も確認できます。
-
-Lambda 関数がテンプレートに定義した SSM パラメータにアクセスできる許可を持っていることを確かめるためには、手動で Lambda 関数を[実行](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/testing-functions.html)します。
-
-CloudFormation スタックの _リソース_ タブに Lambda 関数の物理 ID のリンクをクリックして開きます。Lambda 関数のテスト実行のためには、まずテストイベントを作成する必要があります。`テスト`タブでデフォルトで提供されているテンプレートを使って、新しいテストイベントに名前を設定します。
-
-テストイベントを**保存**し、**テスト**をクリックして Lambda 関数を実行します。
-
-
-Lambda 関数の実行後、**実行結果**の下の _詳細_ を開くと、**ログ出力** のセクションに以下のような出力結果が表示されるはずです。
-
-
-
-上記のように `dbUsername` パラメータが `alice` であることを示す行を確認できます。これで、Lambda 関数に追加したロジックが期待通りパラメータにアクセスし、値を取得、表示していることを確認できました。
-
-### チャレンジ
-このラボでは CloudFormation テンプレートで擬似パラメータを使う方法について学びました。それでは、[Amazon S3 バケット](https://aws.amazon.com/jp/s3/) を CloudFormation テンプレートに追加したいとします。例えば、S3 バケットの名前として
-`YOUR_BUCKET_NAME_PREFIX-AWS_REGION-YOUR_ACCOUNT_ID` (例: `my-demo-bucket-us-east-1-111122223333`) のような形式になるように検討します。
-
-**タスク:** S3 バケットのリソースをテンプレートで記述してください。バケット名にプレフィックスを指定し、CloudFormation テンプレートパラメータで渡すようにしてください。テンプレートパラメータと擬似パラメータを使い、前述の形式になるようにバケット名を組み立ててください。
-
-:::expand{header="ヒントが必要ですか?"}
-- [テンプレートのパラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)のドキュメントを参考し、テンプレートで S3 バケット名のプレフィックスのためのパラメータを定義します。
-- バケット名を組み立てるときは、このラボで `!Sub` 組み込み関数で擬似パラメータを参照したように、テンプレートパラメータを参照します。例えば、テンプレートパラメータが `S3BucketNamePrefix` の場合、`!Sub '${S3BucketNamePrefix}'` となるように `!Sub` 組み込み関数で参照します。
-:::
-
-::::::expand{header="解決策を確認しますか?"}
-まず、_Parameters_ セクションに S3 バケットプレフィックスとして使うテンプレートパラメータ `S3BucketNamePrefix` を追加します。
-
-```yaml
-S3BucketNamePrefix:
- Description: The prefix to use for your S3 bucket
- Type: String
- Default: cfn-workshop
- AllowedPattern: ^(?!(^xn--|.$))^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$
- ConstraintDescription: Bucket name prefix can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-).
-```
-
-そして、`DemoBucket` リソースをテンプレートの _Resources_ セクションに追加します。
-
-```yaml
-DemoBucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketName: !Sub '${S3BucketNamePrefix}-${AWS::Region}-${AWS::AccountId}'
-```
-完成した解答コードは、`code/solutions/pseudo-parameters/pseudo-parameters.yaml` を見てください。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace/pseudo-parameters` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/pseudo-parameters
-:::
-1. AWS CLI でスタックを更新します。必要な `--stack-name`、`--template-body`、`--capabilities` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-pseudo-parameters --template-body file://pseudo-parameters.yaml --capabilities CAPABILITY_NAMED_IAM
-:::
-1. `update-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-pseudo-parameters/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-1. **[Amazon S3](https://console.aws.amazon.com/s3)** のコンソールを開いて、バケット名が `YOUR_BUCKET_NAME_PREFIX-AWS_REGION-YOUR_ACCOUNT_ID` の形になっていることを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. スタック名 (例: `cfn-workshop-pseudo-parameters`) をクリックします。
-1. 画面右上の **更新** ボタンをクリックします。
-1. **テンプレートの準備** で、**既存テンプレートを置き換える** を選択します。
-1. **テンプレートの指定** で、 **テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックし、作業用ディレクトリに移動します。
-1. `pseudo-parameters.yaml` を指定し、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** ページで、一番下までスクロールし、**AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。** チェックボックスをチェックし、**送信** をクリックします。
-1. スタックが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-1. **[Amazon S3](https://console.aws.amazon.com/s3)** のコンソールを開いて、バケット名が `YOUR_BUCKET_NAME_PREFIX-AWS_REGION-YOUR_ACCOUNT_ID` の形になっていることを確認します。
-::::
-:::::
-::::::
-
-### クリーンアップ
-
-次のステップに従って、作成したリソースを削除してください。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** に移動します。
-1. CloudFormation の **スタック** ページで `cfn-workshop-pseudo-parameters` を選択します。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-1. スタックが **DELETE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-
----
-
-### まとめ
-すばらしいです!これでより再利用可能な CloudFormation テンプレートを作るために擬似パラメータの使い方について学びました。より詳しい情報については、[擬似パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html)を参照してください。
diff --git a/content/basics/templates/pseudo-parameters/index.md b/content/basics/templates/pseudo-parameters/index.md
deleted file mode 100644
index 08f5d918a..000000000
--- a/content/basics/templates/pseudo-parameters/index.md
+++ /dev/null
@@ -1,300 +0,0 @@
----
-title: "Pseudo parameters"
-weight: 500
----
-
-_Lab Duration: ~15 minutes_
-
----
-
-### Overview
-In this lab, you will learn how to use [pseudo parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html) to write reusable templates.
-
-### Topics Covered
-By the end of this lab, you will be able to:
-
-+ Leverage pseudo parameters for template portability best practices
-+ Identify sample use cases for leveraging pseudo parameters
-
-When working with CloudFormation templates, one of the things you should aim for is to write modular and reusable templates to facilitate reuse of templates across AWS Accounts and Regions. In addition to [CloudFormation parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html), you can choose to engineer your template to use [pseudo parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html). Pseudo parameters are parameters predefined by CloudFormation.
-
-You can use a pseudo parameter the same way you use a parameter; for example, as an argument for the [Ref intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html).
-
-In this module, you will use the three pseudo parameters below:
-
-* [AWS::AccountId](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html#cfn-pseudo-param-accountid) -
- returns the Account ID of the Account you choose to create the stack off of your template.
-* [AWS::Region](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html#cfn-pseudo-param-region) -
- returns the name of the AWS Region where you choose to create the stack.
-* [AWS::Partition](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html#cfn-pseudo-param-partition) -
- returns the name of the AWS partition. The partition name for standard AWS Regions is `aws`; for the China (Beijing and Ningxia) Region is `aws-cn`, and for the AWS GovCloud (US-West) Region is `aws-us-gov`.
-
-::alert[For more information on available pseudo parameters, see the [pseudo parameters reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html) in the documentation.]{type="info"}
-
-Let’s walk through an example of how to leverage pseudo parameters.
-
-### Start Lab
-* Change directory to: `code/workspace/pseudo-parameters`.
-* Open the `pseudo-parameters.yaml` file.
-* Update the content of the template as you follow along steps on this lab.
-
-In the following example, use [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html#what-is-a-parameter)
-to centrally store a configuration information, such as the username for your database. For this, describe an `AWS::SSM::Parameter`
-resource in your CloudFormation template where you will store the username value.
-
-Then write an IAM policy to describe
-action(s) you wish to grant to an [AWS Lambda function](https://aws.amazon.com/lambda/) you will create and use to consume
-your parameter store value. Start with describing your IAM policy, where you reference the SSM parameter you created. This
-will require you to know the [Amazon Resource Name](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) (ARN) of the SSM parameter.
-
-First, check the return values section for the resource (the SSM parameter in this case): in the relevant [documentation page](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html#aws-resource-ssm-parameter-return-values), you see that `Ref` returns the parameter name, and `Fn::GetAtt` returns the type and the value. Since the ARN is not available as an output value for that resource type today, you can choose to leverage pseudo parameters to construct the ARN.
-
-You want to construct the resource ARN using pseudo parameters like the one in the following example. Let's say, for example, you have a sample parameter called `dbUsername` that you create in the `us-east-1` region, and in the AWS account `111122223333`; an example parameter ARN is constructed as in this example policy snippet:
-:::code{language=json showLineNumbers=false showCopyAction=false}
-{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "ssm:GetParameters"
- ],
- "Resource": "arn:aws:ssm:us-east-1:111122223333:parameter/dbUsername"
- }
- ]
-}
-:::
-Let's describe resources you need in your CloudFormation template.
-
-Start by defining a [template parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html),
-you will use as the value of the SSM parameter, that you'll define in the template. Start with a template parameter called
-`DatabaseUsername` under the `Parameters` section.
-
-Reference this template parameter in the `Resources` section by using the `Ref` intrinsic function. Copy
-the content shown below, and paste it in the `pseudo-parameters.yaml` file, by appending it to the existing file content:
-```yaml
-Parameters:
- DatabaseUsername:
- AllowedPattern: ^[a-z0-9]{5,12}$
- Type: String
- Default: alice
- Description: Value to be used with the dbUsername SSM parameter. The default value is set to 'alice', which users can override when creating a CloudFormation stack.
-```
-
-Now, let's describe an SSM parameter: set its `Name` property to `dbUsername`, and use `Ref` to reference the `DatabaseUsername`
-template parameter in the `Value` property.
-
-Append the following content to the existing file content:
-```yaml
-Resources:
- BasicParameter:
- Type: AWS::SSM::Parameter
- Properties:
- Name: dbUsername
- Type: String
- Value: !Ref DatabaseUsername
- Description: SSM Parameter for database username.
-```
-
-Next, let’s define the IAM role and policy from where you want to reference the SSM parameter you defined above.
-Copy the content below, and paste it in the `Resources` section of the `pseudo-parameters.yaml` file by appending it to the existing file content:
-```yaml
-DemoRole:
- Type: AWS::IAM::Role
- Properties:
- AssumeRolePolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Effect: Allow
- Principal:
- Service:
- - lambda.amazonaws.com
- Action:
- - sts:AssumeRole
- Path: /
- Policies:
- - PolicyName: ssm-least-privilege
- PolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Effect: Allow
- Action: ssm:GetParameter
- Resource: '*'
-```
-
-In the example snippet above, you have described an [execution role](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html)
-you will associate with a Lambda function you plan to deploy. The role allows your Lambda function to perform the `GetParameter`
-operation on your SSM parameters. To follow the best practice of the least privilege, scope down actions in your IAM policy,
-so to only allow access from the Lambda function, to SSM parameter you defined above.
-
-Instead of using `Resource: '*'` for the `Resource` definition above, specify the ARN of your parameter that you construct
-with `AWS::Partition`, `AWS::Region`, and `AWS::AccountId` pseudo parameters. The [Fn::Sub](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html)
-intrinsic function lets you substitute variables in an input string with values that you specify: you will use this intrinsic
-function (shown next in its `!Sub` YAML short form) to substitute values of pseudo parameters mentioned earlier. In the ARN you
-compose, you will also specify the name of your Parameter Store resource, by referencing it with `BasicParameter`, that is
-the [logical ID](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) of the
-Parameter Store resource you described in your template.
-
-Locate the `Policies` section for `DemoRole`; replace the whole line containing `Resource: '*'` with the following:
-```yaml
-Resource: !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${BasicParameter}'
-```
-
-Finally, add the example snippet below to the `Resources` section of the `pseudo-parameters.yaml` template file.
-The snippet defines a Lambda function that uses the IAM Role you defined above with permissions to read the SSM parameter,
-which you also defined above. You will invoke this Lambda function to test if the Lambda function can access the SSM parameter named `dbUsername`.
-```yaml
-DemoLambdaFunction:
- Type: AWS::Lambda::Function
- Properties:
- Handler: index.lambda_handler
- Role: !GetAtt DemoRole.Arn
- Runtime: python3.12
- Code:
- ZipFile: |
- import boto3
- client = boto3.client('ssm')
-
- def lambda_handler(event, context):
- response = client.get_parameter(Name='dbUsername')
- print(f'SSM dbUsername parameter value: {response["Parameter"]["Value"]}')
-```
-
-Save the template you have updated with content above. Next, navigate to the AWS CloudFormation [console](https://console.aws.amazon.com/cloudformation), and choose to create a stack using this template:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/pseudo-parameters`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/pseudo-parameters
-:::
-1. Use the AWS CLI to create the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-pseudo-parameters --template-body file://pseudo-parameters.yaml --capabilities CAPABILITY_NAMED_IAM
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-pseudo-parameters/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. In the CloudFormation console, select *Create stack With new resources (standard)*.
-1. In **Prepare template**, select **Template is ready**.
-1. In **Specify template**, select **Upload a template file**.
-1. Choose the `pseudo-parameters.yaml` template.
-1. Enter a **Stack name**. For example, choose to specify `cfn-workshop-pseudo-parameters`.
-1. Accept the **Configure stack options** default value, and choose **Next**.
-1. On the _Review_ page, scroll down to the bottom, and check the box under the following *Capabilities* section: **I acknowledge that AWS CloudFormation might create IAM resources.**
-1. Choose **Submit**. You can view the progress of the stack being created in the CloudFormation console.
-1. Wait until the stack creation is complete. Refresh the view in the console until you see your stack to be in the `CREATE_COMPLETE` status.
-::::
-:::::
-
-You should see new resources created under Resources tab in cloudformation stack console:
-
-
-
-Verify IAM permissions you described work as you expect. Under the _Resources_ tab for your CloudFormation stack, as shown in the picture above, find the `DemoRole` you described with the `pseudo-parameters.yaml` template. Choose to follow the link to the Physical ID of the `DemoRole`. Expand the inline policy `ssm-least-privilege` under the section for the policy name.
-
-
-
-You should see the IAM policy you described with your CloudFormation template. Verify that the ARN for your parameter is constructed as you expected.
-
-
-
-In the _Resources_ tab, you should also find the Lambda function you described with your template.
-
-To verify the Lambda function has permissions to access your SSM parameter you defined in the template,
-manually [invoke](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html#get-started-invoke-manually) your
-Lambda function.
-
-Follow the link to the _Physical ID_ of your Lambda function under the _Resources_ tab of CloudFormation stack. To invoke your Lambda function for testing, you'll first need to create a Test event. On the `Test` tab, give a name to a new Test event in the new event template provided by default.
-
-**Save changes** to your Test event, and then select **Test** to invoke the Lambda function.
-
-
-After you invoke the Lambda function, under the **Function Logs** section you should see output similar to the example shown next:
-
-
-
-You should see a line, similar to the one above, showing `alice` as the value for your `dbUsername` parameter: with this,
-you have verified that the logic you added to your Lambda function can access your parameter, and retrieve and print its value as you expected.
-
-### Challenge
-You’ve learned how to use pseudo parameters in your CloudFormation templates. Now let’s say you want to add an [Amazon S3 bucket](https://aws.amazon.com/s3/) to
-your CloudFormation template: for example, you choose the name of the S3 bucket to be as in the following format: `YOUR_BUCKET_NAME_PREFIX-AWS_REGION-YOUR_ACCOUNT_ID`, such as: `my-demo-bucket-us-east-1-111122223333`.
-
-**Task:** Describe an S3 bucket resource in your template. Add a prefix for your bucket name, and pass this prefix in as a CloudFormation template parameter. Use your template parameter and pseudo parameters to compose the bucket name as in the format mentioned earlier.
-
-:::expand{header="Need a hint?"}
-- See the documentation for [CloudFormation parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html), and define a parameter for your S3 bucket name prefix in your template.
-- When composing the bucket name, reference your CloudFormation parameter like you referenced pseudo parameters with the `!Sub` intrinsic function earlier. For example, if your template parameter is `S3BucketNamePrefix`, choose to reference it with the `!Sub` intrinsic function as follows: `!Sub '${S3BucketNamePrefix}'`
-:::
-
-::::::expand{header="Want to see the solution?"}
-First, under the _Parameters_ section, add a template parameter `S3BucketNamePrefix` to be used as the S3 bucket prefix you'll be creating.
-
-```yaml
-S3BucketNamePrefix:
- Description: The prefix to use for your S3 bucket
- Type: String
- Default: cfn-workshop
- AllowedPattern: ^(?!(^xn--|.$))^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$
- ConstraintDescription: Bucket name prefix can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-).
-```
-
-Then, add a `DemoBucket` resource under the _Resources_ section of the template.
-
-```yaml
-DemoBucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketName: !Sub '${S3BucketNamePrefix}-${AWS::Region}-${AWS::AccountId}'
-```
-See `code/solutions/pseudo-parameters/pseudo-parameters.yaml` for the full solution.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/pseudo-parameters`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/pseudo-parameters
-:::
-1. Use the AWS CLI to update the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name cfn-workshop-pseudo-parameters --template-body file://pseudo-parameters.yaml --capabilities CAPABILITY_NAMED_IAM
-:::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-pseudo-parameters/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-1. Open the **[Amazon S3](https://console.aws.amazon.com/s3)** console and verify your S3 bucket uses the `YOUR_BUCKET_NAME_PREFIX-AWS_REGION-YOUR_ACCOUNT_ID` format.
-::::
-::::tab{id="local" label="Local development"}
-1. Click on the stack name, for example **cfn-workshop-pseudo-parameters**.
-1. In the top right corner click on **Update**.
-1. In **Prepare template**, choose **Template is ready**.
-1. In **Specify template**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Choose the `pseudo-parameters.yaml` template.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and click on **Submit**.
-1. Wait until the stack creation is complete. Refresh the view in the console until you see your stack to be in the `UPDATE_COMPLETE` status.
-1. Open the **[Amazon S3](https://console.aws.amazon.com/s3)** console and verify your S3 bucket uses the `YOUR_BUCKET_NAME_PREFIX-AWS_REGION-YOUR_ACCOUNT_ID` format.
-::::
-:::::
-::::::
-
-### Clean up
-
-Follow these steps to clean up created resources:
-
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the stack you have created in this lab. For example `cfn-workshop-pseudo-parameters`.
-1. In the top right corner, select **Delete**.
-1. In the pop-up window, select **Delete**.
-1. Wait for the stack to reach the **DELETE_COMPLETE** status. You need to periodically select **Refresh** to see the latest stack status.
-
----
-### Conclusion
-Great job! You have learned how to use pseudo parameters to write more reusable CloudFormation templates. For more information, see [pseudo parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html).
diff --git a/content/basics/templates/resource-return-values/index.ja.md b/content/basics/templates/resource-return-values/index.ja.md
deleted file mode 100644
index 3c4fdfcd5..000000000
--- a/content/basics/templates/resource-return-values/index.ja.md
+++ /dev/null
@@ -1,223 +0,0 @@
----
-title: "戻り値の特定"
-weight: 800
----
-
-_ラボ実施時間 : 10分程度_
-
----
-
-### 概要
-[AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/) を使って、テンプレートによってリソースをプログラムで表現することができます。そうした場合、リソースを構成するために、同じテンプレートで定義されている特定のリソースの戻り値の参照が必要な場合があります。
-
-テンプレートの`出力`[セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html)で特定のリソースの戻り値を表示することもできます。その場合、出力値を[エクスポート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html)することで、同じリージョンの他のスタックから参照可能にすることもできます。
-
-### カバーするトピック
-このラボの完了までに次のことができるようになります。
-
-* 戻り値の使い方について理解します。
-* リソースタイプに応じて、戻り値を特定する方法を学びます。
-* 戻り値を使うときの `Ref`、`Fn::GetAtt`、`Fn::Sub` の[組み込み関数の](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html) 違いを理解します。
-
-戻り値については、リソースタイプ毎に [AWS リソースおよびプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)に記載されています。任意のリソースタイプをリストから選び、ページの右側の **Return values** から `Ref` や `Fn::GetAtt` の[組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)でどの値が利用可能かを見ることができます。
-
-[Amazon Simple Storage Service](https://aws.amazon.com/jp/s3/) (Amazon S3) バケットのリソースタイプ `AWS::S3::Bucket` を例として見てみましょう。[AWS リソースおよびプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)のリストから **Amazon Simple Storage Service** を選びます。次のページで **AWS::S3::Bucket** を選び、このリソースタイプのリファレンスドキュメントを見ます。ページ右側の **Return values** から `AWS::S3::Bucket` リソースタイプで使用可能な戻り値を見ることができます。
-
-ドキュメントにて、`Ref` や `Fn::GetAtt` の組み込み関数を使う場合に、どのような値が利用可能で返ってくるかを確認しましょう。例えば、バケット名を参照したい場合、バケットリソースの `Ref` に [論理 ID](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) を指定することで参照できます。もしバケットの [Amazon リソースネーム](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference-arns.html) (ARN) を取得したい場合は、`Fn::GetAtt` を `Arn` 属性と一緒にすることで取得できます。
-
-このラボでは、テンプレートで与えられているリソースタイプから、同じテンプレートにある別のリソースタイプの戻り値を参照する方法について学びます。
-
-### ラボの開始
-* `code/workspace/resource-return-values` ディレクトリへ移動します。
-* `resource-return-values.yaml` ファイルを開きます。
-* ラボの以下のトピックを進みながら、コードをコピーしていきます。
-
-このラボでは、次のことを実施します。
-* 1つのリソースのから同じテンプレート内の他のリソースの戻り値を活用する方法について学びます。
-* `Ref`、`Fn::GetAtt`、`Fn::Sub` の[組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)を使って、リソースの戻り値を活用して、どのようにスタックの出力値を定義するかを学びます。
-
-::alert[次の例では、Amazon S3 バケット名を表す `BucketName` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#cfn-s3-bucket-name) を定義していません。この場合、CloudFormation はリソースに一意の名前を生成します。]{type="info"}
-
-次で例のバケットポリシーでは、リクエストが `aws:SecureTransport: false` の条件に当てはまる場合に Amazon S3 へのアクセスを拒否します。次のポリシーは、リクエストが HTTPS の代わりに HTTP で行われたときに `Deny` の効果を持ちます。
-
-次のサンプルのテンプレートスニペットをコピーして `resource-return-values.yaml` ファイルに追記してください。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- Tags:
- - Key: Purpose
- Value: AWS CloudFormation Workshop
-
- S3BucketPolicy:
- Type: AWS::S3::BucketPolicy
- Properties:
- Bucket: !Ref S3Bucket
- PolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Action:
- - s3:*
- Effect: Deny
- Resource:
- - !GetAtt S3Bucket.Arn
- - !Sub '${S3Bucket.Arn}/*'
- Principal: '*'
- Condition:
- Bool:
- aws:SecureTransport: false
-
-Outputs:
- S3BucketDomainName:
- Description: IPv4 DNS name of the bucket.
- Value: !GetAtt S3Bucket.DomainName
-:::
-
-テンプレートに貼り付けたテンプレートスニペットには Amazon S3 [バケット](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html) とバケット[ポリシー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-policy.html)の 2 つのリソースがあります。次に解説します。
-
-* バケットリソースの[論理 ID](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html#resources-section-structure-resource-fields) (つまり `S3Bucket`) は、`S3BucketPolicy` リソースの `Bucket` プロパティで `Ref` 組み込み関数で参照されています。`Bucket` プロパティはポリシーを適用する Amazon S3 バケットの名前が必要です。バケットリソースの論理 ID を `Ref` 関数で指定した場合、バケットリソースはバケット名を返します。詳細は、Amazon S3 バケットの [戻り値](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-return-values) を参照してください。
-* `S3BucketPolicy` リソースの `PolicyDocument` プロパティの `Resource` セクションはバケットの [Amazon リソースネーム](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference-arns.html) (ARN) が必要です。そして、`AWS::S3::Bucket` リソースタイプは、`Fn::GetAtt` 組み込み関数をバケットの論理 ID と `Arn` 属性を使うことでバケットの ARN を返します。
-* Amazon S3 バケットの [戻り値](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-return-values)を参照してください。`AWS::S3::Bucket` リソースタイプには `Fn::GetAtt` 組み込み関数と共に必要な属性を指定することで返される多くの値があります。例えば、上述のテンプレートスニペットの `Outputs` [セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) の `S3BucketDomainName` の出力値を見てください。ここでは、テンプレートに記述されたバケットの DNS 名を出力することを意味しています。バケットの IPv4 DNS 名は `Fn::GetAtt` 組み込み関数に対し、バケットリソースの論理 ID と `DomainName` 属性を指定することで取得できます。
-* ここで、`S3BucketPolicy` リソースの `PolicyDocument` プロパティの `Resource` 属性で使われた `Fn::Sub` 組み込み関数について議論します。`Fn::Sub` 組み込み関数は、`Ref` と `Fn::GetAtt` が特定のリソースに対し論理 ID と戻り値の属性という同じ形式を使って、返す値を取得するのに使うことができます。`Fn::Sub` を戻り値と一緒に使う主目的は、文字列と戻り値を結合することです。上記の例では、`Fn::Sub` を `/*` と戻り値のバケット ARN と結合するために使っています。バケット ARN の最後に `/*` を足す理由は、ポリシーで定義されているアクションがバケット内のすべてのオブジェクトに適用されることを確実にすることです。
-
-それでは、`resource-return-values.yaml` テンプレートを使ってスタックを作成し、ここまで説明してきた動作を実際に見ていきます。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/resource-return-values
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-resource-return-values --template-body file://resource-return-values.yaml
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-return-values/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
-1. `resource-return-values.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックの名前** (例: `cfn-workshop-resource-return-values`) を入力し、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**送信** をクリックします。
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-
-それでは、スタックイベントと出力値を見ていきます。スタックイベントは次の画像のようになっているはずです。
-
-
-スタックイベントを見ていると、バケットとバケットポリシーが無事に作られていることがわかります。ここで、スタックの**リソース**タブに移動して `S3Bucket` の物理 ID を見つけ、リンクをクリックしてください。[Amazon S3 コンソール](https://console.aws.amazon.com/s3/)のバケットの詳細ページに移動できます。次に、バケットのページで**アクセス許可**を選び**バケットポリシー**セクションのバケットポリシーを確認してください。バケットポリシーの `Resource` セクションで戻り値がどのように置換されているかを見てください。次に、AWS CloudFormation コンソールのスタックの**出力**タブに移動し、表示されているスタックで作成した Amazon S3 バケットの IPv4 DNS 名を確認してください。
-
-おめでとうございます!これで特定のリソースの戻り値を見つける方法と、それらを他のリソースで `Ref`、`Fn::GetAtt`、`Fn::Sub` の[組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)で使う方法を学びました。
-
-### チャレンジ
-このチャレンジでは、既存の Amazon EC2 [インスタンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html)と [セキュリティグループ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html)が記述されたテンプレートを更新することがタスクになります。Amazon EC2 インスタンスリソースの `SecurityGroups` プロパティでセキュリティグループの論理 ID を参照することになります。また、テンプレートの `Outputs` セクションを更新し、次の値を出力することになります。
-
-* スタックで作成された Amazon EC2 インスタンスのインスタンス ID
-* 作成された Amazon EC2 インスタンスのパブリック IP
-* スタックで作成されたセキュリティグループの ID
-
-初めに、`code/workspace/resource-return-values` ディレクトリ内の `resource-return-values-challenge.yaml` テンプレートをお好みのエディタで開いてください。上記のサンプルの要件に従い、テンプレートを適切に更新してください。
-
-準備ができたら、更新した `resource-return-values-challenge.yaml` テンプレートで `resource-return-values-challenge` と呼ばれる新しいスタックを作成し、要件を満たしているかを確認してください。
-
-:::expand{header="ヒントが必要ですか?"}
-* Amazon EC2 インスタンスの `SecurityGroups` プロパティでセキュリティグループをどのように[参照](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)できるでしょうか?
-* セキュリティグループを参照する際、`SecurityGroups` プロパティの `Type` の値が *List of String* であることに気をつけてください。YAML 形式でどのように表現するでしょうか?
-* Amazon EC2 インスタンスの[戻り値](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#aws-properties-ec2-instance-return-values) とセキュリティグループの[戻り値](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html#aws-properties-ec2-security-group-return-values)を確認し、`Ref` や `Fn::GetAtt` の[組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)でどのような値が返るかを見てください。
-:::
-
-::::::expand{header="解決策を確認しますか?"}
-* `Ref` 組み込み関数を使って、インスタンスリソースの `SecurityGroups` プロパティにセキュリティグループの論理 ID をリストアイテムとして指定してください。
-* Amazon EC2 インスタンスリソースを次の定義のように修正してください。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Ec2Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- SecurityGroups:
- - !Ref InstanceSecurityGroup
- Tags:
- - Key: Name
- Value: Resource-return-values-workshop
-:::
-
-* `Ref` 組み込み関数を使い、インスタンス ID を取得するために Amazon EC2 インスタンスリソースの論理 ID を渡してください。同様にインスタンスのパブリック IP を取得するために、Amazon EC2 インスタンスリソースの論理 ID と `PublicIp` 属性を `Fn::GetAtt` 関数に渡します。
-* セキュリティグループの ID を取得するために、セキュリティグループリソースの論理 ID と `GroupId` 属性を `Fn::GetAtt` 関数に渡します。
-* テンプレートの `Outputs` セクションを次のように修正します。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Outputs:
- InstanceID:
- Description: The ID of the launched instance
- Value: !Ref Ec2Instance
-
- PublicIP:
- Description: Public IP of the launched instance
- Value: !GetAtt Ec2Instance.PublicIp
-
- SecurityGroupId:
- Description: ID of the security group created
- Value: !GetAtt InstanceSecurityGroup.GroupId
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace/resource-return-values` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/resource-return-values
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-resource-return-values-challenge --template-body file://resource-return-values-challenge.yaml
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-return-values-challenge/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-1. [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation) の _出力_ タブで出力値を確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
-1. `resource-return-values-challenge.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックの名前** (例: `cfn-workshop-resource-return-values-challenge`) を入力し、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**送信** をクリックします。
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-1. [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation) の _出力_ タブで出力値を確認します。
-::::
-:::::
-::::::
-
-このチャレンジの完全な解答は `code/solutions/resource-return-values/resource-return-values-challenge.yaml` テンプレートにあります。
-
-### クリーンアップ
-
-次のステップに従って、このラボの各パートで作成した[スタックを削除](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html)してください。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** に移動してください。
-2. CloudFormation コンソールの **スタック**ページで、`cfn-workshop-resource-return-values` を選択してください。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-4. 同様の手順で `cfn-workshop-resource-return-values-challenge` スタックを削除してください。
-
----
-
-### まとめ
-すばらしいです!これで特定のリソースの戻り値を見つける方法と、それらを他のリソースで `Ref`、`Fn::GetAtt`、`Fn::Sub` の[組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)で使う方法を学びました。
diff --git a/content/basics/templates/resource-return-values/index.md b/content/basics/templates/resource-return-values/index.md
deleted file mode 100644
index 1eae8c90b..000000000
--- a/content/basics/templates/resource-return-values/index.md
+++ /dev/null
@@ -1,220 +0,0 @@
----
-title: "Finding return values"
-weight: 800
----
-
-_Lab Duration: ~10 minutes_
-
----
-
-### Overview
-You use [AWS CloudFormation](https://aws.amazon.com/cloudformation/) to programmatically describe your resources in your templates. When you do so, you might also need to reference return values, for a given resource, from another resource or resources that you also describe in the same template, and that depend on the given resource.
-
-You can also choose to display a given resource’s return value(s) in the `Outputs` [section](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) of your template: when you do so, you also have the choice to make a given output value available to other stacks in the same region by [exporting](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) the output.
-
-### Topics Covered
-By the end of this lab, you will be able to:
-
-* Understand the usage of return values.
-* Learn how to search for return values for different resource types.
-* Understand the difference between using `Ref`, `Fn::GetAtt`, and `Fn::Sub` [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html) when using return values.
-
-Return values are documented in the [AWS resource and property types reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) for a given resource type: choose any resource type from the list, and then choose **Return Values** on the right side of the page to see which values you can use with [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html) such as `Ref` and `Fn::GetAtt`.
-
-Let’s take an [Amazon Simple Storage Service](https://aws.amazon.com/s3/) (Amazon S3) bucket resource type, `AWS::S3::Bucket`, as an example: choose **Amazon Simple Storage Service** from the list under [AWS resource and property types reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html). On the next page, choose **AWS::S3::Bucket** to view the reference documentation for the resource type: on the right pane of the page, choose **Return Values** to view available return values for the `AWS::S3::Bucket` resource type.
-
-Follow through the document to understand what available values are returned when you use `Ref` or `Fn::GetAtt` intrinsic functions. For example, if you want to reference the bucket name, use `Ref` followed by the [logical ID](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) of your bucket resource; if you wish to retrieve the [Amazon Resource Name](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) (ARN) of your bucket, use `Fn::GetAtt` with the `Arn` attribute.
-
-In this lab, you will learn how to reference, from a given resource type you describe in your template, return values for another resource type that you also describe in the same template.
-
-### Start Lab
-* Change directory to `code/workspace/resource-return-values`.
-* Open the `resource-return-values.yaml` file.
-* Update the content of the template as you follow along steps on this lab.
-
-In this lab, you will:
-
-* Learn how to utilize return values of a resource in other resource described in the same template.
-* Learn how you can define stack outputs based on the resource return values using `Ref`, `Fn::GetAtt` and `Fn::Sub` [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html).
-
-::alert[The example shown next does not include the `BucketName` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#cfn-s3-bucket-name) for the Amazon S3 bucket. In this case, CloudFormation will generate a unique name for the given resource.]{type="info"}
-
-The bucket policy in the example shown next denies access to the Amazon S3 bucket when a request meets the `aws\:SecureTransport: false` condition. The policy below uses the `Deny` effect when a request is made via HTTP instead of HTTPS.
-
-Copy and append the example template snippet shown next to the `resource-return-values.yaml` file:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- Tags:
- - Key: Purpose
- Value: AWS CloudFormation Workshop
-
- S3BucketPolicy:
- Type: AWS::S3::BucketPolicy
- Properties:
- Bucket: !Ref S3Bucket
- PolicyDocument:
- Version: "2012-10-17"
- Statement:
- - Action:
- - s3:*
- Effect: Deny
- Resource:
- - !GetAtt S3Bucket.Arn
- - !Sub '${S3Bucket.Arn}/*'
- Principal: '*'
- Condition:
- Bool:
- aws:SecureTransport: false
-
-Outputs:
- S3BucketDomainName:
- Description: IPv4 DNS name of the bucket.
- Value: !GetAtt S3Bucket.DomainName
-:::
-
-There are two resources in the template snippet you pasted into your template: an Amazon S3 [bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html) and a bucket [policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-policy.html). Note the following:
-
-* The [logical ID](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html#resources-section-structure-resource-fields) of the bucket resource (i.e., `S3Bucket` in the above example), is referenced with the `Ref` intrinsic function in the `Bucket` property of the `S3BucketPolicy` resource. The `Bucket` property requires the name of the Amazon S3 bucket to which the policy applies. The bucket resource returns the name of the bucket when you specify the logical ID of the bucket resource with the `Ref` function. For more information, see Amazon S3 bucket [return values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-return-values).
-* Note the `Resource` section for the `PolicyDocument` property of `S3BucketPolicy`: `Resource` requires the [Amazon Resource Name](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) (ARN) of the bucket. Refer to the Amazon S3 bucket [return values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-return-values), and note that the `AWS::S3::Bucket` resource type returns the ARN of the bucket when you use the `Fn::GetAtt` intrinsic function, along with the logical ID of the bucket and the `Arn` attribute.
-* Refer to the Amazon S3 bucket [return values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-return-values): note that there are a number of values being returned by the `AWS::S3::Bucket` resource type when you specify the required attribute along with the `Fn::GetAtt` intrinsic function. As an example, see the `S3BucketDomainName` output described in the `Outputs` [section](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) of the template snippet shown above. Here, the intent is to output the DNS name of the bucket you describe in your template. The IPv4 DNS name of the bucket is returned when you specify the logical ID of the bucket resource, along with the `DomainName` attribute for the `Fn::GetAtt` intrinsic function.
-* Now, let’s discuss the `Fn::Sub` intrinsic function, used above in the `Resource` attribute of the `PolicyDocument` property for the `S3BucketPolicy` resource. The `Fn::Sub` intrinsic function can be used to retrieve values that `Ref` and `Fn::GetAtt` return for a specified resource using the same format of logical ID and return value attribute. The main purpose of using `Fn::Sub` with return values is to concatenate string(s) to the returned value(s). In the above example, you use `Fn::Sub` to concatenate `/*` to the returned bucket ARN: the reason for adding `/*` at the end of the bucket ARN is to make sure the actions defined in the policy are applied to all the objects in the bucket.
-
-Let’s create a stack using the `resource-return-values.yaml` template, and see the above in action!
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/resource-return-values`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/resource-return-values
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-resource-return-values --template-body file://resource-return-values.yaml
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-return-values/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. In the CloudFormation console, select **Create stack With new resources (standard)**.
-1. In **Prepare template**, choose **Template is ready**.
-1. In **Template source**, select **Upload a template file**.
-1. Upload the `resource-return-values.yaml` template, and choose **Next**.
-1. Enter a stack name. For example, `cfn-workshop-resource-return-values`. When ready, choose **Next**.
-1. Choose to accept default values on the **Configure stack options** page; scroll to the bottom of the page, and choose **Next**.
-1. In the review page, scroll to the bottom and choose **Submit**.
-1. Refresh the page until you see the `CREATE_COMPLETE` status for your stack.
-::::
-:::::
-
- Now, let’s review the stack events and outputs. Your stack events should look similar to the image shown next:
-
-
-Looking at the stack events, you can see the bucket and the bucket policy are created successfully. Now, navigate to the **Resources** pane for your stack, note the Physical ID value for `S3Bucket`, and follow the link: this will bring you to the details page for your bucket in the [Amazon S3 Console](https://console.aws.amazon.com/s3/). Next, in the bucket view, choose **Permissions** and review the bucket policy in the **Bucket policy** section: see how the return values have been substituted in the `Resource` section of the bucket policy. Next, navigate to the **Outputs** pane of your stack in the AWS CloudFormation Console, and note the value of the IPv4 DNS name displayed for the Amazon S3 bucket you created in the stack.
-
-Congratulations! You have now learned how to find return values for a specified resource, and how to use them in your templates with other resources using `Ref`, `Fn::GetAtt` and `Fn::Sub` [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html).
-
-### Challenge
-In this section of the lab, you are tasked with updating an existing, example template that describes an Amazon EC2 [instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html) and a [security group](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html). You will need to reference the security group’s logical ID in the `SecurityGroups` property of the Amazon EC2 instance resource. Also, you need to update the `Outputs` section of the template to output the following values:
-
-* Instance ID of the Amazon EC2 instance created in the stack.
-* Public IP of the Amazon EC2 instance created.
-* ID of the security group created in the stack.
-
-To get started, open the `resource-return-values-challenge.yaml` template, that you can find in the `code/workspace/resource-return-values` directory, with your favorite code editor. Follow example requirements above, and update the template accordingly.
-
-When ready, create a new stack, called `resource-return-values-challenge`, with your updated `resource-return-values-challenge.yaml` template, and verify if the requirements are met.
-
-:::expand{header="Need a hint?"}
-* How can you [reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html) your security group in the `SecurityGroups` property of your Amazon EC2 instance?
-* When you reference your security group, also note that the `Type` of the `SecurityGroups` property value is a *List of String*. How do you represent this value in YAML format?
-* Review Amazon EC2 instance [return values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#aws-properties-ec2-instance-return-values) and security group [return values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html#aws-properties-ec2-security-group-return-values), and see what values are returned when you use `Ref` or `Fn::GetAtt` [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html).
-:::
-
-::::::expand{header="Want to see the solution?"}
-* Reference the Security Group’s logical ID as a list item under the `SecurityGroups` instance resource property, by using `Ref` intrinsic function.
-* Modify the Amazon EC2 instance resource definition as next:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Ec2Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- SecurityGroups:
- - !Ref InstanceSecurityGroup
- Tags:
- - Key: Name
- Value: Resource-return-values-workshop
-:::
-
-* Use `Ref` intrinsic function, and pass the logical ID of the Amazon EC2 instance resource to retrieve the instance ID; similarly, pass the logical ID of the Amazon EC2 instance resource, along with the `PublicIp` attribute to the `Fn::GetAtt` function, to retrieve the public IP of the instance.
-* Pass the logical ID of the security group resource, along with the `GroupId` attribute, to the `Fn::GetAtt` function to retrieve the ID of the security group.
-* Modify the `Outputs` section of the template as shown next:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Outputs:
- InstanceID:
- Description: The ID of the launched instance
- Value: !Ref Ec2Instance
-
- PublicIP:
- Description: Public IP of the launched instance
- Value: !GetAtt Ec2Instance.PublicIp
-
- SecurityGroupId:
- Description: ID of the security group created
- Value: !GetAtt InstanceSecurityGroup.GroupId
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/resource-return-values`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/resource-return-values
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-resource-return-values-challenge --template-body file://resource-return-values-challenge.yaml
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-return-values-challenge/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-1. View the output value on the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation), in the _Outputs_ tab.
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. In the CloudFormation console, select **Create stack With new resources (standard)**.
-1. In **Prepare template**, choose **Template is ready**.
-1. In **Template source**, select **Upload a template file**.
-1. Upload the `resource-return-values-challenge.yaml` template, and choose **Next**.
-1. Enter a stack name. For example, `cfn-workshop-resource-return-values-challenge`. When ready, choose **Next**.
-1. Choose to accept default values on the **Configure stack options** page; scroll to the bottom of the page, and choose **Next**.
-1. In the review page, scroll to the bottom and choose **Submit**.
-1. Refresh the page until you see the `CREATE_COMPLETE` status for your stack.
-1. View the output value on the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation), in the _Outputs_ tab.
-::::
-:::::
-::::::
-
-The full solution for this challenge is available in the `code/solutions/resource-return-values/resource-return-values-challenge.yaml` template.
-
-### Cleanup
-Follow the steps below to [delete the stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html) you created as a part of this lab:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-2. On the **Stacks** page in the CloudFormation console, select the `cfn-workshop-resource-return-values` stack.
-3. In the stack details pane, choose **Delete** to delete the stack, and then choose **Delete stack** to confirm.
-4. Repeat steps above to delete the `cfn-workshop-resource-return-values-challenge` stack you created.
-
----
-### Conclusion
-Great work! You have now learned how to find return values for a specified resource, and how to use them in your templates in other resources using `Ref`, `Fn::GetAtt`, and `Fn::Sub` [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html).
diff --git a/content/basics/templates/resources/index.ja.md b/content/basics/templates/resources/index.ja.md
deleted file mode 100644
index 524083396..000000000
--- a/content/basics/templates/resources/index.ja.md
+++ /dev/null
@@ -1,178 +0,0 @@
----
-title: "リソース"
-weight: 300
----
-
-_ラボ実施時間 : 10分程度_
-
----
-
-### 概要
-
-このラボでは、CloudFormation の最上位の要素 (形式バージョン、説明、メタデータ、パラメータ、リソース) について学んでいきます。
-
-### カバーされるトピック
-このラボを完了すると、以下のことができるようになります。
-
-+ CloudFormation テンプレートの構造といくつかのセクションについての理解。
-+ CloudFormation で EC2 インスタンスのデプロイ。
-+ SSM パラメータストアから最新の Linux AMI ID の取得。
-
-### ラボの開始
-
-::alert[各セクションに、サンプルコードが最後に記載されています。コードをご自身のテンプレートにコピーしてください。]{type="info"}
-
-1. `code/workspace/` ディレクトリへ移動します。
-1. `resources.yaml` ファイルを開きます。
-1. 以下のトピックを進みながら、コードをコピーしていきます。
-
-#### 形式バージョン
-_AWSTemplateFormatVersion_ セクションは、テンプレートの機能を識別します。最新のテンプレートの形式バージョンは _2010-09-09_ であり、現時点で唯一の有効な値です。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-AWSTemplateFormatVersion: "2010-09-09"
-:::
-
-#### 説明
-_Description_ セクションには、テンプレートに関するコメントを含めることができます。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Description: AWS CloudFormation workshop - Resources (uksb-1q9p31idr) (tag:resources).
-:::
-
-#### メタデータ
-[_Metadata_ セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html)を使用して、任意の JSON または YAML オブジェクトを含めることができます。このセクションは、CloudFormation テンプレートと相互作用する他のツールへ情報を提供するのに役立ちます。例えば、AWS コンソールから CloudFormation テンプレートをデプロイするときに、パラメータのソート順やラベル、グループ化の方法を指定することでデプロイするユーザのユーザエクスペリエンスを向上することができます。この場合は [_AWS::CloudFormation::Interface_](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-interface.html) キーで実現できます。
-
-```yaml
-Metadata:
- AWS::CloudFormation::Interface:
- ParameterGroups:
- - Label:
- default: 'Amazon EC2 Configuration'
- Parameters:
- - InstanceType
- ParameterLabels:
- InstanceType:
- default: 'Type of EC2 Instance'
-```
-
-#### パラメータ
-_Parameters_ セクションを使用すると、スタックを作成または更新する時にテンプレートにカスタム値を入力できます。
-
-AWS CloudFormation は次のパラメータタイプをサポートします。
-
-| Type | Description | Example |
-|---------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|-----------------------------------------------------|
-| _String_ | リテラル文字列 | "MyUserName" |
-| _Number_ | 整数または浮動小数点値 | "123" |
-| _List\_ | カンマ区切りの整数または浮動小数点値の配列 | "10,20,30" |
-| _CommaDelimitedList_ | カンマ区切りのリテラル文字列の配列 | "test,dev,prod" |
-| [AWS 固有のパラメータタイプ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-specific-parameter-types) | VPC の ID などの AWS の値です | _AWS::EC2::VPC::Id_ |
-| [SSM パラメータタイプ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-ssm-parameter-types) | Systems Manager パラメータストアに存在するパラメータを参照するパラメータ | _AWS::SSM::Parameter::Value\_ |
-
-```yaml
-Parameters:
- InstanceType:
- Type: String
- Default: t2.micro
- AllowedValues:
- - t2.micro
- - t2.small
- Description: 'Enter t2.micro or t2.small. Default is t2.micro.'
-```
-
-#### リソース
-必須である _Resources_ セクションでは、スタックに含める AWS リソースを宣言します。ここで EC2 リソースをスタックに追加してみましょう。
-
-```yaml
-Resources:
- WebServerInstance:
- Type: 'AWS::EC2::Instance'
- Properties:
- InstanceType: !Ref InstanceType
- ImageId:
-```
-
-EC2 リソースタイプの唯一の必須プロパティは _ImageId_ です。 AWS コンソールから AMI ID を見つけてみましょう。
-
- 1. **[AWS EC2 console](https://console.aws.amazon.com/ec2)** を開きます。
- 2. **インスタンス** -> **インスタンスを起動** をクリックします。
- 3. **Amazon Linux 2023 AMI** `ami-xxxxxxxxx` の ID をコピーします。
- ::alert[x86 と Arm アーキテクチャを選択できるリージョンの場合、必ず **64-bit (x86)** AMI ID を使うようにしてください。]{type="info"}
- 4. AMI ID が見つかったら、コピーして **ImageId** プロパティに貼り付けます。
-
-::alert[**米国東部 (バージニア北部) リージョン** の場合の解答を `code/solutions/resources.yaml` ファイルで見ることができます。]{type="info"}
-
-これで EC2 テンプレートをデプロイする準備が整いました。[テンプレートとスタック](../template-and-stack) で実施した時と同様の方法でデプロイを行います。
-
-:::alert{type="warning"}
-これ以降のラボを実施するためには、CloudFormation をデプロイするリージョンに **デフォルト VPC** が必要です。もしデフォルト VPC を削除していた場合、**[デフォルトの VPC を作成する](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/default-vpc.html#create-default-vpc)** の AWS ドキュメントに沿って新しいデフォルト VPC を作成できます。
-:::
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** で `code/workspace` に移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace
-:::
-1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-resources --template-body file://resources.yaml
-:::
-1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resources/62df5090-e747-11ed-a22a-0e39ed6c0e49"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-
-::::tab{id="local" label="ローカル開発"}
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
-1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
-1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
-1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
-1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
-1. `resources.yaml` ファイルを指定し、**次へ** をクリックします。
-1. **スタックの名前** (例: `cfn-workshop-resources`) を入力します。
- + _スタックの名前_ はスタックを識別します。スタックの目的がわかるような名前を使ってください。
-1. **Type of EC2 Instance** には、お好みのインスタンスサイズ (例: **t2.micro**) を選択し、**次へ** をクリックします。
-1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
-1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**送信** をクリックします。
- ::alert[これによりお使いのアカウントに EC2 インスタンスが作成されます。デプロイされたスタックのコストを確認するためには、レビューページの **予想コスト** をクリックして、ご確認ください。]{type="info"}
-1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-::::
-:::::
-
-### チャレンジ
-
-この練習問題では、AWS CLI を使って、AWS Systems Manager パラメータストアから最新の Amazon Linux AMI ID を取得します。
-
-::alert[このチャレンジを完了するには、[AWS CLI](../../../prerequisites/local-development) が完了していることをご確認ください。Code Editor 環境には最初からインストールされています。]{type="info"}
-
-::expand[[Amazon Web Services ブログ](https://aws.amazon.com/jp/blogs/news/query-for-the-latest-amazon-linux-ami-ids-using-aws-systems-manager-parameter-store/) を確認してみてください。]{header="ヒントが必要ですか?"}
-
-::::expand{header="解決策を確認しますか?"}
-ターミナルに以下のコードをコピーします。CloudFormation をデプロイするリージョンにあわせて `--region` フラグを変更するようにしてください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ssm get-parameters \
- --names /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \
- --query "Parameters[].Value" \
- --region us-east-1 \
- --output text
-:::
-::::
-
-### クリーンアップ
-
-以下の手順で作成したリソースの削除を行います。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** に移動します。
-1. CloudFormation の **スタック** ページで `cfn-workshop-resources` を選択します。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-1. スタックが **DELETE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-
----
-
-### まとめ
-おめでとうございます!これで無事に CloudFormation を使って EC2 インスタンスをデプロイする方法について学習できました。
diff --git a/content/basics/templates/resources/index.md b/content/basics/templates/resources/index.md
deleted file mode 100644
index c5bc2b5b0..000000000
--- a/content/basics/templates/resources/index.md
+++ /dev/null
@@ -1,191 +0,0 @@
----
-title: "Resources"
-weight: 300
----
-
-_Lab Duration: ~10 minutes_
-
----
-
-### Overview
-
-In this Lab, you will learn a little more about CloudFormation top-level sections, including Format Version, Description, Metadata, Parameters and Resources.
-
-### Topics Covered
-By the end of this lab, you will be able to:
-
-+ Understand CloudFormation template structure and some of its sections.
-+ Deploy an EC2 instance via CloudFormation.
-+ Query SSM parameter store to get the latest Amazon Linux AMI ID.
-
-### Start Lab
-
-::alert[As you read through each section, there are code samples at the end. Copy these into your own template file.]{type="info"}
-
-1. Go to `code/workspace/` directory.
-1. Open the `resources.yaml` file.
-1. Copy the code as you go through the topics below.
-
-#### Format Version
-The _AWSTemplateFormatVersion_ section identifies the capabilities of the template. The latest template format version
-is _2010-09-09_ and is currently the only valid value.
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-AWSTemplateFormatVersion: "2010-09-09"
-:::
-
-#### Description
-The _Description_ section enables you to include comments about your template.
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-Description: AWS CloudFormation workshop - Resources (uksb-1q9p31idr) (tag:resources).
-:::
-
-#### Metadata
-You can use the [_Metadata_ section](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html)
-to include arbitrary JSON or YAML objects. This section is useful for providing information to other tools that interact
-with your CloudFormation template. For example, when deploying CloudFormation templates via the AWS console, you can
-improve the experience of users deploying your templates by specify how to order, label and group parameters.
-This can be done with the [_AWS::CloudFormation::Interface_](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-interface.html) key.
-
-```yaml
-Metadata:
- AWS::CloudFormation::Interface:
- ParameterGroups:
- - Label:
- default: 'Amazon EC2 Configuration'
- Parameters:
- - InstanceType
- ParameterLabels:
- InstanceType:
- default: 'Type of EC2 Instance'
-```
-
-#### Parameters
-_Parameters_ enable you to input custom values to your template each time you create or update a stack.
-
-AWS CloudFormation supports the following parameter types:
-
-| Type | Description | Example |
-|---------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|-----------------------------------------------------|
-| _String_ | A literal string. | "MyUserName" |
-| _Number_ | An integer or float. | "123" |
-| _List\_ | An array of integers or floats. | "10,20,30" |
-| _CommaDelimitedList_ | An array of literal strings. | "test,dev,prod" |
-| [AWS-Specific Parameter Types](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-specific-parameter-types) | AWS values such as Amazon VPC IDs. | _AWS::EC2::VPC::Id_ |
-| [SSM Parameter Types](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-ssm-parameter-types) | Parameters that correspond to existing parameters in Systems Manager Parameter Store. | _AWS::SSM::Parameter::Value\_ |
-
-```yaml
-Parameters:
- InstanceType:
- Type: String
- Default: t2.micro
- AllowedValues:
- - t2.micro
- - t2.small
- Description: 'Enter t2.micro or t2.small. Default is t2.micro.'
-```
-
-#### Resources
-
-The required _Resources_ section declares the AWS resources that you want to include in the stack. Let's add the EC2 resource to your stack.
-
-```yaml
-Resources:
- WebServerInstance:
- Type: 'AWS::EC2::Instance'
- Properties:
- InstanceType: !Ref InstanceType
- ImageId:
-```
-
-The only required property of the EC2 resource type is _ImageId_. Let's find the AMI ID via AWS console:
-
- 1. Open **[AWS EC2 console](https://console.aws.amazon.com/ec2)**
- 1. Click **Instances** -> **Launch Instance**.
- 1. Copy the **Amazon Linux 2023 AMI** `ami-xxxxxxxxx` ID.
- ::alert[Make sure to use **64-bit (x86)** AMI ID, if the region supports both x86 and ARM architectures.]{type="info"}
- 1. Once you have your AMI ID, copy and paste it to **ImageId** property.
-
-::alert[You can find a working solution for the **US East (N.Virginia) Region** in `code/solutions/resources.yaml` file.]{type="info"}
-
-Now your EC2 template is ready to be deployed. Deploy the stack same way as you did in [Template and Stack](../template-and-stack).
-
-:::alert{type="warning"}
-To complete this and future labs you will need **Default VPC** in the region you will be deploying CloudFormation templates to. \
-If you have deleted your default VPC, you can create a new one by following the AWS documentation for **[Creating a Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html#create-default-vpc)**.
-:::
-
-:::::tabs{variant="container"}
-
- ::::tab{id="code-editor" label="Code Editor"}
- 1. In the **Code Editor terminal** navigate to `code/workspace`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace
- :::
- 1. Use the AWS CLI to create the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack --stack-name cfn-workshop-resources --template-body file://resources.yaml
- :::
- 1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resources/62df5090-e747-11ed-a22a-0e39ed6c0e49"
- :::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and wait for stack status to reach the **CREATE_COMPLETE** status. You need to periodically select Refresh to see the latest stack status.
- ::::
-
-::::tab{id="local" label="Local development"}
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
-1. Click on **Create stack** (_With new resources (Standard)_ if you have clicked in the top right corner).
-1. In **Prepare template**, choose **Template is ready**.
-1. In **Specify template**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the file `resources.yaml`.
-1. Click **Next**.
-1. Provide a **Stack name**. For example `cfn-workshop-resources`.
- + The _Stack name_ identifies the stack. Use a name to help you distinguish the purpose of this stack.
- + For **Type of EC2 Instance** select your preferred instance size, for example **t2.micro**.
- + Click **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and click on **Submit**.
- ::alert[This will create EC2 instance in your account. To check the cost of the deployed stack, click on **Estimate cost** on the review page.]{type="info"}
-1. You can click the **refresh** button a few times until you see in the status **CREATE_COMPLETE**.
-::::
-
-:::::
-
-### Challenge
-
-In this exercise, use the AWS CLI to query the AWS Systems Manager Parameter Store to get the latest Amazon Linux AMI ID.
-
-::alert[To complete this challenge, make sure you have the [AWS CLI](../../../prerequisites/local-development) configured. Your Code Editor environment comes with this pre-configured.]{type="info"}
-
-::expand[Check out the [AWS Compute Blog](https://aws.amazon.com/blogs/compute/query-for-the-latest-amazon-linux-ami-ids-using-aws-systems-manager-parameter-store/) to find out.]{header="Need a hint?"}
-
-::::expand{header="Want to see the solution?"}
-Copy the code below to your terminal. Make sure to change the `--region` flag to use a region that you are deploying your CloudFormation to.
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ssm get-parameters \
- --names /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \
- --query "Parameters[].Value" \
- --region us-east-1 \
- --output text
-:::
-
-
-::::
-
-### Clean up
-
-Follow these steps to clean up created resources:
-
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the stack you have created in this lab. For example `cfn-workshop-resources`.
-1. In the top right corner, select **Delete**.
-1. In the pop-up window, select **Delete**.
-1. Wait for the stack to reach the **DELETE_COMPLETE** status. You need to periodically select **Refresh** to see the latest stack status.
-
----
-
-### Conclusion
-Congratulations! You have successfully learned how to deploy an EC2 instance via CloudFormation.
diff --git a/content/basics/templates/template-anatomy/index.ja.md b/content/basics/templates/template-anatomy/index.ja.md
deleted file mode 100644
index ede2fbfc4..000000000
--- a/content/basics/templates/template-anatomy/index.ja.md
+++ /dev/null
@@ -1,54 +0,0 @@
----
-title: "テンプレートの構造"
-weight: 100
----
-
-_ラボ実施時間 : 10分程度_
-
----
-
-### テンプレート
-
-**AWS CloudFormation テンプレート** は **スタック** を構成する AWS リソースの宣言です。テンプレートは JavaScript Object Notation (JSON) または YAML 形式のテキストファイルとして保存します。一般的なテキストファイルであるため、任意のテキストエディタでの作成や編集、他のソースコードと一緒にバージョン管理システムでの管理などが可能です。
-
-:::alert{type="info"}
-このワークショップでは、サンプルコードとして YAML 形式を使用します。JSON を使う場合には、[形式による差異](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-formats.html) があることにご注意ください。
-:::
-
-次の例では、AWS CloudFormation の YAML のテンプレートの構造と最上位のセクションを紹介します。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-AWSTemplateFormatVersion: 'バージョン日付' (任意) # CloudFormation テンプレート形式のバージョン。 '2010-09-09' のみ指定可能
-
-Description: '文字列' (任意) # Cloudformation テンプレートを説明するテキスト
-
-Metadata: 'テンプレートメタデータ' (任意) # テンプレートに関する追加情報を提供するオブジェクト
-
-Parameters: 'パラメータのセット' (任意) # テンプレートをカスタマイズするための入力値
-
-Rules: 'ルールのセット' (任意) # デプロイ・更新時にパラメータまたはパラメータの組み合わせの検証ルール
-
-Mappings: 'マッピングのセット' (任意) # キーとバリューのマッピング
-
-Conditions: '条件のセット' (任意) # 特定のリソースの作成の有無を制御する条件
-
-Transform: 'トランスフォームのセット' (任意) # サーバレスアプリケーション向けの宣言
-
-Resources: 'リソースのセット' (必須) # インフラストラクチャのコンポーネント
-
-Hooks: 'フックのセット' (任意) # ECS の Blue/Green デプロイに利用
-
-Outputs: '出力のセット' (任意) # スタックのプロパティで確認できる出力値
-:::
-
-最上位のセクションで唯一必要なのは **Resources** セクションだけで、少なくとも 1 つのリソースの宣言が必要です。これらのセクションの定義については、[テンプレートの分析](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-anatomy.html) のガイドで確認することができます。
-
-### スタック
-
-スタックは CloudFormation テンプレートをデプロイしたものになります。1 つの CloudFormation テンプレートから複数のスタックを作成できます。スタックは一連の AWS リソースの集合を含み、単一のユニットとして管理できます。スタック内のすべてのリソースは、スタックの AWS CloudFormation テンプレートで定義されています。
-
-AWS CloudFormation は全体としてスタックの作成、更新、削除を行います。
- * 全体としてスタックが作成、または更新できない場合、AWS CloudFormation はロールバックを行い、その操作で作成されたリソースをすべて自動的に削除します。
- * リソースを削除できなかった場合、スタックの削除に成功するまでに、それらのリソースを保持します。
-
-
diff --git a/content/basics/templates/template-anatomy/index.md b/content/basics/templates/template-anatomy/index.md
deleted file mode 100644
index a8a1f1809..000000000
--- a/content/basics/templates/template-anatomy/index.md
+++ /dev/null
@@ -1,62 +0,0 @@
----
-title: "Template anatomy"
-weight: 100
----
-
-_Lab Duration: ~10 minutes_
-
----
-
-### Template
-
-**An AWS CloudFormation template** is a declaration of the AWS resources that make up a **stack**.
-The template is stored as a text file in either JavaScript Object Notation (JSON) or YAML format.
-Because they are just text files, you can create and edit them in any text editor and manage them in your source control
-system with the rest of your source code.
-
-:::alert{type="info"}
-Throughout this workshop, code samples will use the YAML format. If you prefer to use JSON, please be aware
-of [the differences](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-formats.html).
-:::
-
-The following example shows an AWS CloudFormation YAML template structure and its top-level objects:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-AWSTemplateFormatVersion: 'version date' (optional) # version of the CloudFormation template. Only accepted value is '2010-09-09'
-
-Description: 'String' (optional) # a text description of the Cloudformation template
-
-Metadata: 'template metadata' (optional) # objects that provide additional information about the template
-
-Parameters: 'set of parameters' (optional) # a set of inputs used to customize the template
-
-Rules: 'set of rules' (optional) # a set of rules to validate the parameters provided at deployment/update
-
-Mappings: 'set of mappings' (optional) # a mapping of keys and associated values
-
-Conditions: 'set of conditions' (optional) # conditions that control whether certain resources are created
-
-Transform: 'set of transforms' (optional) # for serverless applications
-
-Resources: 'set of resources' (required) # a components of your infrastructure
-
-Hooks: 'set of hooks' (optional) # Used for ECS Blue/Green Deployments
-
-Outputs: 'set of outputs' (optional) # values that are returned whenever you view your stack's properties
-:::
-
-The only required top-level object is the **Resources** object, which must declare at least one resource.
-The definition of each of these objects can be found in the online [Template Anatomy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html) documentation.
-
-### Stack
-
-A stack is a deployment of a CloudFormation template. You can create multiple stacks from a single CloudFormation
-template. A stack contains a collection of AWS resources that you can manage as a single unit. All the resources in
-a stack are defined by the stack's AWS CloudFormation template.
-
-AWS CloudFormation will create, update or delete a stack in its entirety:
-
- * If a stack cannot be created or updated in its entirety, AWS CloudFormation will roll it back, and automatically delete any resources that were created.
- * If a resource cannot be deleted, any remaining resources are retained until the stack can be successfully deleted.
-
-
diff --git a/content/basics/templates/template-and-stack/index.ja.md b/content/basics/templates/template-and-stack/index.ja.md
deleted file mode 100644
index 318888762..000000000
--- a/content/basics/templates/template-and-stack/index.ja.md
+++ /dev/null
@@ -1,137 +0,0 @@
----
-title: "テンプレートとスタック"
-weight: 200
----
-
-_ラボ実施時間 : 10分程度_
-
----
-
-### 概要
-このラボでは、1 つの S3 バケットの宣言を含む、`Resources` セクションだけで構成された最も基礎的なテンプレートから始めます。
-
-### カバーするトピック
-このラボを完了すると、以下のことができるようになります。
-+ [S3](https://aws.amazon.com/jp/s3/) バケットを記述した簡単な CloudFormation テンプレートの作成
-+ テンプレートのデプロイと CloudFormation スタックの作成
-
-### ラボの開始
-
-1. `code/workspace/` ディレクトリを開きます。
-2. `template-and-stack.yaml` ファイルをコードエディタで開きます。
-3. 以下は S3 バケットを定義する CloudFormation テンプレートのサンプルです。S3 バケットを含む単一のリソースを持っています。以下のコードをコピーし、`template-and-stack.yaml` ファイルに追加してください。
- ```yaml
- Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
- ```
-4. 以下の手順の通りにスタックを作成します。
-
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **Code Editor のターミナル** で `code/workspace` に移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace
- :::
- 1. AWS CLI でスタックを作成します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack --stack-name cfn-workshop-template-and-stack --template-body file://template-and-stack.yaml
- :::
- 1. `create-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-template-and-stack/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
- 1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のリンクを新しいタブで開き、必要に応じて AWS アカウントにログインします。
- 1. 画面右上の **スタックの作成** をクリックし、**新しいリソースを使用 (標準)** をクリックしてください。
- 1. **テンプレートの準備** では、**テンプレートの準備完了** を選びます。
- 1. **テンプレートの指定** では、**テンプレートファイルのアップロード** を選びます。
- 1. **ファイルの選択** をクリックして、作業ディレクトリに移動します。
- 1. `template-and-stack.yaml` ファイルを指定し、**次へ** をクリックします。
- 1. **スタックの名前** (例: `cfn-workshop-template-and-stack`) を入力します。
- + _スタック名_ はスタックを識別します。スタックの目的がわかるような名前を使ってください。
- + **次へ** をクリックします。
- 1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
- 1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**送信** をクリックします。
- 1. スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
- ::::
- ::::::
-
-### チャレンジ
-この練習問題では、S3 バケットのオブジェクトの誤った削除や上書きを防止したり、バージョニングを有効にします。アーカイブすることで以前のバージョンのオブジェクトを取得できるようになります。
-
-1. S3 リソースの `Properties` セクションに、`VersioningConfiguration` プロパティを追加します。
-2. `Status` を `Enabled` に設定します。
-3. テンプレートの変更を反映するために、スタックを更新します。
-
-::expand[ [AWS::S3::Bucket](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html) リソースの AWS ドキュメントをご確認ください。]{header="ヒントが必要ですか?"}
-
-::::::expand{header="解決策を確認しますか?"}
-1. 次のコードで、テンプレートのコードを置き換えてください。
- ```yaml
- Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- VersioningConfiguration:
- Status: Enabled
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
- ```
-1. 次は、以下の手順の通りにスタックを更新します。
-
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **Code Editor のターミナル** で `code/workspace` に移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace
- :::
- 1. AWS CLI でスタックを更新します。必要な `--stack-name`、`--template-body` パラメータがあらかじめ設定されています。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-template-and-stack --template-body file://template-and-stack.yaml
- :::
- 1. `update-stack` コマンドが正常に送信されたら、CloudFormation が `StackId` を返します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-template-and-stack/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
- 1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** のコンソールを新しいタブで開き、スタックが **CREATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. **[AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** を新しいタブで開き、必要に応じて AWS アカウントにログインします。
- 1. スタック名 (例: `cfn-workshop-template-and-stack`) を選択します。
- 1. 画面右上の **更新** ボタンをクリックします。
- 1. **テンプレートの準備** で、**既存テンプレートを置き換える** を選択します。
- 1. **テンプレートの指定** で、 **テンプレートファイルのアップロード** を選びます。
- 1. **ファイルの選択** ボタンをクリックし、ワークショップのディレクトリに移動します。
- 1. `code/workspace/template-and-stack.yaml` ファイルを指定し、**次へ** をクリックします。
- 1. **スタックの詳細を指定** では **次へ** をクリックします。
- 1. **スタックオプションの設定** はデフォルトの設定のままとし、**次へ** をクリックします。
- 1. **レビュー <スタック名>** のページで、ページの下部までスクロールし、**変更セットのプレビュー** の内容が表示されることをしばらく待ち、**送信** をクリックします。
- 1. スタックが **UPDATE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
- ::::
- :::::
-::::::
-
-### クリーンアップ
-
-次のステップに従って、作成したリソースを削除してください。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** に移動します。
-1. CloudFormation の **スタック** ページで `cfn-workshop-template-and-stack` を選択します。
-1. スタックの詳細で **削除** を選択し、ポップアップ上で **削除** で確定します。
-1. スタックが **DELETE_COMPLETE** ステータスになるまで待ちます。必要に応じて、リフレッシュボタンをクリックします。
-
----
-
-### まとめ
-
-おめでとうございます! これで最初の CloudFormation テンプレートと最初のスタックの作成ができました。
diff --git a/content/basics/templates/template-and-stack/index.md b/content/basics/templates/template-and-stack/index.md
deleted file mode 100644
index 08e40c8f1..000000000
--- a/content/basics/templates/template-and-stack/index.md
+++ /dev/null
@@ -1,142 +0,0 @@
----
-title: "Template and stack"
-weight: 200
----
-
-_Lab Duration: ~10 minutes_
-
----
-
-### Overview
-This lab will start with the most basic template containing only the `Resources` section, which contains a single resource declaration of the S3 bucket.
-
-### Topics Covered
-By the end of this lab, you will be able to:
-
-+ Write a simple CloudFormation template that describes an [S3](https://aws.amazon.com/s3/) bucket.
-+ Deploy the template and create a CloudFormation stack.
-
-### Start Lab
-
-1. Go to the `code/workspace/` directory.
-2. Open the `template-and-stack.yaml` file in your code editor.
-3. Here is a sample CloudFormation template that defines an S3 Bucket. It has a single resource that contains the S3 bucket.
- Copy the code below and save to the `template-and-stack.yaml` file.
- ```yaml
- Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
- ```
-4. It’s now time to create your stack! Follow steps below:
-
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. In the **Code Editor terminal** navigate to `code/workspace`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace
- :::
- 1. Use the AWS CLI to create the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack --stack-name cfn-workshop-template-and-stack --template-body file://template-and-stack.yaml
- :::
- 1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-template-and-stack/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
- ::::
- ::::tab{id="local" label="Local development"}
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** link in a new tab and log in to your AWS account.
- 1. Choose **Create stack** (_With new resources (Standard)_) from the top-right side of the page.
- 1. In **Prepare template**, choose **Template is ready**.
- 1. In **Template source**, choose **Upload a template file**.
- 1. Choose the **Choose file** button and navigate to your workshop directory.
- 1. Select the file `template-and-stack.yaml` referenced in step 1.
- 1. Choose **Next**.
- 1. Provide a **Stack name**. For example `cfn-workshop-template-and-stack`.
- + The _Stack name_ identifies the stack. Use a name to help you distinguish the purpose of this stack.
- + Choose **Next**.
- 1. Choose to accept default values for **Configure stack options**; choose **Next**.
- 1. On the **Review ** page, scroll to the bottom and choose **Submit**.
- 1. Use the **refresh** button to update the page as needed, until you see the stack has the **CREATE_COMPLETE** status.
- ::::
- :::::
-
-### Challenge
-In this exercise, you'll enable versioning on the S3 bucket to prevent objects from being deleted or
-overwritten by mistake or to archive objects so that you can retrieve previous versions of them.
-
-1. Create a `VersioningConfiguration` property in the `Properties` section of the S3 resource.
-2. Set the `Status` to `Enabled`.
-3. Update the stack to reflect the changes made in the template.
-
-::expand[Check out the AWS Documentation for [AWS::S3::Bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html) resource.]{header="Need a hint?"}
-
-::::::expand{header="Want to see the solution?"}
-1. Replace the code in your template with the code below:
- ```yaml
- Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- VersioningConfiguration:
- Status: Enabled
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
- ```
-1. It’s now time to update your stack! Follow steps below:
-
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. In the **Code Editor terminal** navigate to `code/workspace`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace
- :::
- 1. Use the AWS CLI to create the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-template-and-stack --template-body file://template-and-stack.yaml
- :::
- 1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-template-and-stack/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
- ::::
- ::::tab{id="local" label="Local Development"}
- 1. Log in to the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new browser tab.
- 1. Select the stack name, for example `cfn-workshop-template-and-stack`.
- 1. In the top right corner select **Update**.
- 1. In **Prepare template**, choose **Replace current template**.
- 1. In **Template source**, choose **Upload a template file**.
- 1. Select **Choose file** button and navigate to your workshop directory.
- 1. Choose the file `code/workspace/template-and-stack.yaml` and select **Next**.
- 1. On **Specify stack details** page, select **Next**.
- 1. On the **Configure stack options** page, select **Next**.
- 1. On the **Review ** page, scroll down and wait for the **Change set** section to complete. Then select **Submit**.
- 1. Wait for the stack status to reach **UPDATE_COMPLETE**. You need to periodically select **Refresh** to see the latest stack status.
- ::::
- :::::
-
-::::::
-
-### Clean up
-
-Follow these steps to clean up created resources:
-
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the stack you have created in this lab. For example `cfn-workshop-template-and-stack`.
-1. In the top right corner, select **Delete**.
-1. In the pop-up window, select **Delete**.
-1. Wait for the stack to reach the **DELETE_COMPLETE** status. You need to periodically select **Refresh** to see the latest stack status.
-
----
-
-### Conclusion
-
-Great work! You have written your first CloudFormation template and created your first stack.
diff --git a/content/index.ja.md b/content/index.ja.md
deleted file mode 100644
index ac03bec7b..000000000
--- a/content/index.ja.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "AWS CloudFormation ワークショップ"
-weight: 1
----
-
-
-
-#### AWS CloudFormation ワークショップへようこそ !
-
-このワークショップは、ビルダーの方が [AWS CloudFormation](https://aws.amazon.com/cloudformation/) の特徴を学び、素早く構築を開始することを目的としています。
-
-CloudFormation、コマンドライン、Git、開発ワークフローに関する経験は不要です。
diff --git a/content/index.md b/content/index.md
deleted file mode 100644
index a7f72b91b..000000000
--- a/content/index.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "AWS CloudFormation Workshop"
-weight: 1
----
-
-
-
-#### Welcome to the AWS CloudFormation Workshop!
-
-The intent of this workshop is to educate builders about the features of [AWS
-CloudFormation](https://aws.amazon.com/cloudformation/) and how to get started building quickly.
-
-A background in CloudFormation, command line, git, and development workflows is not required.
diff --git a/content/intermediate/index.ja.md b/content/intermediate/index.ja.md
deleted file mode 100644
index 47483bcb2..000000000
--- a/content/intermediate/index.ja.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "中級編"
-weight: 40
----
-
-ワークショップの**中級編**へようこそ。このパートでは、より高度な CloudFormation の概念を紹介します。
-
-**ネストされたスタックや階層化されたスタック**を作成する方法、Lambda 関数を**パッケージ化してデプロイ**する方法等を学びます。
-
-**中級編ワークショップ**の各セクションでは、独自で書いたルールに従い、JSON や YAML 形式の Policy as Code 検証を行う [AWS CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) 等のトピックについて学びます。
diff --git a/content/intermediate/index.md b/content/intermediate/index.md
deleted file mode 100644
index f0e441d58..000000000
--- a/content/intermediate/index.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-title: "Intermediate"
-weight: 40
----
-
-Welcome to the **Intermediate** part of the workshop. This part introduces more advanced CloudFormation concepts. You will
-learn how to create **nested and layered stacks** and how to **package and deploy** Lambda functions.
-
-In other sections of the **Intermediate** part of the workshop, you will learn about topics that include using [AWS CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) for policy-as-code validation of any JSON- or YAML-formatted data, including CloudFormation templates, against rules you write.
diff --git a/content/intermediate/operations/drift-detection/index.ja.md b/content/intermediate/operations/drift-detection/index.ja.md
deleted file mode 100644
index b39c3254c..000000000
--- a/content/intermediate/operations/drift-detection/index.ja.md
+++ /dev/null
@@ -1,765 +0,0 @@
----
-title: "ドリフト検出"
-weight: 500
----
-
-### 概要
-
-[AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/) を使用してリソースをプロビジョニングすることを選択した場合、必要に応じて CloudFormation を使用してリソースの設定を長期にわたって維持することになります。その後、そのようなリソースを CloudFormation の範囲外で変更した場合 (例えば、[AWS マネジメントコンソール](https://aws.amazon.com/jp/console/)、[AWS Command Line Interface](https://aws.amazon.com/jp/cli/) (AWS CLI)、[AWS SDK](https://aws.amazon.com/jp/developer/tools/)、[AWS API](https://docs.aws.amazon.com/general/latest/gr/aws-apis.html))、リソースの設定と CloudFormation の設定と差分ができてしまいます。
-
-CloudFormation は[ドリフト検出](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-drift.html) を提供しています。これは、リソースの現在の構成と、リソースの作成または更新に使用したテンプレートで宣言した構成との違いに関する情報を提供します。ドリフト検出の結果には、対象リソースに対して、現在の状態とテンプレートの違いが表示されます。その後、リソースを元の設定に戻すか、テンプレートと CloudFormation スタックを更新して望ましい状態を反映させることができます。
-
-### 取り上げるトピック
-
-このラボを修了すると、次のことができるようになります。
-
-* CloudFormation ドリフト検出を使用して、スタックリソースのドリフトを検出します。
-* ドリフト検出の結果を解釈して、どのリソースプロパティが変更されたかを特定する方法を理解します。
-* リソースを変更して元の構成に戻します。
-* リソースの新しい構成に合わせてテンプレートを更新します。
-* リソースインポートを使用して、リソースの新しい構成と一致するようにスタックとテンプレートを更新します。
-
-### ラボを開始
-
-[Amazon DynamoDB](https://aws.amazon.com/jp/dynamodb/) テーブルと [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/jp/sqs/) キューを新しいスタックとして含む AWS CloudFormation テンプレートの例をデプロイします。次に、プロビジョニングされたリソースにいくつかの設定変更を行い、ドリフト検出を使用して変更を特定します。次に、リソース構成を修正するか、新しい構成を反映するようにテンプレートを更新することで、ドリフトを解決します。
-
-開始するには、次の手順に従います。
-
-1. `code/workspace/drift-detection` ディレクトリに移動します。
-1. 以下のコードをコピーして `drift-detection-workshop.yaml` ファイルに追加し、ファイルを保存します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=5}
-Resources:
- Table1:
- Type: AWS::DynamoDB::Table
- Properties:
- AttributeDefinitions:
- - AttributeName: Album
- AttributeType: S
- - AttributeName: Artist
- AttributeType: S
- BillingMode: PROVISIONED
- KeySchema:
- - AttributeName: Album
- KeyType: HASH
- - AttributeName: Artist
- KeyType: RANGE
- ProvisionedThroughput:
- ReadCapacityUnits: 1
- WriteCapacityUnits: 1
-
- Queue1:
- Type: AWS::SQS::Queue
- Properties:
- MessageRetentionPeriod: 345600
-:::
-
-1. テンプレート内のリソース例をよく確認した上で、実施してください。
- 1. DynamoDB [テーブル](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html) には、正常に作成するための `KeySchema` と `AttributeDefinitions` プロパティの最小限の定義があります。ワークショップ中は、テーブルにデータを保存したり、テーブルからデータを取得したりすることはありません。
- 1. SQS [キュー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html) の `MessageRetentionPeriod` は 4 日間 (秒単位で表現) です。この値は [デフォルト](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#cfn-sqs-queue-messageretentionperiod) ですが、CloudFormation はテンプレートで明示的に宣言したプロパティに対してのみドリフトを評価することに注意してください。このプロパティを含めない場合、CloudFormation は後でリソースの変更を報告しません。
-1. 次のステップでは、このテンプレートを使用して新しいスタックを作成します。
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **Code Editor のターミナル** 上で `cfn101-workshop/code/workspace/drift-detection` ディレクトリに移動します:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/drift-detection
- :::
- 1. AWS CLI コマンドを使ってスタックを作成します。例えばスタック名を `cfn-workshop-drift-detection` と入力します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
---stack-name cfn-workshop-drift-detection \
---template-body file://drift-detection-workshop.yaml
- :::
- 1. `create-stack` コマンドが成功すると CloudFormation は `StackId` を返却します。
- :::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
- 1. 新しいタブで **[AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** を開いてスタックが **CREATE_COMPLETE** 状態であることを確認します。
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
- 1. **スタックの作成** から、 **新しいリソースを使用 (標準)** を選択します。
- 1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。前述の `drift-detection-workshop.yaml` テンプレートを選択し、 **次へ** をクリックします。
- 1. スタック名を入力します。例えば、`cfn-workshop-drift-detection-workshop` と入力します。 **次へ** をクリックします。
- 1. **スタックオプションの設定** ページはデフォルト値のまま、 **次へ** をクリックします。
- 1. **送信** をクリックします。
- 1. スタックが `CREATE_COMPLETE` 状態になるまで、スタック作成ページを更新します。
- ::::
- :::::
-
-### リソースの変更によるドリフトの検出と修復
-
-次に、CloudFormation の外で DynamoDB テーブルを直接変更します。
-
-1. [Amazon DynamoDB コンソール](https://console.aws.amazon.com/dynamodb/) に移動します。
-1. メニューの **テーブル** 見出しの下で、 **アクション** 、 **設定の更新** を選択します。
-1. **Table1** エントリを選択します (テーブル名の先頭にはスタックの名前が付きます)。
-1. **追加の設定** タブを選択します。
-1. **読み取り/書き込みキャパシティー** セクションで、 **編集** を選択します。
-1. **オンデマンド** キャパシティモードを選択し、 **変更を保存** を選択します。
-
-このステップでは、CloudFormation ドリフト検出を使用して、元のテンプレートと比較して `Table1` リソースに加えられた変更を特定します。
-
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **ドリフト検出** を行うために `cfn-workshop-drift-detection` スタックに対して次のコマンドを実行します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection
- :::
- 1. CloudFormation は次の結果を返却します。
- :::code{language=json showLineNumbers=false showCopyAction=true}
- "StackDriftDetectionId": "35768f30-f947-11ed-9dc9-0eb469d3b073"
- :::
- 1. ドリフト検出操作の実行結果をステップ 2 で得られた `stack-drift-detection-id` を使って確認します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-drift-detection-status \
---stack-drift-detection-id stack-drift-detection-id
- :::
- 1. `describe-stack-drift-detect-status` コマンドが成功すると、CloudFormation は`"DetectionStatus":"DETECTION_COMPLETE"` と `"StackDriftStatus":"DRIFTED"` の情報を返却します。
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=4-5}
-{
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/83fd7940-f945-11ed-ab77-12daf0c351ad",
- "StackDriftDetectionId": "35768f30-f947-11ed-9dc9-0eb469d3b073",
- "StackDriftStatus": "DRIFTED",
- "DetectionStatus": "DETECTION_COMPLETE",
- "DriftedStackResourceCount": 1,
- "Timestamp": "2023-05-23T08:52:55.332000+00:00"
-}
- :::
- 1. ドリフトしたリソースの詳細を確認するため次のコマンドを実行します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-resource-drifts \
---stack-name cfn-workshop-drift-detection
- :::
- 1. `descibe-stack-resource-drifts` コマンドの出力結果に `Table1` リソースのドリフトした内容が `Property Differences` の中で示されています。
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=21-34}
-{
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/83fd7940-f945-11ed-ab77-12daf0c351ad",
- "LogicalResourceId": "Queue1",
- "PhysicalResourceId": "https://sqs.us-east-1.amazonaws.com/123456789012/cfn-workshop-drift-detection-Queue1-LhZ9kuNmNV62",
- "ResourceType": "AWS::SQS::Queue",
- "ExpectedProperties": "{\"MessageRetentionPeriod\":345600}",
- "ActualProperties": "{\"MessageRetentionPeriod\":345600}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T08:42:44.951000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/83fd7940-f945-11ed-ab77-12daf0c351ad",
- "LogicalResourceId": "Table1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-Table1-173M9QVM1EZKE",
- "ResourceType": "AWS::DynamoDB::Table",
- "ExpectedProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"WriteCapacityUnits\":1,\"ReadCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeType\":\"S\",\"AttributeName\":\"Album\"},{\"AttributeType\":\"S\",\"AttributeName\":\"Artist\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "ActualProperties": "{\"BillingMode\":\"PAY_PER_REQUEST\",\"AttributeDefinitions\":[{\"AttributeName\":\"Album\",\"AttributeType\":\"S\"},{\"AttributeName\":\"Artist\",\"AttributeType\":\"S\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "PropertyDifferences": [
- {
- "PropertyPath": "/ProvisionedThroughput",
- "ExpectedValue": "{\"ReadCapacityUnits\":1,\"WriteCapacityUnits\":1}",
- "ActualValue": "null",
- "DifferenceType": "REMOVE"
- },
- {
- "PropertyPath": "/BillingMode",
- "ExpectedValue": "PROVISIONED",
- "ActualValue": "PAY_PER_REQUEST",
- "DifferenceType": "NOT_EQUAL"
- }
- ],
- "StackResourceDriftStatus": "MODIFIED",
- "Timestamp": "2023-05-23T09:31:32.470000+00:00"
- }
- ]
-}
- :::
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. [CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。必要に応じて、 **スタック** メニュー項目を選択してスタックを確認します。
- 1. 前のステップで作成したスタック (例えば、`cfn-workshop-drift-detection-workshop`) を選択します。
- 1. **スタックアクション** から、 **ドリフトの検出** を選択します。
- 1. **スタックの情報** タブに移動し、 **ドリフトステータス** フィールドに `DRIFTED` と表示されるまでページを更新します。なお、ドリフト検出が完了するまでに少し時間がかかります。
- 1. **スタックアクション** から、 **ドリフト結果を表示** を選択します。
- 1. ドリフトステータスページが表示されます。画面では、`Table1` が変更され、`Queue1` がテンプレートと同期されていることがわかります。
- 1. **リソースのドリフトステータス** ビューから `Table1` を選択し、次に **ドリフトの詳細を表示** を選択します。
- 1. 次に、`Table1` のドリフトの詳細を確認すると、3 つの差分があります。コンソールで行った変更に応じて `BillingMode` プロパティが変更され、`ProvisionedThroughput` の値もその変更の一部として DynamoDB によって更新されました。 **違い** ビューで各プロパティを選択すると、関連するテンプレートの違いが強調表示されます。
- ::::
- :::::
-
-これで、構成ドリフトを修正するために必要な情報が揃い、希望する構成がテンプレートと再び一致するようになりました。以下の手順に従ってテーブル設定を更新してください。
-
-1. [DynamoDB コンソール](https://console.aws.amazon.com/dynamodb) に戻り、以前と同じように **設定の更新** を選択します。
-1. **Table1** のエントリを選択し、 **追加の設定** タブに移動します。
-1. **編集** を選択します。
-1. **プロビジョニング** キャパシティモードを選択します。
-1. **読み取りキャパシティー** と **書き込みキャパシティー** の両方で、 **Auto Scaling** を **オフ** にします。
-1. 読み取りキャパシティーと書き込みキャパシティーの **プロビジョンドキャパシティーユニット** 両方に `1` を入力します。
-1. **変更を保存** をクリックします。
-
-リソースはテンプレートと同期され、元の構成に復元されました。先ほど行ったようにスタックのドリフト検出を実行すると、 **スタック情報** タブの **ドリフトステータス** フィールドに `IN_SYNC` と表示されるはずです。
-
-### テンプレートの更新によるドリフトの検出と修復
-
-前のセクションでデプロイしたテンプレートで Amazon SQS キューが作成されました。次に、キューのプロパティを変更し、CloudFormation がドリフトを検出していることを確認してから、新しいリソース設定と一致するようにテンプレートを更新します。まず、キューを変更します。
-
-
-1. [Amazon SQS コンソール](https://console.aws.amazon.com/sqs/) に移動します。
-1. 必要に応じて、左側の折りたたまれたメニューを選択して展開し、 **キュー** を選択します。
-1. スタックの名前で始まる名前のキュー (例: `cfn-workshop-drift-detection-workshop`) を見つけて選択します。
-1. **編集** を選択します。
-1. **メッセージ保持期間** を `4` ではなく `2` 日に変更し、ページの一番下にある **保存** をクリックします。
-
-このステップでは、CloudFormation を使用してキューリソースのドリフトを検出します。
-
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **ドリフト検出** を行うために `cfn-workshop-drift-detection` スタックに対して次のコマンドを実行します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection
- :::
- 1. CloudFormation は次の結果を返却します。
- :::code{language=json showLineNumbers=false showCopyAction=true}
- "StackDriftDetectionId": "2c320c80-f954-11ed-9e69-0a031a01f375"
- :::
- 1. ドリフト検出操作の実行結果をステップ 2 で得られた `stack-drift-detection-id` を使って確認します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-drift-detection-status \
---stack-drift-detection-id stack-drift-detection-id
- :::
- 1. `describe-stack-drift-detect-status` コマンドが成功すると、CloudFormation は`"DetectionStatus":"DETECTION_COMPLETE"` と `"StackDriftStatus":"DRIFTED"` の情報を返却します。
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=4-5}
-{
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/2c320c80-f954-11ed-9e69-0a031a01f375",
- "StackDriftDetectionId": "35768f30-f947-11ed-9dc9-0eb469d3b073",
- "StackDriftStatus": "DRIFTED",
- "DetectionStatus": "DETECTION_COMPLETE",
- "DriftedStackResourceCount": 1,
- "Timestamp": "2023-05-23T08:52:55.332000+00:00"
-}
- :::
- 1. ドリフトしたリソースの詳細を確認するため次のコマンドを実行します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-resource-drifts \
---stack-name cfn-workshop-drift-detection
- :::
- 1. `descibe-stack-resource-drifts` コマンドの出力結果に `Queue1` リソースのドリフトした内容が `Property Differences` の中で示されています。
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=10-17}
-{
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/6a9d0720-f94c-11ed-8f4f-0e06081e3865",
- "LogicalResourceId": "Queue1",
- "PhysicalResourceId": "https://sqs.us-east-1.amazonaws.com/123456789012/cfn-workshop-drift-detection-Queue1-9vq6DP77LiCe",
- "ResourceType": "AWS::SQS::Queue",
- "ExpectedProperties": "{\"MessageRetentionPeriod\":345600}",
- "ActualProperties": "{\"MessageRetentionPeriod\":172800}",
- "PropertyDifferences": [
- {
- "PropertyPath": "/MessageRetentionPeriod",
- "ExpectedValue": "345600",
- "ActualValue": "172800",
- "DifferenceType": "NOT_EQUAL"
- }
- ],
- "StackResourceDriftStatus": "MODIFIED",
- "Timestamp": "2023-05-23T10:25:44.111000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/6a9d0720-f94c-11ed-8f4f-0e06081e3865",
- "LogicalResourceId": "Table1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-Table1-1VFN7I198DR33",
- "ResourceType": "AWS::DynamoDB::Table",
- "ExpectedProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"WriteCapacityUnits\":1,\"ReadCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeType\":\"S\",\"AttributeName\":\"Album\"},{\"AttributeType\":\"S\",\"AttributeName\":\"Artist\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "ActualProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"ReadCapacityUnits\":1,\"WriteCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeName\":\"Album\",\"AttributeType\":\"S\"},{\"AttributeName\":\"Artist\",\"AttributeType\":\"S\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T10:25:44.761000+00:00"
- }
- ]
-}
- :::
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. [CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。必要な場合は、 **スタック** メニュー項目を選択してスタックを確認してください。
- 1. 前のステップで作成したスタック (例えば、`cfn-workshop-drift-detection-workshop`) を選択します。
- 1. **スタックアクション** から、 **ドリフトの検出** を選択します。
- 1. ドリフト検出が完了するまで数秒待ってください。 **ドリフトステータス** フィールドに `DRIFTED` と表示されるまで、スタック情報ページを更新します。
- 1. **スタックアクション** から、 **ドリフト結果を表示** を選択します。
- 1. ドリフトステータスページが表示され、`Queue1` が変更されたことが示されます。
- 1. `Queue1` を選択し、 **ドリフトの詳細を表示** を選択します。
- 1. `Queue1` のドリフトの詳細を確認します。差分が 1 つあることが確認できます。コンソールで行った変更に応じて、`MessageRetentionPeriod` プロパティが変更されました。
- ::::
- :::::
-
-次に、リソースの新しい状態に合わせてテンプレートを更新し、スタックを同期し直します。
-
-1. お好みのテキストエディターで、ワークショップのテンプレートファイルを開きます。
-1. `Queue1` の `MessageRetentionPeriod` を、前のステップで見たドリフト詳細ページの **現在の値** 列に表示された値と一致するように変更します。テンプレートの `MessageRetentionPeriod` の値を `172800` に設定します。これは `2` 日間の秒数です。
-1. テンプレートファイルを保存します。
-1. 以下の手順でスタックを更新しましょう。
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **Code Editor のターミナル** 上で `cfn101-workshop/code/workspace/drift-detection` ディレクトリに移動します:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/drift-detection
- :::
- 1. AWS CLI コマンドを使って `cfn-workshop-drift-detection` スタックを更新します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack \
---stack-name cfn-workshop-drift-detection \
---template-body file://drift-detection-workshop.yaml
- :::
- 1. `update-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
- :::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
- 1. 次のコマンドで `UPDATE` 操作が完了するまで待ちます。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-drift-detection
- :::
- 1. 確認のため、`cfn-workshop-drift-detection`スタックに対して **ドリフト検出** を行います。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection
- :::
- 1. ドリフトしたリソースの詳細を確認するため次のコマンドを実行します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-resource-drifts \
---stack-name cfn-workshop-drift-detection
- :::
- 1. ドリフトのステータスが`IN_SYNC`であることを確認できれば、テンプレートとリソースが一致しています。
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=11,22}
- {
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/6a9d0720-f94c-11ed-8f4f-0e06081e3865",
- "LogicalResourceId": "Queue1",
- "PhysicalResourceId": "https://sqs.us-east-1.amazonaws.com/123456789012/cfn-workshop-drift-detection-Queue1-9vq6DP77LiCe",
- "ResourceType": "AWS::SQS::Queue",
- "ExpectedProperties": "{\"MessageRetentionPeriod\":172800}",
- "ActualProperties": "{\"MessageRetentionPeriod\":172800}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T10:54:21.628000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/6a9d0720-f94c-11ed-8f4f-0e06081e3865",
- "LogicalResourceId": "Table1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-Table1-1VFN7I198DR33",
- "ResourceType": "AWS::DynamoDB::Table",
- "ExpectedProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"WriteCapacityUnits\":1,\"ReadCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeType\":\"S\",\"AttributeName\":\"Album\"},{\"AttributeType\":\"S\",\"AttributeName\":\"Artist\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "ActualProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"ReadCapacityUnits\":1,\"WriteCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeName\":\"Album\",\"AttributeType\":\"S\"},{\"AttributeName\":\"Artist\",\"AttributeType\":\"S\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T10:54:22.168000+00:00"
- }
- ]
- }
- :::
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. [CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
- 1. 前で実施した操作と同様に、スタックを選択します。
- 1. **更新** を選択します。
- 1. **既存テンプレートを置き換える** を選択し、 **テンプレートファイルのアップロード** を選択します。
- 1. **ファイルを選択** を使用して、更新されたテンプレートファイルを選択します。
- 1. **次へ** をクリックします。
- 1. スタックの詳細ページで、 **次へ** をクリックします。
- 1. スタックのオプションページで、 **次へ** をクリックします。
- 1. **送信** をクリックします。
- 1. スタックの更新が完了するまでお待ちください。ページを更新して現在の状態を読み込みます。
- 1. **スタックの情報** タブを選択します。
- 1. **スタックアクション** から、 **ドリフトの検出** を選択します。
- 1. ドリフト検出が完了するまで数秒待ってください。
- 1. これで、ドリフトステータスが `IN_SYNC` になり、テンプレートとリソースが一致していることがわかります。
- ::::
- :::::
-
-
-おめでとうございます! リソースの新しい状態に一致するようにテンプレートを更新することで、スタックのずれを修復する方法を学びました。
-
-### チャレンジ
-
-この演習では、このラボの前半で得た知識と、前回の [リソースインポート](/intermediate/operations/resource-importing.html) のラボで得た知識を使用して、CloudFormation スタックの範囲外でリソースが更新された場合の問題を解決します。その構成に差分が出ましたが、リソースを [中断](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html) せずに CloudFormation スタックを一致するように更新することはできません。スタックからリソースを削除し、更新されたプロパティを使用してリソースをインポートする必要があります。
-
-はじめに、以下の手順に従ってください。
-
-1. お気に入りのエディターで `drift-detection-challenge.yaml` ファイルを開きます。
-1. 以下の内容を `drift-detection-challenge.yaml` テンプレートに追加し、ファイルを保存します。このテンプレートは、最新の Amazon Linux 2 AMI を使用して [Amazon Elastic Compute Cloud](https://aws.amazon.com/ec2/) (Amazon EC2) インスタンスを起動し、初回起動時に `Hello World` と出力されるスクリプトを実行するように設定します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=5}
-Parameters:
- LatestAmiId:
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-
-Resources:
- Instance1:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- UserData: !Base64 |
- #!/usr/bin/env bash
- echo Hello World
-
- Bucket1:
- Type: AWS::S3::Bucket
-:::
-
-:::alert{type="info"}
-この `UserData` スクリプトは、インスタンスの初回起動時にのみ実行されます。起動のたびにスクリプトを実行するために[設定を作成する](https://repost.aws/ja/knowledge-center/execute-user-data-ec2)のも良いですが、今回のワークショップではテンプレートの複雑さを低く抑えるため、このテンプレートでは簡単な内容だけを紹介します。
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor のターミナル** 上で `cfn101-workshop/code/workspace/drift-detection` ディレクトリに移動します:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/drift-detection
-:::
-1. AWS CLI を使用してスタックを作成します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-drift-detection-challenge \
---template-body file://drift-detection-challenge.yaml
-:::
-1. 次のコマンドで `CREATE` 操作が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. 以下のコマンドを実行し `Instance1` の **物理 ID** を取得します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. コマンドを実行すると CloudFormation は以下の結果を返却します。`Instance1` の **物理 ID** をメモしておきます。
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=19}
-{
- "StackResources": [
- {
- "StackName": "cfn-workshop-drift-detection-challenge",
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Bucket1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-challenge-bucket1-1svpxjottevmx",
- "ResourceType": "AWS::S3::Bucket",
- "Timestamp": "2023-05-23T12:27:57.391000+00:00",
- "ResourceStatus": "CREATE_COMPLETE",
- "DriftInformation": {
- "StackResourceDriftStatus": "NOT_CHECKED"
- }
- },
- {
- "StackName": "cfn-workshop-drift-detection-challenge",
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Instance1",
- "PhysicalResourceId": "i-1234567890abcdef0",
- "ResourceType": "AWS::EC2::Instance",
- "Timestamp": "2023-05-23T12:28:09.726000+00:00",
- "ResourceStatus": "CREATE_COMPLETE",
- "DriftInformation": {
- "StackResourceDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. **スタックの作成** から、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択し、`drift-detection-challenge.yaml` ファイルをアップロードして、 **次へ** をクリックします。
-1. スタック名 (例えば、`cfn-workshop-drift-detection-challenge`) を入力し、 **次へ** をクリックします。
-1. **スタックオプションの設定** ページで、 **次へ** をクリックします。
-1. 次のページで、 **送信** をクリックします。
-1. スタックが作成されたら、`cfn-workshop-drift-detection-challenge` スタックを選択し、 **リソース** を選択します。例えば、`i-1234567890abcdef0` のような形式で記述された、`Instance1` の **物理 ID** をメモしておきます。
-::::
-:::::
-
-次に、ドリフトを導入した最初のラボと同様の方法でこのリソースを変更します。変更する `UserData` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-userdata) ではまずインスタンスを停止する必要があるため、この変更により中断が発生します。出力されるメッセージを `Hello Universe` に変更します。
-
-1. [Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/) に移動します。
-1. **インスタンス** セクションを見つけて、上に記録された ID のインスタンスを選択します。
-1. **インスタンスの状態** から、 **インスタンスを停止** を選択し、 **停止** ボタンをクリックします。
-1. インスタンスの状態が `停止済み` に変わるのを待ちます。必要に応じてページを更新してください。
-1. インスタンスの状態が `停止済み` になったら、必要に応じてインスタンスを再度選択し、 **アクション** から **インスタンス設定** を選択し、 **ユーザーデータを編集** を選択します。
-1. **新しいユーザーデータ** として、以下のように Hello World を Hello Universe に変更します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-#!/usr/bin/env bash
-echo Hello Universe
-:::
-1. **保存** をクリックします。
-1. インスタンスをもう一度選択し、 **インスタンスの状態** から **インスタンスを開始** を選択します。
-1. インスタンスの状態が `実行中` に変わるのを待ちます。必要に応じてページを更新してください。
-
-このステップでは、CloudFormation ドリフト検出を使用して、元のテンプレートと比較して `Instance1` リソースに加えられた変更を特定します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. `Instance1` の変更を特定しましょう。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. 以下のコマンドを AWS CLI で実行して **ドリフトの検出結果** を確認します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resource-drift \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. `descibe-stack-resource-drifts` コマンドの出力結果でリソースのドリフトした内容が `Property Differences` に示されています。
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=21-28}
-{
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Bucket1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-challenge-bucket1-1svpxjottevmx",
- "ResourceType": "AWS::S3::Bucket",
- "ExpectedProperties": "{}",
- "ActualProperties": "{}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T12:52:07.616000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Instance1",
- "PhysicalResourceId": "i-0113f35b272b0f04e",
- "ResourceType": "AWS::EC2::Instance",
- "ExpectedProperties": "{\"ImageId\":\"ami-0d52ddcdf3a885741\",\"InstanceType\":\"t2.micro\",\"UserData\":\"IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==\"}",
- "ActualProperties": "{\"ImageId\":\"ami-0d52ddcdf3a885741\",\"InstanceType\":\"t2.micro\",\"UserData\":\"IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFVuaXZlcnNl\"}",
- "PropertyDifferences": [
- {
- "PropertyPath": "/UserData",
- "ExpectedValue": "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==",
- "ActualValue": "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFVuaXZlcnNl",
- "DifferenceType": "NOT_EQUAL"
- }
- ],
- "StackResourceDriftStatus": "MODIFIED",
- "Timestamp": "2023-05-23T12:52:08.421000+00:00"
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。必要な場合は、 **スタック** メニュー項目を選択してください。
-1. 前のステップで作成したスタック (例えば、`cfn-workshop-drift-detection-challenge`) を選択します。
-1. **スタックアクション** から、 **ドリフトの検出** を選択します。
-1. ドリフト検出が完了するまでに少し時間がかかります。 **ドリフトステータス** フィールドに `Drifted` と表示されるまで、スタック情報ページを更新します。
-1. **スタックアクション** から、 **ドリフト結果を表示** を選択します。
-1. ドリフトステータスページが表示され、`Instance1` が変更されたことが示されます。
-1. `Instance1` を選択し、 **ドリフトの詳細を表示** を選択します。
-1. ドリフトの詳細は、`UserData` プロパティが変更されたことを示しています。`UserData` プロパティは Base64 エンコーディングを使用して保存されるため、行った正確な変更は画面上では分かりません。
-::::
-:::::
-:::alert{type="info"}
-ツールを使って Base64 のテキストをデコードし、それが表すシェルスクリプトを見ることができます。例えば、 Linux では、`base64` コマンドラインツールを使用して次のように処理できます。macOS などの一部の実装では、`base64` コマンドのオプションとして `-d` の代わりに `-D` を使用していることに注意してください。
-:::
-
-例えば、次のコマンドを実行すると、
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-echo "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==" | base64 -d
-:::
-
-次の出力が表示されるはずです。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-#!/usr/bin/env bash
-echo Hello World
-:::
-
-:::alert{type="warning"}
-UserData の base64 テキストを外部の Web サイトを使用してエンコードまたはデコードする場合、特に機密情報が含まれている可能性がある場合は注意が必要です。
-:::
-
-ここでのタスクは、それ以上中断することなく、スタックをリソースの新しい状態で更新することです。
-
-:::expand{header= "ヒントが必要ですか?"}
-* リソースをスタックからデタッチし、`UserData` を修正して再度インポートする必要があります。`UserData` を Base64 に変換する必要はありません。
-* 詳細なガイダンスについては、[リソースインポート](/intermediate/operations/resource-importing.html) ラボを参照してください。
-:::
-::::::expand{header="解決策を確認しますか?"}
-1. `drift-detection-challenge.yaml` テンプレートを更新して、値が `Retain` の `DeletionPolicy` 属性を `Instance1` リソースに追加し、ファイルを保存します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=10 highlightLines=12}
-Resources:
- Instance1:
- DeletionPolicy: Retain
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- UserData: !Base64 |
- #!/usr/bin/env bash
- echo Hello World
-:::
-1. 更新された `drift-detection-challenge.yaml` テンプレートでスタックを更新します。これにより、CloudFormation は、テンプレートからリソースを削除しても、そのリソースは削除せず、管理を停止するだけとなります。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-drift-detection-challenge \
---template-body file://drift-detection-challenge.yaml
-:::
-1. スタックの更新が完了したら、テンプレートファイルをもう一度編集して Resources 宣言全体を削除し (関連する各行の先頭にある `#` 文字を使用してコメントアウトしても良いです)、ファイルを保存します。
-1. 更新されたテンプレートファイルでスタックを更新します。CloudFormation はインスタンスを終了せずにスタックから削除します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-drift-detection-challenge \
---template-body file://drift-detection-challenge.yaml
-:::
-1. テンプレートファイルを編集してリソースを復元し、以前に行った変更と一致するように UserData を更新します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=10 highlightLines=19}
-Resources:
- Instance1:
- DeletionPolicy: Retain
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- UserData: !Base64 |
- #!/usr/bin/env bash
- echo Hello Universe
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. IMPORT 操作のためにリソースを記述するテキストファイルを作成します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch resources-import.txt
-:::
-1. 以下のコードをコピーして `resources-import.txt` にペーストします。[**識別子**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview)の値はこのパートの前に、メモをしたインスンスの **物理 ID** に置き換えます。
-:::code{language=json showLineNumbers=false showCopyAction=true}
-[
- {
- "ResourceType":"AWS::EC2::Instance",
- "LogicalResourceId":"Instance1",
- "ResourceIdentifier": {
- "InstanceId":"i-12345abcd6789"
- }
- }
-]
-:::
-1. リソースのインポートを行うために、次のコマンドを使って `cfn-workshop-drift-detection-challenge` スタックを更新します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-drift-detection-challenge \
---change-set-name drift-challenge --change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://drift-detection-challenge.yaml
-:::
-1. 次のコマンドを使って変更セットを実行します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation execute-change-set \
---stack-name cfn-workshop-drift-detection-challenge \
---change-set-name drift-challenge
-:::
-1. 次のコマンドで `IMPORT` 操作が完了するのを待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. `cfn-workshop-drift-detection-challenge` スタックのドリフト検出を確認します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. `descibe-stack-resource-drifts`コマンドの実行結果を確認すると、ドリフトの詳細で `Instance1` インスタンスの状態がスタックと同じであることが確認できます。
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=11,22}
-{
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Bucket1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-challenge-bucket1-1svpxjottevmx",
- "ResourceType": "AWS::S3::Bucket",
- "ExpectedProperties": "{}",
- "ActualProperties": "{}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T17:29:29.338000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:402198065244:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Instance1",
- "PhysicalResourceId": "i-0113f35b272b0f04e",
- "ResourceType": "AWS::EC2::Instance",
- "ExpectedProperties": "{\"ImageId\":\"ami-0d52ddcdf3a885741\",\"InstanceType\":\"t2.micro\",\"UserData\":\"IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==\"}",
- "ActualProperties": "{\"ImageId\":\"ami-0d52ddcdf3a885741\",\"InstanceType\":\"t2.micro\",\"UserData\":\"IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==\"}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T17:29:30.015000+00:00"
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. CloudFormation コンソールでスタックを選択し、 **スタックアクション** から **スタックへのリソースのインポート** を選択します。
-1. **次へ** をクリックします。
-1. テンプレートファイルをアップロードします。
-1. インスタンスの物理 ID を入力し、 **次へ** をクリックします。
-1. **スタックの詳細を指定** で、 **次へ** をクリックします。
-1. **リソースをインポート** を選択します。
-1. スタックの操作が完了し、リソースがインポートされたら、ドリフト検出を実行して、インスタンスがスタックテンプレートと同期していることを確認できます。
-::::
-:::::
-ソリューションのテンプレートは `code/solutions/drift-detection/drift-detection-workshop.yaml` にあります。
-
-おめでとうございます! これで、リソースを削除して再インポートすることで、影響なしにドリフトを修復する方法がわかりました。
-::::::
-
-### クリーンアップ
-
-次に示す手順に従って、このワークショップで作成したリソースをクリーンアップしてください。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. AWS CLI を使って S3 バケットを削除します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3 rb s3://drift-detection-challenge-AWS_ACCOUNT_ID --force
-:::
-1. `cfn-workshoop-drift-detection-workshop` スタックを削除します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-drift-detection-workshop
-:::
-1. `cfn-workshop-drift-detection-challenge` スタックの `DeletionPolicy` を `Delete` に変更するため、テンプレートファイルを編集します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=10 highlightLines=12}
-Resources:
- Instance1:
- DeletionPolicy: Delete
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- UserData: !Base64 |
- #!/usr/bin/env bash
- echo Hello Universe
-:::
-1. AWS CLI を使用してスタックを作成します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-drift-detection-challenge \
---template-body file://drift-detection-challenge.yaml
-:::
-1. スタックの更新が完了した後に、スタックの削除を行います。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. CloudFormation コンソールに移動します。
-1. 最初のラボで作成したスタック (例えば、`cfn-workshop-drift-detection-workshop`) を選択します。
-1. **削除** を選択し、 **削除** をクリックします。
-1. `cfn-workshop-drift-detection-challenge` スタックのために使ったテンプレートファイルを編集して `DeletionPolicy` を `Delete` に変更します。
-1. スタックを選択して **更新** を選択します。次に **既存テンプレートを置き換える** を選択し、更新されたファイルをアップロードすることでスタックを更新します。 **次へ** を 3 回選択し、最後に **送信** をクリックします。スタックの更新が完了するまでお待ちください。
-1. `cfn-workshop-drift-detection-challenge` スタックを選択し、 **削除** を選択後、 **削除** ボタンをクリックします。
-::::
-:::::
-
----
-
-
-### まとめ
-
-このラボでは、CloudFormation スタックのドリフトを検出して、CloudFormation の外部で変更されたリソースを見つけ、変更の詳細を確認する方法を学びました。リソースがテンプレートと一致するように正しく変更されたことを確認する方法と、リソースの望ましい状態に一致するようにスタックを更新する方法を学びました。最後に、影響を受けたリソースを削除して再インポートすることでドリフトを修正する方法を学びました。
diff --git a/content/intermediate/operations/drift-detection/index.md b/content/intermediate/operations/drift-detection/index.md
deleted file mode 100644
index 8601ae44b..000000000
--- a/content/intermediate/operations/drift-detection/index.md
+++ /dev/null
@@ -1,756 +0,0 @@
----
-title: "Drift Detection"
-weight: 500
----
-
-### Overview
-
-When you choose to use [AWS CloudFormation](https://aws.amazon.com/cloudformation/) to provision your resources, you maintain your resources’ configurations with CloudFormation over time, as needed. If, subsequently, you choose to manage such resources outside the purview of CloudFormation (for example, with the [AWS Management Console](https://aws.amazon.com/console/), the [AWS Command Line Interface](https://aws.amazon.com/cli/) (AWS CLI), [AWS SDKs](https://aws.amazon.com/getting-started/tools-sdks/), or with [AWS APIs](https://docs.aws.amazon.com/general/latest/gr/aws-apis.html), your resources’ configuration will drift.)
-
-CloudFormation offers [Drift Detection](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-drift.html), that gives you information on the difference between the current configuration of a resource and the configuration you declared in the template you used to create or update the resource. The results of drift detection show you the affected resources and the differences between the current state and the template. You can then either return the resource to its original configuration, or update your template and your CloudFormation stack to reflect the new, desired state.
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* Use CloudFormation Drift Detection to detect drift on stack resources.
-* Understand how to interpret the Drift Detection results to identify which resource properties have changed.
-* Modify a resource to return it to its original configuration.
-* Update a template to match the new configuration of a resource.
-* Use resource import to update the stack and template to match the new configuration of a resource.
-
-### Start Lab
-
-You will deploy an example AWS CloudFormation template which contains an [Amazon DynamoDB](https://aws.amazon.com/dynamodb/) table and an [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) queue as a new stack. You will then perform a number of configuration changes to the provisioned resources, and use Drift Detection to identify them. You will then resolve the drift by correcting the resource configuration or updating the template to reflect the new configuration.
-
-To get started, follow these steps:
-
-1. Change directory to the `code/workspace/drift-detection` directory.
-1. Copy the code below, and append it to the `drift-detection-workshop.yaml` file, and save the file:
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=5}
-Resources:
- Table1:
- Type: AWS::DynamoDB::Table
- Properties:
- AttributeDefinitions:
- - AttributeName: Album
- AttributeType: S
- - AttributeName: Artist
- AttributeType: S
- BillingMode: PROVISIONED
- KeySchema:
- - AttributeName: Album
- KeyType: HASH
- - AttributeName: Artist
- KeyType: RANGE
- ProvisionedThroughput:
- ReadCapacityUnits: 1
- WriteCapacityUnits: 1
-
- Queue1:
- Type: AWS::SQS::Queue
- Properties:
- MessageRetentionPeriod: 345600
-:::
-
-1. Familiarise yourself with the example resources in the template:
- 1. The DynamoDB [table](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html) has a minimal definition for the `KeySchema` and `AttributeDefinitions` properties in order to be successfully created. You will not be storing data in or retrieving data from the table during the workshop.
- 2. The SQS [queue](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html) has a `MessageRetentionPeriod` of four days (expressed in seconds). Note that although this value is the [default](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#cfn-sqs-queue-messageretentionperiod), CloudFormation only evaluates drift against properties that you explicitly declare in the template. If you do not include this property, CloudFormation will not report a change to it on the resource later on.
-1. In the next step, you will use the AWS CloudFormation to create a new stack using this template:
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. In the **Code Editor terminal** navigate to `cfn101-workshop/code/workspace/drift-detection`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/drift-detection
- :::
- 1. Create the stack by using the following AWS CLI command. For example use stack name as `cfn-workshop-drift-detection`
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
---stack-name cfn-workshop-drift-detection \
---template-body file://drift-detection-workshop.yaml
- :::
- 1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
- ::::
- ::::tab{id="local" label="Local Development"}
- 1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
- 1. From **Create stack**, choose **With new resources (standard)**.
- 1. From **Specify template**, choose **Upload a template file**. Choose the `drift-detection-workshop.yaml` template mentioned earlier, and then choose **Next**.
- 1. Enter a stack name. For example, specify `cfn-workshop-drift-detection`. Choose **Next**.
- 1. In **Configure stack options**, choose **Next**.
- 1. Choose **Submit**.
- 1. Refresh the stack creation page until you see your stack in the `CREATE_COMPLETE` state.
- ::::
- :::::
-
-### Detecting and repairing drift by modifying the resource
-
-Now you will modify the DynamoDB table directly, outside of CloudFormation.
-
-1. Navigate to the [Amazon DynamoDB Console](https://console.aws.amazon.com/dynamodb/).
-1. Under the **Tables** heading on the menu, choose **Update settings**.
-1. Choose the **Table1** entry (the table name will be prefixed with the name of your stack).
-1. Choose the **Additional settings** tab.
-1. In the **Read/write capacity** section, choose **Edit**.
-1. Choose the **On-demand** capacity mode, then choose **Save Changes**.
-
-In this step, you will use CloudFormation Drift Detection to identify the changes to the `Table1` resource compared to the original template.
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. Run the following AWS CLI command to **Detect Drift** for your stack `cfn-workshop-drift-detection`.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection
- :::
- 1. CloudFormation returns the following output.
- :::code{language=json showLineNumbers=false showCopyAction=true}
- "StackDriftDetectionId": "35768f30-f947-11ed-9dc9-0eb469d3b073"
- :::
- 1. Verify the status of drift detection operation with the `stack-drift-detection-id` that is returned as part of the output of step 2.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-drift-detection-status \
---stack-drift-detection-id stack-drift-detection-id
- :::
- 1. If the `describe-stack-drift-detect-status` command was successfully sent, CloudFormation wll return the information with `"DetectionStatus":"DETECTION_COMPLETE"` and `"StackDriftStatus":"DRIFTED"`.
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=4-5}
-{
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/83fd7940-f945-11ed-ab77-12daf0c351ad",
- "StackDriftDetectionId": "35768f30-f947-11ed-9dc9-0eb469d3b073",
- "StackDriftStatus": "DRIFTED",
- "DetectionStatus": "DETECTION_COMPLETE",
- "DriftedStackResourceCount": 1,
- "Timestamp": "2023-05-23T08:52:55.332000+00:00"
-}
- :::
- 1. Run the following command to describe drifted resources.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-resource-drifts \
---stack-name cfn-workshop-drift-detection
- :::
- 1. The drift details for `Table1` are shown in the output of `descibe-stack-resource-drifts` under `Property Differences` as highlighted in the below example.
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=21-34}
-{
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/83fd7940-f945-11ed-ab77-12daf0c351ad",
- "LogicalResourceId": "Queue1",
- "PhysicalResourceId": "https://sqs.us-east-1.amazonaws.com/123456789012/cfn-workshop-drift-detection-Queue1-LhZ9kuNmNV62",
- "ResourceType": "AWS::SQS::Queue",
- "ExpectedProperties": "{\"MessageRetentionPeriod\":345600}",
- "ActualProperties": "{\"MessageRetentionPeriod\":345600}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T08:42:44.951000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/83fd7940-f945-11ed-ab77-12daf0c351ad",
- "LogicalResourceId": "Table1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-Table1-173M9QVM1EZKE",
- "ResourceType": "AWS::DynamoDB::Table",
- "ExpectedProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"WriteCapacityUnits\":1,\"ReadCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeType\":\"S\",\"AttributeName\":\"Album\"},{\"AttributeType\":\"S\",\"AttributeName\":\"Artist\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "ActualProperties": "{\"BillingMode\":\"PAY_PER_REQUEST\",\"AttributeDefinitions\":[{\"AttributeName\":\"Album\",\"AttributeType\":\"S\"},{\"AttributeName\":\"Artist\",\"AttributeType\":\"S\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "PropertyDifferences": [
- {
- "PropertyPath": "/ProvisionedThroughput",
- "ExpectedValue": "{\"ReadCapacityUnits\":1,\"WriteCapacityUnits\":1}",
- "ActualValue": "null",
- "DifferenceType": "REMOVE"
- },
- {
- "PropertyPath": "/BillingMode",
- "ExpectedValue": "PROVISIONED",
- "ActualValue": "PAY_PER_REQUEST",
- "DifferenceType": "NOT_EQUAL"
- }
- ],
- "StackResourceDriftStatus": "MODIFIED",
- "Timestamp": "2023-05-23T09:31:32.470000+00:00"
- }
- ]
-}
- :::
- ::::
- ::::tab{id="local" label="Local Development"}
- 1. Navigate to the [CloudFormation Console](https://console.aws.amazon.com/cloudformation/). If necessary, choose the **Stacks** menu item to see your stacks.
- 1. Choose your stack created in the earlier steps (for example, `cfn-workshop-drift-detection`).
- 1. From **Stack actions**, choose **Detect Drift**.
- 1. Drift detection takes a few moments to complete. Navigate to the **Stack info** tab, and refresh the page until the **Drift status** field shows `DRIFTED`.
- 1. From **Stack actions**, choose **View drift results**.
- 1. The drift status page displays, showing that `Table1` has been modified and `Queue1` is still in sync with the template.
- 1. From the **Resource drift status** view, select `Table1`; next, choose **View drift details**.
- 1. The drift details for `Table1` will show next, giving three differences. The `BillingMode` property has changed per the change you made in the Console, and the `ProvisionedThroughput` values have also been updated by DynamoDB as part of that change. You can select each property in the **Differences** view to see, highlighted, related template differences.
- ::::
- :::::
-You now have the necessary information to correct the configuration drift, and have your desired configuration match your template again. Follow these steps to update your table configuration:
-
-1. Return to the [DynamoDB Console](https://console.aws.amazon.com/dynamodb), then choose **Update settings** as before.
-1. Choose the entry for **Table1**, and then navigate to the **Additional settings** tab.
-1. Choose **Edit**.
-1. Choose **Provisioned** capacity mode.
-1. Choose **Off** for **Auto scaling** for both **Read capacity** and **Write capacity**.
-1. Enter `1` for both Read and Write capacity **provisioned capacity units**.
-1. Choose **Save changes**.
-
-The resource is now in sync with template, restored to its original configuration. If you perform the drift detection on the stack as you did earlier, in the **Stack info** tab you should now see `IN_SYNC` for the **Drift status** field.
-
-### Detecting and repairing drift by updating the template
-
-The template you deployed in the previous section also created an Amazon SQS queue. You will now modify a property of the queue, verify that CloudFormation detects the drift, and then update the template to match the new resource configuration. You will start by modifying the queue.
-
-1. Navigate to the [Amazon SQS Console](https://console.aws.amazon.com/sqs/).
-1. If necessary, choose the collapsed menu on the left to expand it, then choose **Queues**.
-1. Locate the queue which has a name starting with the name of your stack (e.g. `cfn-workshop-drift-detection`) and choose it.
-1. Choose **Edit**.
-1. Modify the **Message Retention Period** to be `2` days instead of `4`, then choose **Save** at the bottom of the page.
-
-In this step, you will detect the drift on the Queue resource using CloudFormation.
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. Run the following AWS CLI command to **Detect Drift** for your stack `cfn-workshop-drift-detection`.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection
- :::
- 1. CloudFormation returns the following output.
- :::code{language=json showLineNumbers=false showCopyAction=true}
- "StackDriftDetectionId": "2c320c80-f954-11ed-9e69-0a031a01f375"
- :::
- 1. Verify the status of drift detection operation with the `stack-drift-detection-id` that is returned as part of the output of step 2.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-drift-detection-status \
---stack-drift-detection-id stack-drift-detection-id
- :::
- 1. If the `describe-stack-drift-detect-status` command was successfully sent, CloudFormation wll return the information with `"DetectionStatus":"DETECTION_COMPLETE"` and `"StackDriftStatus":"DRIFTED"`.
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=4-5}
-{
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/2c320c80-f954-11ed-9e69-0a031a01f375",
- "StackDriftDetectionId": "35768f30-f947-11ed-9dc9-0eb469d3b073",
- "StackDriftStatus": "DRIFTED",
- "DetectionStatus": "DETECTION_COMPLETE",
- "DriftedStackResourceCount": 1,
- "Timestamp": "2023-05-23T08:52:55.332000+00:00"
-}
- :::
- 1. Run the following command to describe drifted resources.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-resource-drifts \
---stack-name cfn-workshop-drift-detection
- :::
- 1. The drift details for `Queue1` are shown in the output of `descibe-stack-resource-drifts` under `Property Differences` as highlighted in the below example.
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=10-17}
-{
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/6a9d0720-f94c-11ed-8f4f-0e06081e3865",
- "LogicalResourceId": "Queue1",
- "PhysicalResourceId": "https://sqs.us-east-1.amazonaws.com/123456789012/cfn-workshop-drift-detection-Queue1-9vq6DP77LiCe",
- "ResourceType": "AWS::SQS::Queue",
- "ExpectedProperties": "{\"MessageRetentionPeriod\":345600}",
- "ActualProperties": "{\"MessageRetentionPeriod\":172800}",
- "PropertyDifferences": [
- {
- "PropertyPath": "/MessageRetentionPeriod",
- "ExpectedValue": "345600",
- "ActualValue": "172800",
- "DifferenceType": "NOT_EQUAL"
- }
- ],
- "StackResourceDriftStatus": "MODIFIED",
- "Timestamp": "2023-05-23T10:25:44.111000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/6a9d0720-f94c-11ed-8f4f-0e06081e3865",
- "LogicalResourceId": "Table1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-Table1-1VFN7I198DR33",
- "ResourceType": "AWS::DynamoDB::Table",
- "ExpectedProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"WriteCapacityUnits\":1,\"ReadCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeType\":\"S\",\"AttributeName\":\"Album\"},{\"AttributeType\":\"S\",\"AttributeName\":\"Artist\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "ActualProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"ReadCapacityUnits\":1,\"WriteCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeName\":\"Album\",\"AttributeType\":\"S\"},{\"AttributeName\":\"Artist\",\"AttributeType\":\"S\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T10:25:44.761000+00:00"
- }
- ]
-}
- :::
- ::::
- ::::tab{id="local" label="Local Development"}
- 1. Navigate to the [CloudFormation Console](https://console.aws.amazon.com/cloudformation/). If necessary, choose the **Stacks** menu item to see your stacks.
- 1. Choose your stack created in the earlier steps (for example, `drift-detection-workshop`).
- 1. From **Stack actions**, choose **Detect Drift**.
- 1. Wait a few seconds for drift detection to complete. Refresh the stack info page until the **Drift status** field shows `DRIFTED`.
- 1. From **Stack actions**, choose **View drift results**.
- 1. The drift status page displays, showing that `Queue1` has been modified.
- 1. Select `Queue1`, and then choose **View drift details**.
- 1. The drift details for `Queue1` show, giving one difference. The `MessageRetentionPeriod` property has changed per the change you made in the Console.
- ::::
- :::::
-You will now update the template to match the new state of the resource and bring the stack back into sync.
-
-1. In your text editor, open the template file `drift-detection-workshop.yaml` for the workshop.
-1. Modify `Queue1`'s `MessageRetentionPeriod` to match the value shown in the **Actual** column of the drift details page you saw in the previous step. In your template, set the value for `MessageRetentionPeriod` to `172800`, that is the number of seconds in `2` days.
-1. Save the template file.
-1. It’s now time to update your stack! Follow steps below:
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. In the **Code Editor terminal** ensure your working directory is `cfn101-workshop/code/workspace/drift-detection`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/drift-detection
- :::
- 1. Update the stack `cfn-workshop-drift-detection` by using the following AWS CLI command.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack \
---stack-name cfn-workshop-drift-detection \
---template-body file://drift-detection-workshop.yaml
- :::
- 1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
- 1. Wait for the `UPDATE` operation to complete by running the following AWS CLI command.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-drift-detection
- :::
- 1. Run the following AWS CLI command to **Detect Drift** for your stack `cfn-workshop-drift-detection`.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection
- :::
- 1. Run the following command to describe drifted resources.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stack-resource-drifts \
---stack-name cfn-workshop-drift-detection
- :::
- 1. You should now see that the drift status is `IN_SYNC`, showing that the template and resource match.
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=11,22}
- {
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/6a9d0720-f94c-11ed-8f4f-0e06081e3865",
- "LogicalResourceId": "Queue1",
- "PhysicalResourceId": "https://sqs.us-east-1.amazonaws.com/123456789012/cfn-workshop-drift-detection-Queue1-9vq6DP77LiCe",
- "ResourceType": "AWS::SQS::Queue",
- "ExpectedProperties": "{\"MessageRetentionPeriod\":172800}",
- "ActualProperties": "{\"MessageRetentionPeriod\":172800}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T10:54:21.628000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection/6a9d0720-f94c-11ed-8f4f-0e06081e3865",
- "LogicalResourceId": "Table1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-Table1-1VFN7I198DR33",
- "ResourceType": "AWS::DynamoDB::Table",
- "ExpectedProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"WriteCapacityUnits\":1,\"ReadCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeType\":\"S\",\"AttributeName\":\"Album\"},{\"AttributeType\":\"S\",\"AttributeName\":\"Artist\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "ActualProperties": "{\"BillingMode\":\"PROVISIONED\",\"ProvisionedThroughput\":{\"ReadCapacityUnits\":1,\"WriteCapacityUnits\":1},\"AttributeDefinitions\":[{\"AttributeName\":\"Album\",\"AttributeType\":\"S\"},{\"AttributeName\":\"Artist\",\"AttributeType\":\"S\"}],\"KeySchema\":[{\"KeyType\":\"HASH\",\"AttributeName\":\"Album\"},{\"KeyType\":\"RANGE\",\"AttributeName\":\"Artist\"}]}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T10:54:22.168000+00:00"
- }
- ]
- }
- :::
- ::::
- ::::tab{id="local" label="Local Development"}
- 1. Navigate to the [CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
- 1. Choose your stack as before.
- 1. Choose **Update**.
- 1. Choose **Replace current template**, then choose **Upload a template file**.
- 1. Use **Choose file** to select your updated template file.
- 1. Choose **Next**.
- 1. On the stack details page, choose **Next**.
- 1. On the stack options page, choose **Next**.
- 1. Choose **Submit**.
- 1. Wait for the stack update to complete. Refresh the page to load the current state.
- 1. Choose the **Stack info** tab.
- 1. From **Stack actions**, choose **Detect Drift**.
- 1. Wait a few seconds for drift detection to complete.
- 1. You should now see that the drift status is `IN_SYNC`, showing that the template and resource match.
- ::::
- :::::
-
-Congratulations! You have learned how to repair stack drift by updating the template to match the new state of a resource.
-
-### Challenge
-
-In this exercise, you will use the knowledge gained from the earlier parts of this lab, along with the knowledge gained from the previous lab on [Resource Importing](/intermediate/operations/resource-importing.html), to solve an issue where a resource has been updated outside your CloudFormation stack’s purview and its configuration drifted, but you are unable to update the CloudFormation stack to match without causing an [interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html) to the resource. You should remove the resource from the stack, and then import it with the updated properties.
-
-To begin, follow the steps below:
-
-1. Open the `drift-detection-challenge.yaml` file in your favourite editor.
-1. Add the content below to the `drift-detection-challenge.yaml` template and save the file. This template will launch an [Amazon Elastic Compute Cloud](https://aws.amazon.com/ec2/) (Amazon EC2) instance using the latest Amazon Linux 2 AMI, and configure it to run a script on first boot, which prints `Hello World`.
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=5}
-Parameters:
- LatestAmiId:
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-
-Resources:
- Instance1:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- UserData: !Base64 |
- #!/usr/bin/env bash
- echo Hello World
-
- Bucket1:
- Type: AWS::S3::Bucket
-:::
-:::alert{type="info"}
-This `UserData` script will only run the first time the instance boots. You can [create a configuration](https://aws.amazon.com/premiumsupport/knowledge-center/execute-user-data-ec2/) which will run a script on every boot, but in order to keep the template complexity low for this workshop, this template just shows simple content.
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** ensure your working directory is `cfn101-workshop/code/workspace/drift-detection`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/drift-detection
-:::
-1. Use the AWS CLI to create the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-drift-detection-challenge \
---template-body file://drift-detection-challenge.yaml
-:::
-1. Wait for the `CREATE` operation to complete by using the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. Run the AWS CLI command to get the **Physical ID** for `Instance1`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. CloudFormation returns the following output. Take note of the **Physical ID** for `Instance1` as highlighted in the below example
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=19}
-{
- "StackResources": [
- {
- "StackName": "cfn-workshop-drift-detection-challenge",
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Bucket1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-challenge-bucket1-1svpxjottevmx",
- "ResourceType": "AWS::S3::Bucket",
- "Timestamp": "2023-05-23T12:27:57.391000+00:00",
- "ResourceStatus": "CREATE_COMPLETE",
- "DriftInformation": {
- "StackResourceDriftStatus": "NOT_CHECKED"
- }
- },
- {
- "StackName": "cfn-workshop-drift-detection-challenge",
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Instance1",
- "PhysicalResourceId": "i-1234567890abcdef0",
- "ResourceType": "AWS::EC2::Instance",
- "Timestamp": "2023-05-23T12:28:09.726000+00:00",
- "ResourceStatus": "CREATE_COMPLETE",
- "DriftInformation": {
- "StackResourceDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="Local Development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From **Create stack**, choose **With new resources (standard)**.
-1. From **Specify template**, choose **Upload a template file**, upload the `drift-detection-challenge.yaml` file and choose **Next**.
-1. Enter a stack name, for example `cfn-workshop-drift-detection-challenge` and choose **Next**.
-1. In **Configure Stack Options**, choose **Next**.
-1. In the next page, choose **Submit**.
-1. Once the stack is created, select the `cfn-workshop-drift-detection-challenge` stack and choose **Resources**. Take a note of the **Physical ID** for `Instance1`, for example `i-1234567890abcdef0`.
-::::
-:::::
-
-You will now modify this resource in a similar way to the first lab to introduce drift. This modification causes an interruption, as the `UserData` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-userdata) you will change requires the instance to be stopped first. You will change the message printed to read: `Hello Universe`.
-
-1. Navigate to the [Amazon EC2 Console](https://console.aws.amazon.com/ec2/).
-1. Locate the **Instances** section, and select the instance with the ID recorded above.
-1. From **Instance state**, choose **Stop instance**, then choose **Stop**.
-1. Wait for the instance state to change to `Stopped`. Refresh the page if necessary.
-1. Once the Instance state is `Stopped`, select the instance again if necessary, then from **Actions** choose **Instance settings**, then choose **Edit user data**.
-1. In **New user data**, modify the script to change Hello World to Hello Universe as below:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-#!/usr/bin/env bash
-echo Hello Universe
-:::
-1. Choose **Save**.
-1. Select the instance again, then from **Instance state**, choose **Start instance**.
-1. Wait for the instance state to change to `Running`. Refresh the page if necessary.
-
-In this step, you will use CloudFormation Drift Detection to identity the changes to the `Instance1` resource compared to the original template.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Let's try to identify the changes to the `Instance1`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. Verify the **Drift Results** by using the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resource-drift \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. The drift details for `Instance1` are shown in the output of `descibe-stack-resource-drifts` under `Property Differences` as highlighted in the below example.
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=21-28}
-{
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Bucket1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-challenge-bucket1-1svpxjottevmx",
- "ResourceType": "AWS::S3::Bucket",
- "ExpectedProperties": "{}",
- "ActualProperties": "{}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T12:52:07.616000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Instance1",
- "PhysicalResourceId": "i-0113f35b272b0f04e",
- "ResourceType": "AWS::EC2::Instance",
- "ExpectedProperties": "{\"ImageId\":\"ami-0d52ddcdf3a885741\",\"InstanceType\":\"t2.micro\",\"UserData\":\"IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==\"}",
- "ActualProperties": "{\"ImageId\":\"ami-0d52ddcdf3a885741\",\"InstanceType\":\"t2.micro\",\"UserData\":\"IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFVuaXZlcnNl\"}",
- "PropertyDifferences": [
- {
- "PropertyPath": "/UserData",
- "ExpectedValue": "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==",
- "ActualValue": "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFVuaXZlcnNl",
- "DifferenceType": "NOT_EQUAL"
- }
- ],
- "StackResourceDriftStatus": "MODIFIED",
- "Timestamp": "2023-05-23T12:52:08.421000+00:00"
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="Local Development"}
-1. Navigate to the [CloudFormation Console](https://console.aws.amazon.com/cloudformation/). If necessary, choose the **Stacks** menu item to see your Stacks.
-1. Choose your stack created in the earlier steps (for example, `cfn-workshop-drift-detection-challenge`).
-1. From **Stack actions**, choose **Detect Drift**.
-1. Drift detection takes a few moments to complete. Refresh the stack info page until the **Drift status** field shows `Drifted`.
-1. From **Stack actions**, choose **View drift results**.
-1. The drift status page displays, showing that `Instance1` has been modified.
-1. Select `Instance1`, then choose **View drift details**.
-1. The drift details show that the `UserData` property has been modified. The `UserData` property is stored using Base64 encoding, so the exact change you made is not obvious in the display.
-::::
-:::::
-:::alert{type="info"}
-You can use a tool to decode the Base64 text and see the shell script it represents. For example, on Linux you can use the `base64` command line tool to process it as follows. Note that some implementations, for example macOS, use `-D` instead of `-d` as the option to the `base64` command.
-:::
-
-For example, when you run the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-echo "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==" | base64 -d
-:::
-
-you should see the following output:
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-#!/usr/bin/env bash
-echo Hello World
-:::
-
-:::alert{type="warning"}
-Be wary of using third-party websites to encode or decode your base64 text for UserData, especially if it contains or could contain sensitive information.
-:::
-
-Your task now is to update the stack with the new state of the resource, without causing a further interruption.
-
-:::expand{header="Need a hint?"}
-* You should detach the resource from the stack, then re-import it again with the `UserData` corrected. You do not need to convert the `UserData` to Base64.
-* Refer to the [Resource Importing](/intermediate/operations/resource-importing.html) lab for more guidance.
-:::
-::::::expand{header="Want to see the solution?"}
-1. Update the `drift-detection-challenge.yaml` template to add a `DeletionPolicy` attribute with a value of `Retain` to the `Instance1` resource. Save the file.
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=10 highlightLines=12}
-Resources:
- Instance1:
- DeletionPolicy: Retain
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- UserData: !Base64 |
- #!/usr/bin/env bash
- echo Hello World
-:::
-1. Update the stack with the updated `drift-detection-challenge.yaml` template. This tells CloudFormation that when the resource is removed from the template, it should not delete it but just stop managing it.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-drift-detection-challenge \
---template-body file://drift-detection-challenge.yaml
-:::
-1. Once the stack update is complete, edit the template file again to remove the whole resource declaration (you can also choose to comment it out, using the `#` character at the start of each relevant line), and save the file.
-1. Update the stack with the updated template file. CloudFormation will remove the instance from the stack without terminating it.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-drift-detection-challenge \
---template-body file://drift-detection-challenge.yaml
-:::
-1. Edit the template file to restore the resource, and update the UserData to match the change made previously.
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=10 highlightLines=19}
-Resources:
- Instance1:
- DeletionPolicy: Retain
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- UserData: !Base64 |
- #!/usr/bin/env bash
- echo Hello Universe
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Create a text file to describe the resources for an IMPORT operation.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch resources-import.txt
-:::
-1. Copy the code below and replace the `resources-import.txt`. For the [**Identifier Value**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview), specify the instance's **Physical ID**, that you noted earlier as part of this challenge.
-:::code{language=json showLineNumbers=false showCopyAction=true}
-[
- {
- "ResourceType":"AWS::EC2::Instance",
- "LogicalResourceId":"Instance1",
- "ResourceIdentifier": {
- "InstanceId":"i-12345abcd6789"
- }
- }
-]
-:::
-1. Update the `cfn-workshop-drift-detection-challenge` Stack to Import resources by using the following code.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-drift-detection-challenge \
---change-set-name drift-challenge --change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://drift-detection-challenge.yaml
-:::
-1. Execute the change set by using the following code.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation execute-change-set \
---stack-name cfn-workshop-drift-detection-challenge \
---change-set-name drift-challenge
-:::
-1. Wait until the `IMPORT` operation is complete by using the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. Verify the drift detection on the stack `cfn-workshop-drift-detection-challenge`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation detect-stack-drift \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-1. The drift details for `Instance1` are shown in the output of `descibe-stack-resource-drifts` to confirm the instance is now in sync with the stack.
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=11,22}
-{
- "StackResourceDrifts": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Bucket1",
- "PhysicalResourceId": "cfn-workshop-drift-detection-challenge-bucket1-1svpxjottevmx",
- "ResourceType": "AWS::S3::Bucket",
- "ExpectedProperties": "{}",
- "ActualProperties": "{}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T17:29:29.338000+00:00"
- },
- {
- "StackId": "arn:aws:cloudformation:us-east-1:402198065244:stack/cfn-workshop-drift-detection-challenge/30dbaeb0-f965-11ed-a54c-0ea8a8f21e33",
- "LogicalResourceId": "Instance1",
- "PhysicalResourceId": "i-0113f35b272b0f04e",
- "ResourceType": "AWS::EC2::Instance",
- "ExpectedProperties": "{\"ImageId\":\"ami-0d52ddcdf3a885741\",\"InstanceType\":\"t2.micro\",\"UserData\":\"IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==\"}",
- "ActualProperties": "{\"ImageId\":\"ami-0d52ddcdf3a885741\",\"InstanceType\":\"t2.micro\",\"UserData\":\"IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvIEhlbGxvIFdvcmxkCg==\"}",
- "PropertyDifferences": [],
- "StackResourceDriftStatus": "IN_SYNC",
- "Timestamp": "2023-05-23T17:29:30.015000+00:00"
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="Local Development"}
-1. Select the stack in the CloudFormation console, then from **Stack actions** choose **Import resources in to stack**.
-1. Choose **Next**.
-1. Upload the template file.
-1. Enter the physical ID of the instance and choose **Next**.
-1. In **Specify stack options**, choose **Next**.
-1. Choose **Import resources**.
-1. Once the stack operation is complete and the resource is imported, you can run drift detection on the stack to confirm the instance is now in sync with the stack template.
-::::
-:::::
-You can find the template for the solution in `code/solutions/drift-detection/drift-detection-workshop.yaml`.
-
-Well done! You have now learned how to repair drift without impact by deleting and re-importing a resource.
-::::::
-
-### Cleanup
-
-Follow steps shown next to clean up the resources you created in this workshop.
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Delete the S3 bucket by using the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-aws s3 rb s3://drift-detection-challenge-AWS_ACCOUNT_ID --force
-:::
-1. Delete the `cfn-workshoop-drift-detection-workshop` stack.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-drift-detection-workshop
-:::
-1. For the `cfn-workshop-drift-detection-challenge` stack, edit the template file to change the `DeletionPolicy` to `Delete`.
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=10 highlightLines=12}
-Resources:
- Instance1:
- DeletionPolicy: Delete
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- UserData: !Base64 |
- #!/usr/bin/env bash
- echo Hello Universe
-:::
-1. Use the AWS CLI to update the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-drift-detection-challenge \
---template-body file://drift-detection-challenge.yaml
-:::
-1. Once the updating of the stack is complete, go ahead and delete it.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-drift-detection-challenge
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the CloudFormation Console.
-1. Choose the stack created in the first lab, for example `cfn-workshop-drift-detection-workshop`.
-1. Choose **Delete**, then choose the **Delete**.
-1. For the `cfn-workshop-drift-detection-challenge` stack, edit the template file to change the `DeletionPolicy` to `Delete`.
-1. Update the stack by selecting it, then choosing **Upload**, then **Replace current template** and uploading the updated file. Choose **Next**, then choose **Next**, then choose **Next**, and then choose **Submit**. Wait for the stack update to complete.
-1. Select the `cfn-workshop-drift-detection-challenge` stack and choose **Delete**, then choose **Delete**.
-::::
-:::::
-
----
-
-### Conclusion
-
-In this lab, you learned how to detect drift on CloudFormation stacks to find resources which had been modified outside of CloudFormation, and see details of the changes. You learned how to verify a resource had been modified correctly back to match the template, as well as how to update the stack to match a resource’s new desired state. Finally, you learned how to correct drift by deleting and re-importing the affected resource.
diff --git a/content/intermediate/operations/index.ja.md b/content/intermediate/operations/index.ja.md
deleted file mode 100644
index 078a5c607..000000000
--- a/content/intermediate/operations/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "オペレーション"
-weight: 20
----
-
-
diff --git a/content/intermediate/operations/index.md b/content/intermediate/operations/index.md
deleted file mode 100644
index 9e0efe85f..000000000
--- a/content/intermediate/operations/index.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Operations"
-weight: 20
----
-
-
diff --git a/content/intermediate/operations/resource-importing/index.ja.md b/content/intermediate/operations/resource-importing/index.ja.md
deleted file mode 100644
index 58c835eda..000000000
--- a/content/intermediate/operations/resource-importing/index.ja.md
+++ /dev/null
@@ -1,780 +0,0 @@
----
-title: "リソースインポート"
-weight: 400
----
-
-### 概要
-
-[AWS CloudFormation](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/Welcome.html) を使用して、コードで記述したインフラストラクチャをプログラムで管理します。例えば、[AWS マネジメントコンソール](https://aws.amazon.com/jp/console/) や [AWS Command Line Interface](https://aws.amazon.com/jp/cli/) (CLI) を使用して AWS アカウントでリソースを作成した場合は、リソースを CloudFormation スタックに[インポート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html)すると、CloudFormation でリソースのライフサイクルを管理できます。
-
-[スタック間でリソースを移動する](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/refactor-stacks.html) 場合は、インポート機能を使用することもできます。これにより、スタックとリソースを [ライフサイクルと所有権](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/best-practices.html#organizingstacks) 別に整理できます。例えば、[Amazon Elastic Compute Cloud](https://aws.amazon.com/jp/ec2/) (Amazon EC2) セキュリティグループなどのリソースを、セキュリティグループのリソース専用の 1 つのスタック (または複数のスタック) に再編成します。
-
-::alert[インポート操作でサポートされるリソースの詳細については、 [インポートおよびドリフト検出オペレーションをサポートするリソース](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html) をご参照ください。]{type="info"}
-
-### 取り上げるトピック
-
-このラボを修了すると、次のことができるようになります。
-
-* リソースをスタックにインポートする方法を学びます。
-* リソースインポートのさまざまなユースケースに関する重要な考慮事項を学び、実践します。
-
-### ラボを開始
-* `code/workspace/resource-importing` ディレクトリに移動します。
-* `resource-importing.yaml`ファイルを開きます。
-* このラボの手順に従って、テンプレートのコンテンツを更新します。
-
-### ラボパート 1
-
-このラボでは、まず [Amazon SNS コンソール](https://console.aws.amazon.com/sns/) を使用して [Amazon Simple Notification Service](https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html) (Amazon SNS) トピックを作成します。次に、新しい CloudFormation スタックを作成し、SNS トピックをインポートします。さらに、Amazon SNS コンソールで 2 つ目のトピックを作成し、それを既存のスタックにインポートします。
-
-開始するには、次に示す手順に従ってください。
-
-1. [Amazon SNS コンソール](https://console.aws.amazon.com/sns/) に移動し、 **トピック** を選択します。次に、 **トピックの作成** を選択します。
-1. **タイプ** セクションで、`スタンダード`を選択します。
-1. トピックの **名前** (`Topic1` など) を指定します。
-1. 準備ができたら、 **トピックの作成** を選択します。
-1. トピックが正常に作成されたら、`Topic1` の **詳細** セクションの下にある [Amazon リソースネーム (ARN)](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference-arns.html) をメモします。この ARN 値は、このラボの後半で使用します。Amazon SNS トピックの ARN パターンの例は `arn:aws:sns:us-east-1:123456789012:MyTopic` です。
-
-次に、リソースのインポート機能を使用して、新しく作成したトピックを、これから作成する新しいスタックにインポートします。そのためには、CloudFormation テンプレートを使用して、既存のトピックを `AWS::SNS::Topic` [リソース](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sns-topic.html) で次のように記述します。
-
-* `TopicName` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sns-topic.html#aws-resource-sns-topic-properties) には、既存のトピックの名前、つまり `Topic1` を指定します。この値を `Topic1Name` と呼ぶテンプレート[パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) で渡します。次に、このパラメータの値を `Ref` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) で参照します。
-* インポートする各リソースには、`DeletionPolicy` [属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) が記述されている必要があります。トピックにはこの属性を指定し、属性値には `Retain` を指定します。`DeletionPolicy` 属性に `Retain` 値を使用するときは、スタックからリソースを削除するとき、またはスタックを削除するときにリソースを保持するように指定します。
-* 以下のコードをコピーして `resource-importing.yaml` ファイルに追加し、ファイルを保存します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Parameters:
- Topic1Name:
- Type: String
- Default: Topic1
- Description: Name of the first Amazon SNS topic you created with the Amazon SNS console.
-
-Resources:
- SNSTopic1:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: !Ref Topic1Name
-:::
-
-
-::alert[インポート操作を成功させるには、インポートするすべてのリソースのテンプレートの記述に [DeletionPolicy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) 属性が設定されている必要があります。詳しい情報については、[インポートオペレーション中の考慮事項](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-considerations) をご参照ください。]{type="info"}
-
-この次のステップでは、AWS CloudFormation コンソールを使用して、`resource-importing.yaml` テンプレートを使用して [スタックを作成](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import-new-stack.html) します。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. `IMPORT` 操作のためリソースを記述するテキストファイルを作成します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch resources-import.txt
-:::
-1. 次のコードを `resources-import.txt` ファイルにコピーペーストして保存してください。[**識別子の値**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview) には、`Topic1` を作成した後にメモしたトピック ARN の値を指定します。
-:::code{language=json showLineNumbers=false showCopyAction=true}
-[
- {
- "ResourceType":"AWS::SNS::Topic",
- "LogicalResourceId":"SNSTopic1",
- "ResourceIdentifier": {
- "TopicArn":"arn:aws:sns:us-east-1:123456789012:Topic1"
- }
- }
-]
-:::
-1. 次のコマンドを実行してリソースインポートのためのテンプレートから `IMPORT` タイプの変更セットを作成しましょう。テンプレートは `Topic1Name` を入力パラメータとして必要とします。例えばスタック名を `cfn-workshop-resource-importing` とし変更セットを `cfn-workshop-resource-import-change-set` として `Topic1Name` の値を `Topic1` とします。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set \
---change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://resource-importing.yaml \
---parameters ParameterKey=Topic1Name,ParameterValue=Topic1
-:::
-1. 変更セットから正しいリソースがインポートされることを確認します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
-:::
-1. リソースをインポートするために変更セットを実行します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation execute-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
-:::
-1. [wait stack-import-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-import-complete.html) コマンドを使って `IMPORT` 操作が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-resource-importing
-:::
-1. [describe-stacks](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) コマンドを使ってインポートが完了していることを確認します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stacks --stack-name cfn-workshop-resource-importing
-:::
-1. `describe-stacks` コマンドを実行すると、17 行目で示されるように CloudFormation は `"StackStatus": "IMPORT_COMPLETE"` を返却します。
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=17}
-{
- "Stacks": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-importing/43d74040-f44e-11ed-9921-0a4da8431f6d",
- "StackName": "cfn-workshop-resource-importing",
- "ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/cfn-workshop-resource-import-change-set/3f86b48d-a0bf-434b-96de-2ec316a04134",
- "Description": "AWS CloudFormation workshop - Resource Importing.",
- "Parameters": [
- {
- "ParameterKey": "Topic1Name",
- "ParameterValue": "Topic1"
- }
- ],
- "CreationTime": "2023-05-17T01:00:50.284000+00:00",
- "LastUpdatedTime": "2023-05-17T01:05:31.414000+00:00",
- "RollbackConfiguration": {},
- "StackStatus": "IMPORT_COMPLETE",
- "DisableRollback": false,
- "NotificationARNs": [],
- "Tags": [],
- "EnableTerminationProtection": false,
- "DriftInformation": {
- "StackDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. **スタックの作成** から、 **既存のリソースを使用 (リソースをインポート)** を選択します。
-1. **必要なもの** を読み、 **次へ** をクリックします。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** をクリックします。`resource-importing.yaml` テンプレートをアップロードし、 **次へ** をクリックします。
-1. [**識別子の値**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview) には、`Topic1` を作成した後にメモしたトピック ARN の値を指定します。
-1. **スタックの名前** を入力します。例えば、`cfn-workshop-resource-importing` と指定します。`Topic1Name` パラメータ値には必ず `Topic1` を指定します。
-1. 次のページで、 **リソースをインポート** をクリックします。
-
-Amazon SNS トピックがスタックに正常にインポートされると、スタックのステータスに `IMPORT_COMPLETE` と表示されます。
-
-既存のリソースを新しいスタックにインポートする方法の関する詳しい説明は、[AWS CLI を使用した既存のリソースからのスタックの作成](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import-new-stack.html#resource-import-new-stack-cli) をご参照ください。
-::::
-:::::
-
-おめでとうございます! Amazon SNS コンソールで以前に作成したリソースを、新しいスタックにインポートしました。
-
-### ラボパート 2
-
-このラボでは、リソースを既存のスタックにインポートする方法を学びます。開始するには、以下の手順に従ってください。
-
-1. [Amazon SNS コンソール](https://console.aws.amazon.com/sns/) に移動して 2 つ目のトピックを作成します。ラボパート 1 で使用した手順に従い、新しいトピックの名前として **Topic2** を指定します。
-1. トピックが正常に作成されたら、`Topic2` の **詳細** セクションの下にある [Amazon リソースネーム (ARN)](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference-arns.html) をメモします。この情報は、後でこのラボで使用します (ARN パターンの例: `arn:aws:sns:us-east-1:123456789012:MyTopic`)。
-1. 以下の例をコピーして、前のラボで使用した `resource-importing.yaml` テンプレートの `Parameters` セクションに追加します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=17}
-Topic2Name:
- Type: String
- Default: Topic2
- Description: Name of the second Amazon SNS topic you created with the Amazon SNS console.
-:::
-1. 次に、以下の例をコピーして、`resource-importing.yaml` テンプレートの `Resources` セクションに追加します。完了したら、テンプレートファイルを保存します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=29}
-SNSTopic2:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: !Ref Topic2Name
-:::
-1. 先ほど更新した `resource-importing.yaml` テンプレートには、2 つのパラメータ (`Topic1Name` と `Topic2Name`) と 2 つのリソース (`SNSTopic1` と `SNSTopic2`) が含まれるようになりました。新しいトピックを既存のスタックにインポートしましょう!
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. 次のコードを `resources-import.txt` ファイルにコピーペーストして保存してください。[**識別子の値**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview) には、`Topic2` を作成した後にメモしたトピック ARN の値を指定します。
- :::code{language=json showLineNumbers=false showCopyAction=true}
- [
- {
- "ResourceType":"AWS::SNS::Topic",
- "LogicalResourceId":"SNSTopic2",
- "ResourceIdentifier": {
- "TopicArn":"arn:aws:sns:us-east-1:123456789012:Topic2"
- }
- }
-]
- :::
- 1. 次のコマンドを実行してリソースインポートのためのテンプレートから `IMPORT` タイプの変更セットを作成します。パラメータを `Topic1Name` を `Topic1` 、`Topic2Name` を `Topic2` とします。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set \
---change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://resource-importing.yaml \
---parameters ParameterKey=Topic1Name,ParameterValue=Topic1 ParameterKey=Topic2Name,ParameterValue=Topic2
- :::
- 1. 変更セットから正しいリソースがインポートされることを確認します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
- :::
- 1. リソースをインポートするために変更セットを実行します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation execute-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
- :::
- 1. [wait stack-import-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-import-complete.html) コマンドを使って `IMPORT` 操作が完了するまで待ちます。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-resource-importing
- :::
- 1. [describe-stacks](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) コマンドを使ってインポートが完了していることを確認します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stacks --stack-name cfn-workshop-resource-importing
- :::
- 1. `describe-stacks` コマンドを実行すると、21 行目で示されるように CloudFormation は `"StackStatus": "IMPORT_COMPLETE"` を返却します。
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=21}
- {
- "Stacks": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-importing/43d74040-f44e-11ed-9921-0a4da8431f6d",
- "StackName": "cfn-workshop-resource-importing",
- "ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/cfn-workshop-resource-import-change-set/b45266b6-01c9-4c23-99d6-d65731fc575c",
- "Description": "AWS CloudFormation workshop - Resource Importing (uksb-1q9p31idr).",
- "Parameters": [
- {
- "ParameterKey": "Topic2Name",
- "ParameterValue": "Topic2"
- },
- {
- "ParameterKey": "Topic1Name",
- "ParameterValue": "Topic1"
- }
- ],
- "CreationTime": "2023-05-17T01:00:50.284000+00:00",
- "LastUpdatedTime": "2023-05-17T01:35:38.408000+00:00",
- "RollbackConfiguration": {},
- "StackStatus": "IMPORT_COMPLETE",
- "DisableRollback": false,
- "NotificationARNs": [],
- "Tags": [],
- "EnableTerminationProtection": false,
- "DriftInformation": {
- "StackDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
- :::
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
- 1. `cfn-workshop-resource-importing` という名前のスタックを選択し、 **スタックアクション** から **リソースへのスタックのインポート** を選択します。
- 1. **必要なもの** を読み、 **次へ** をクリックします。
- 1. **テンプレートの指定** から、 **テンプレートファイルのアップロード** を選択します。このラボパートで更新した `resource-importing.yaml` テンプレートをアップロードし、 **次へ** をクリックします。
- 1. [**識別子の値**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview) には、`Topic2` を作成した後に書き留めたトピックの ARN 値を指定します。
- 1. パラメータについては、必ず `Topic1Name` に `Topic1` を指定し、`Topic2Name` に `Topic2` を指定します。 **次へ** をクリックします。
- 1. 次のページで、 **リソースをインポート** をクリックします。
-
- Amazon SNS トピックがスタックに正常にインポートされると、スタックのステータス `IMPORT_COMPLETE` と表示されます。
- ::::
- :::::
-
-おめでとうございます! これで、リソースを既存のスタックにインポートする方法がわかりました。 追加の情報については、[AWS CLI を使用した既存のリソースのスタックへのインポート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import-existing-stack.html#resource-import-existing-stack-cli) をご参照ください。
-
-### ラボパート 3
-
-ラボのこの部分では、[スタック間でリソースを移動する](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/refactor-stacks.html) 方法を学びます。`SNSTopic1` リソースを `cfn-workshop-resource-importing` スタックから削除し、新しいリソースにインポートします。`SNSTopic1` の `DeletionPolicy` 属性に `Retain` を指定したので、スタックを更新しても `SNSTopic1` リソースは削除されないことに注意します。さっそく始めましょう。
-
-1. ラボパート 2 で使用した `resource-importing.yaml` テンプレートの **Parameters** セクションから以下のコードを削除します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=12}
-Topic1Name:
- Type: String
- Default: Topic1
- Description: Name of the first Amazon SNS topic you created with the Amazon SNS console.
-:::
-1. `resource-importing.yaml` テンプレートの **Resources** セクションから以下のコードを削除し、テンプレートファイルを保存します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=23}
-SNSTopic1:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: !Ref Topic1Name
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次のコマンドを実行してスタックから `SNSTopic1` リソースを削除するための `UPDATE` タイプの変更セットを作成しましょう。スタック名を `cfn-workshop-resource-importing` とし、変更セット名を `cfn-workshop-resource-import-change-set` とし `Topic2Name` パラメータの値を `Topic2` にします。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set \
---change-set-type UPDATE \
---template-body file://resource-importing.yaml \
---parameters ParameterKey=Topic2Name,ParameterValue=Topic2
-:::
-1. 変更セットから正しいリソースが削除されることを確認してください。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
-:::
-1. リソースをインポートするために変更セットを実行します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation execute-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
-:::
-1. [wait stack-import-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-import-complete.html) コマンドを使って `UPDATE` 操作が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-resource-importing
-:::
-1. [describe-stacks](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) コマンドを使ってインポートが完了していることを確認します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stacks --stack-name cfn-workshop-resource-importing
-:::
-1. `describe-stacks` コマンドを実行すると、17 行目で示されるように CloudFormation は `"StackStatus": "IMPORT_COMPLETE"` を返却します。
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=17}
-{
- "Stacks": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-importing/43d74040-f44e-11ed-9921-0a4da8431f6d",
- "StackName": "cfn-workshop-resource-importing",
- "ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/cfn-workshop-resource-import-change-set/11e65a07-b12b-4430-ba7a-d06edf53d2d5",
- "Description": "AWS CloudFormation workshop - Resource Importing (uksb-1q9p31idr).",
- "Parameters": [
- {
- "ParameterKey": "Topic2Name",
- "ParameterValue": "Topic2"
- }
- ],
- "CreationTime": "2023-05-17T01:00:50.284000+00:00",
- "LastUpdatedTime": "2023-05-17T02:00:46.392000+00:00",
- "RollbackConfiguration": {},
- "StackStatus": "UPDATE_COMPLETE",
- "DisableRollback": false,
- "NotificationARNs": [],
- "Tags": [],
- "EnableTerminationProtection": false,
- "DriftInformation": {
- "StackDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-1. [describe-stack-resources](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stack-resources.html) コマンドを使って更新が完了していることを確認します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources --stack-name cfn-workshop-resource-importing
-:::
-1. `describe-stack-resources` コマンドを実行すると、CloudFormation は `SNSTopic2` リソースの情報のみを返却します。
-:::code{language=json showLineNumbers=true showCopyAction=false}
-{
- "StackResources": [
- {
- "StackName": "cfn-workshop-resource-importing",
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-importing/43d74040-f44e-11ed-9921-0a4da8431f6d",
- "LogicalResourceId": "SNSTopic2",
- "PhysicalResourceId": "arn:aws:sns:us-east-1:123456789012:Topic2a.fifo",
- "ResourceType": "AWS::SNS::Topic",
- "Timestamp": "2023-05-17T01:35:50.535000+00:00",
- "ResourceStatus": "UPDATE_COMPLETE",
- "DriftInformation": {
- "StackResourceDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. `cfn-workshop-resource-importing`という名前のスタックを選択し、 **更新** を選択します。
-1. **既存テンプレートを置き換える** を選択し、`resource-importing.yaml` テンプレートをアップロードします。 **次へ** をクリックします。
-1. パラメータセクションで、`Topic2Name` のパラメータ値を `Topic2` のままにします。 **次へ** をクリックします。
-1. **スタックオプションの設定** ページでデフォルト値のまま、 **次へ** をクリックします。
-1. 次のページで **送信** をクリックします。
-1. スタックからの `SNSTopic1` リソースの削除を確認するには、`cfn-workshop-resource-importing` スタックを選択し、 **リソース** を選択します。表示されるリソースは `SNSTopic2` のみです。
-::::
-:::::
-`SNSTopic1` リソースを新しいスタックにインポートします。
-
-1. `code/workspace/resource-importing` ディレクトリにいることを確認します。
-1. お好みのテキストエディタで `moving-resources.yaml` テンプレートファイルを開きます。
-1. 以下の例を `moving-resources.yaml` テンプレートに追加して保存します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Parameters:
- Topic1Name:
- Type: String
- Default: Topic1
- Description: Name of the first Amazon SNS topic you created with the Amazon SNS console.
-
-Resources:
- SNSTopic1:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: !Ref Topic1Name
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 以下のコードをコピーして `resources-import.txt` ファイルの内容を置き換えてください。
-:::code{language=json showLineNumbers=false showCopyAction=true}
-[
- {
- "ResourceType":"AWS::SNS::Topic",
- "LogicalResourceId":"SNSTopic1",
- "ResourceIdentifier": {
- "TopicArn":"arn:aws:sns:us-east-1:123456789012:Topic1"
- }
- }
-]
-:::
-1. [**識別子の値**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview) には、 **ラボ 1** で `Topic1` を作成した後にメモしたトピック ARN の値を指定します。
-1. 次のコマンドを実行してリソースをインポートするために `IMPORT` タイプの変更セットを作成しましょう。スタック名は `cfn-workshop-moving-resources` とし、変更セット名は `cfn-workshop-moving-resources` として `Topic1Name` パラメータの値を `Topic1` とします。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-moving-resources \
---change-set-name cfn-workshop-moving-resources-change-set \
---change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://moving-resources.yaml \
---parameters ParameterKey=Topic1Name,ParameterValue=Topic1
-:::
-1. 変更セットから正しいリソースがインポートされることを確認してください。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-change-set \
---stack-name cfn-workshop-moving-resources \
---change-set-name cfn-workshop-moving-resources-change-set
-:::
-1. リソースをインポートするために変更セットを実行します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation execute-change-set \
---stack-name cfn-workshop-moving-resources \
---change-set-name cfn-workshop-moving-resources-change-set
-:::
-1. [wait stack-import-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-import-complete.html) コマンドを使って `IMPORT` 操作が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-moving-resources
-:::
-1. [describe-stacks](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) コマンドを使ってインポートが完了していることを確認します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stacks --stack-name cfn-workshop-moving-resources
-:::
-1. `describe-stacks` コマンドを実行すると、17 行目で示されるように CloudFormation は `"StackStatus": "IMPORT_COMPLETE"` を返却します。
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=17}
-{
- "Stacks": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-moving-resources/70f207d0-f459-11ed-9c39-123ae332d1a1",
- "StackName": "cfn-workshop-moving-resources",
- "ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/cfn-workshop-moving-resources-change-set/695b51cd-6d16-49e8-99f7-7b93a932f1fe",
- "Description": "AWS CloudFormation workshop - Resource Importing (uksb-1q9p31idr).",
- "Parameters": [
- {
- "ParameterKey": "Topic1Name",
- "ParameterValue": "Topic1"
- }
- ],
- "CreationTime": "2023-05-17T02:20:50.451000+00:00",
- "LastUpdatedTime": "2023-05-17T02:21:03.424000+00:00",
- "RollbackConfiguration": {},
- "StackStatus": "IMPORT_COMPLETE",
- "DisableRollback": false,
- "NotificationARNs": [],
- "Tags": [],
- "EnableTerminationProtection": false,
- "DriftInformation": {
- "StackDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-1. [describe-stack-resources](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stack-resources.html) コマンドを使って更新が完了していることを確認します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources --stack-name cfn-workshop-moving-resources
-:::
-1. `describe-stack-resources` コマンドを実行すると、CloudFormation は `SNSTopic1` リソースの情報のみを返却します。
-:::code{language=json showLineNumbers=true showCopyAction=false}
-{
- "StackResources": [
- {
- "StackName": "cfn-workshop-moving-resources",
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-moving-resources/70f207d0-f459-11ed-9c39-123ae332d1a1",
- "LogicalResourceId": "SNSTopic1",
- "PhysicalResourceId": "arn:aws:sns:us-east-1:123456789012:Topic1.fifo",
- "ResourceType": "AWS::SNS::Topic",
- "Timestamp": "2023-05-17T02:21:15.205000+00:00",
- "ResourceStatus": "UPDATE_COMPLETE",
- "DriftInformation": {
- "StackResourceDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. **スタックの作成** から、 **既存のリソースを使用 (リソースをインポート)** を選択します。
-1. **概要をインポート** を読み、 **次へ** をクリックします。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルをアップロード** を選択します。`moving-resources.yaml` テンプレートをアップロードし、 **次へ** をクリックします。
-1. [**識別子の値**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview) には、`Topic1` を作成した後にメモしたトピック ARN 値を指定し、**次へ** をクリックします。
-1. **スタック名** を入力します。例えば、`cfn-workshop-moving-resources` と指定します。`Topic1Name` パラメータには必ず `Topic1` を指定します。
-1. 次のページで **リソースをインポート** をクリックします。
-
-Amazon SNS トピックがスタックに正常にインポートされると、スタックのステータスには `IMPORT_COMPLETE` と表示されます。
-::::
-:::::
-
-おめでとうございます! スタック間でリソースを移動する方法を学習しました。
-
-::alert[特定のリソースのインポート操作を元に戻すには、まずテンプレート内のリソースの `DeletionPolicy` を `Retain` に設定し、次にスタックを更新して変更を適用します。次に、テンプレートからリソースを削除し、スタックを再度更新します。その際、スタックからリソースを削除しますが、リソースはそのまま残ります。]{type="info"}
-
-### **リソースをインポートする際のベストプラクティス**
-
-1. 既存のリソースのプロパティを取得するには、関連する AWS サービスの AWS マネジメントコンソールページを使用するか、_Describe_ API 呼び出しを使用してリソースを説明し、リソース定義に含めるプロパティを取得します。例えば、`aws ec2 describe-instances` [CLI コマンド](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html) を使用して、次の例に示すようなインスタンス ID を使用して、インポートする Amazon EC2 インスタンスを記述します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ec2 describe-instances --instance-ids i-1234567890abcdef0
-:::
-
-::alert[予期しない変更を避けるため、テンプレートで定義するリソースプロパティがリソースの実際の設定と一致することを確認してください。]{type="info"}
-
-2. インポートするリソースをテンプレートに記述するときは、リソースに必要なすべてのプロパティを必ず指定します。例えば、[AssumeRolePolicyDocument](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-assumerolepolicydocument) は [AWS::IAM::Role](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html) リソースタイプの必須プロパティです。
-3. リソースのインポートが成功したら、[ドリフト検出](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-drift.html)を実行して、テンプレート内のリソースプロパティがリソースの実際の設定と一致することを確認します。
-
-詳細については、[インポートオペレーション中の考慮事項](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-considerations) を参照してください。
-
-### チャレンジ
-
-この演習では、ラボパート 1、2、3 で得た知識を使用して、提供されたタスクを完了する必要があります。CloudFormation テンプレートのリソースの 1 つである EC2 インスタンスに、人為的ミスの結果として CloudFormation の外部で変更されたプロパティ値が存在する問題を解決する必要があります。この問題のトラブルシューティングと解決を行い、CloudFormation で希望するリソース構成を引き続き維持できるようにします。
-
-EC2 インスタンスと Amazon S3 バケットを定義するサンプルテンプレートから始めましょう。
-
-はじめに、以下の手順に従ってください。
-
-1. `code/workspace/resource-importing` というディレクトリにいることを確認します。
-1. `resource-import-challenge.yaml` ファイルを開きます。
-1. 以下の例を `resource-import-challenge.yaml` テンプレートに追加し、ファイルを保存します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Parameters:
- LatestAmiId:
- Description: Fetching the latest AMI ID for Amazon Linux
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
- InstanceType:
- Description: Select the type of the EC2 instance.
- Type: String
- AllowedValues:
- - t2.nano
- - t2.micro
- - t2.small
-
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: !Ref InstanceType
- Tags:
- - Key: Name
- Value: InstanceImport
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次のコマンドを実行して **スタックの作成** を行いましょう。 **スタック名** は `cfn-workshop-resource-import-challenge` とし `InstanceType` パラメータの値は `t2.nano` とします。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-resource-import-challenge \
---template-body file://resource-import-challenge.yaml \
---parameters ParameterKey=InstanceType,ParameterValue=t2.nano
-:::
-1. 次のコマンドを実行して `CREATE_COMPLETE` になるまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-resource-import-challenge
-:::
-::::
-::::tab{id="LocalDevelopment" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. **スタックの作成** から、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートを指定** セクションで、 **テンプレートファイルのアップロード** を選択します。`resource-import-challenge.yaml` テンプレートをアップロードし、 **次へ** をクリックします。
-1. **スタックの名前** を入力します。例えば、`cfn-workshop-resource-import-challenge` と指定します。`InstanceType` には `t2.nano` を指定します。[**次へ**]をクリックします。
-1. **スタックオプションの設定** ページはデフォルト値のまま、 **次へ** をクリックします。
-1. 次のページで、 **送信** を選択します。
-::::
-:::::
-スタックを作成したら、`cfn-workshop-resource-import-challenge` スタックを選択し、 **リソース** を確認します。`i-12345abcd6789` という形式の `インスタンス`の **物理 ID** をメモしておきましょう。
-
-次に、スタックの管理範囲外でインスタンスタイプを変更して、ヒューマンエラーを再現してみましょう。以下の手順に従って [既存の EBS-backed インスタンスのインスタンスタイプを変更](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-resize.html#change-instance-type-of-ebs-backed-instance) を実行します。
-
-1. [Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/) に移動します。
-1. **インスタンス** セクションを見つけて、`InstanceImport` という名前のインスタンスを選択し、 **インスタンスの状態** 、 **インスタンスを停止** を選択します。
-1. 同じインスタンスで、インスタンスが **停止** 状態になったことを確認したら、 **アクション** 、 **インスタンスの設定** 、 **インスタンスタイプを変更** を選択します。
-1. `t2.micro` を選択し、 **適用** を選択します。
-1. `InstanceImport` インスタンスを再度選択し、 **インスタンスの状態** 、 **インスタンスを開始** を選択します。
-
-
-最初に Amazon EC2 インスタンスをスタックで作成しました。ヒューマンエラーを再現するために、テンプレートの [InstanceType](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-instancetype) プロパティを使用する代わりに、(CloudFormation を使用せずに) インスタンスを更新し、次にスタックを更新しました。
-
-:::alert{type="info"}
-インスタンスタイプを変更すると、インスタンスが停止して再起動するなど、 [一時的な中断を伴う更新](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-some-interrupt) が発生します。インスタンスのサイズ変更の詳細については、[インスタンスタイプを変更する](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-resize.html) をご参照ください。
-:::
-今回のタスクは、スタックを更新するときに `InstanceType` プロパティに追加の変更を加えることなく、スタック内で現在 `t2.nano` に設定されているインスタンスタイプ値を、CloudFormation 以外の方法で設定された新しいインスタンス設定である `t2.micro` と一致させることです。
-
-:::expand{header="ヒントが必要ですか?"}
-ラボパート 3 で学んだ概念の利用を検討します。
-:::
-
-:::::::expand{header= "解決策を確認しますか?"}
-1. `resource-import-challenge.yaml` テンプレートを更新します。`Instance` リソースに、値が `Retain` の `DeletionPolicy` 属性を追加し、ファイルを保存します。
-1. パラメータ値を変更せずに、更新された `resource-import-challenge.yaml` テンプレートを使用してスタックを更新します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-resource-import-challenge \
---template-body file://resource-import-challenge.yaml \
---parameters ParameterKey=InstanceType,ParameterValue=t2.nano
-:::
-
-1. スタックを更新し、インスタンスの `DeletionPolicy` 属性が `Retain` に設定されたら、インスタンスリソース定義と Parameters セクションにある関連パラメータをテンプレートから削除します。今回の例では、書くべきパラメーターが特に存在しないため、`Parameters` セクション自体を削除します。具体的には、`resource-import-challenge.yaml` テンプレートから次の 2 つのコードブロックを削除します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11 highlightLines=11-15,17-23}
-Parameters:
- LatestAmiId:
- Description: Fetching the latest AMI ID for Amazon Linux
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-
- InstanceType:
- Description: Select the type of the EC2 instance.
- Type: String
- AllowedValues:
- - t2.nano
- - t2.micro
- - t2.small
-:::
- :::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=30 highlightLines=31}
- Instance:
- DeletionPolicy: Retain
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: !Ref InstanceType
- Tags:
- - Key: Name
- Value: InstanceImport
- :::
-1. 更新された `resource-import-challenge.yaml` テンプレートファイルを使ってスタックを更新します。テンプレートファイルにはパラメータとインスタンスリソースの定義もありません。この操作によりスタックからインスタンスが取り除かれますが、リソースとしては削除されません。これは以前に `DeletionPolicy` の属性を `Retain` に適用したためです。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-resource-import-challenge \
---template-body file://resource-import-challenge.yaml
-:::
-1. スタックを更新したあと、ステップ 3 で 2 つの削除したコードブロックを `resource-import-challenge.yaml` に追加して保存します。
-1. **スタックにリソースをインポート** しましょう
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. 以下のコードをコピーして `resources-import.txt` にペーストします。[**識別子**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview)の値はこのパートの前に、メモをしたインスンスの **物理 ID** に置き換えます。
- :::code{language=json showLineNumbers=false showCopyAction=true}
- [
- {
- "ResourceType":"AWS::EC2::Instance",
- "LogicalResourceId":"Instance",
- "ResourceIdentifier": {
- "InstanceId":"i-12345abcd6789"
- }
- }
-]
- :::
- 1. 以下のコマンドを実行して **リソースのインポート** のために `cfn-workshop-resource-import-challenge` スタックを更新します。`InstanceType` パラメータは `t2.micro` を指定します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-change-set \
---stack-name cfn-workshop-resource-import-challenge \
---change-set-name import-challenge --change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://resource-import-challenge.yaml \
---parameters ParameterKey=InstanceType,ParameterValue=t2.micro
- :::
- 1. 変更セットを実行します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation execute-change-set \
---stack-name cfn-workshop-resource-import-challenge \
---change-set-name import-challenge
- :::
- 1. AWS CLI の [wait stack-import-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-import-complete.html) コマンドを使って `IMPORT` 操作が完了するまで待ちます。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-resource-import-challenge
- :::
- ::::
- ::::tab{id="LocalDevelopment" label="ローカル開発"}
- 1. `cfn-workshop-resource-import-challenge`という名前のスタックを選択し、 **スタックアクション** から **スタックへのリソースのインポート** を選択します。
- 1. **必要なもの** を読み、 **次へ** を選択してください。
- 1. **テンプレートを指定** から、 **テンプレートファイルのアップロード** を選択します。更新した `resource-import-challenge.yaml` テンプレートをアップロードし、 **次へ** をクリックします。
- 1. [**識別子の値**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview) には、このチャレンジの一部として先ほど書き留めたインスタンスの **物理 ID** を指定し、 **次へ** をクリックします。
- 1. インスタンスタイプパラメータとして `t2.micro` を選択します。ここでは、実際のインスタンスタイプ設定である `t2.micro` と一致しています。
- 1. 次のページで、 **リソースをインポート** をクリックします。
- ::::
- :::::
-
-ソリューションのテンプレートは、`code/solutions/resource-import/resource-import-challenge-solution.yaml` サンプルテンプレートにあります。
-:::::::
-
-以上で、CloudFormation 以外の方法で変更があった場合に CloudFormation スタック構成をリソースの実際の設定と一致させる方法を学習しました。
-
-**リソースインポートのユースケース**
-
-1. 以前に AWS マネジメントコンソールや AWS CLI などを使用して AWS リソース (Amazon S3 バケットなど) を作成していて、CloudFormation を使用してリソースを管理したい。
-1. ライフサイクルと所有権ごとにリソースを 1 つのスタックに再編成して管理しやすくしたい (セキュリティグループのリソースなど)。
-1. 既存のスタックを既存のスタックにネストしたい。詳しい情報については、[既存のスタックのネスト化](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import-nested-stacks.html) をご参照ください。
-1. CloudFormation 以外の方法で更新されたリソースの CloudFormation 設定と一致させたい。
-
-### クリーンアップ
-
-このラボで作成したリソースをクリーンアップするには、次に示すクリーンアップ手順に従ってください。
-
-1. `code/workspace/resource-importing` というディレクトリにいることを確認します。
-1. `resource-importing.yaml` テンプレートファイルを更新して、`SNSTopic2` リソース定義から `deletionPolicy: Retain` 行を削除し、テンプレートを保存します。
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. 次のコマンドを実行して **スタック** を更新します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack \
---stack-name cfn-workshop-resource-importing \
---template-body file://resource-importing.yaml
- :::
- 1. 次のコマンドを実行して `UPDATE` 操作が完了するまで。待ちます。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-resource-importing
- :::
- 1. 次のコマンドを実行してスタックを削除します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation delete-stack \
- --stack-name cfn-workshop-resource-importing
- :::
- 1. スタック `cfn-workshop-moving-resources` に対して上記の手順 (1-3) を繰り返します。これには、`moving-resources.yaml` テンプレートを更新して、`SNSTopic1` リソース定義から `DeletionPolicy: Retain` 行を削除します。スタックを更新し、更新が成功した後にスタックを削除します。スタックを更新するときに、既存のパラメーター値を受け入れることを選択します。
- 1. `resource-import-challenge.yaml` テンプレートを更新して `Instance` リソース定義の `DeletionPolicy: Retain` の行を削除し、スタックを更新します。次のコマンドを実行してスタックを更新しましょう。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack \
---stack-name cfn-workshop-resource-import-challenge \
---template-body file://resource-import-challenge.yaml \
---parameters ParameterKey=InstanceType,ParameterValue=t2.micro
- :::
- 1. `cfn-workshop-resource-import-challenge` に対して上記の手順 (2-3) を繰り返してスタックを削除します。
- ::::
- ::::tab{id="LocalDevelopment" label="ローカル開発"}
- 1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
- 1. `cfn-workshop-resource-importing` という名前のスタックを選択し、 **更新** を選択します。
- 1. **現在テンプレートを置き換える** を選択し、`resource-importing.yaml` テンプレートをアップロードします。 **次へ** をクリックします。
- 1. パラメータセクションで、既存のパラメータ値を受け入れることを選択します。 **次へ** をクリックします。
- 1. **スタックオプションの設定** ページでデフォルトのまま、 **次へ** をクリックします。
- 1. 次のページで **送信** を選択します。
- 1. スタックの更新が完了したら、`cfn-workshop-resource-importing` スタックを選択し、 **削除** を選択します。
- 1. `moving-resources.yaml` テンプレートを更新して `SNSTopic1` リソース定義から `deletionPolicy: Retain` 行を削除し、`cfn-workshop-moving-resources` スタックを更新します。正常に更新されたら、手順 2 ~ 9 を繰り返し、`cfn-workshop-moving-resources` スタックを削除します。スタックの更新時には、既存のパラメータ値をそのままにします。
- 1. `resource-import-challenge.yaml` テンプレートを更新して `Instance` リソース定義から `DeletionPolicy: Retain` 行を削除し、スタックを更新します。正常に更新されたらスタック `cfn-workshop-resource-import-challenge` について上記のステップ (2 ~ 9) を繰り返し、スタック削除します。 スタックの更新時には、既存のパラメータ値をそのままにします。
- ::::
- :::::
-
----
-
-### まとめ
-
-これで、リソースをインポートする方法と、リソースをインポートする際の使用例と考慮事項について学習しました。
diff --git a/content/intermediate/operations/resource-importing/index.md b/content/intermediate/operations/resource-importing/index.md
deleted file mode 100644
index 156fc4e08..000000000
--- a/content/intermediate/operations/resource-importing/index.md
+++ /dev/null
@@ -1,776 +0,0 @@
----
-title: "Resource Importing"
-weight: 400
----
-
-### Overview
-
-You use [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) to programmatically manage your infrastructure you describe with code. If you have created, in your AWS account, a resource with the [AWS Management Console](https://aws.amazon.com/console/) or the [AWS Command Line Interface](https://aws.amazon.com/cli/) (CLI) for example, you can choose to [import](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html) your resource into a CloudFormation stack, so you can manage the resource’s lifecycle with CloudFormation.
-
-You can also use the import functionality if you want to [move your resources between stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/refactor-stacks.html), so you can organize your stacks and resources by [lifecycle and ownership](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html#organizingstacks). For example, you choose to reorganize resources such as [Amazon Elastic Compute Cloud](https://aws.amazon.com/ec2/) (Amazon EC2) security groups into one stack - or stacks - you dedicate to your security group resources.
-
-::alert[For more information on supported resources for import operations, see [Resources that support import and drift detection operations](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html).]{type="info"}
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* Learn how to import a resource into your stack.
-* Learn and practice important considerations for a number of resource import use cases.
-
-### Start Lab
-* Navigate to `code/workspace/resource-importing` directory.
-* Open the `resource-importing.yaml` file.
-* Update the content of the template as you follow along steps on this lab.
-
-### Lab Part 1
-
-In this lab, you will first create an [Amazon Simple Notification Service](https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html) (Amazon SNS) topic with the [Amazon SNS Console](https://console.aws.amazon.com/sns/), and you will then import the topic in a new CloudFormation stack you will create. Next, you will create a second topic with the Amazon SNS Console, and you will import it as well into your existing stack.
-
-To get started, follow steps shown next:
-
-1. Navigate to the [Amazon SNS Console](https://console.aws.amazon.com/sns/), and choose **Topics**. Next, choose **Create topic**.
-2. Choose `Standard` for the topic **Type**.
-3. Specify a **Name** for your topic, such as `Topic1`.
-4. When ready, choose **Create topic**.
-5. When your topic is successfully created, take a note of its [**Amazon Resource Name (ARN)**](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) under the **Details** section for `Topic1`: you will use this ARN value later in this lab. For reference, an example ARN pattern for an Amazon SNS topic is `arn:aws:sns:us-east-1:123456789012:MyTopic`.
-
-Let’s now use the resource import functionality to import your newly created topic into a new stack you will create. For this, you will use a CloudFormation template where you describe your existing topic with the `AWS::SNS::Topic` [resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html) as follows:
-
-* You will specify, for the `TopicName` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html#cfn-sns-topic-topicname), the name of your existing topic, that is `Topic1`. Choose to pass this value with a template [parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html), that you will call `Topic1Name`. You will then reference the value for this parameter with the `Ref` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html).
-* Each resource you import must have a `DeletionPolicy` [attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) described for it: specify this attribute for your topic, and specify `Retain` for the attribute value. When you use a `Retain` value for the `DeletionPolicy` attribute, you indicate to retain the resource when you remove it from the stack, or when you delete the stack.
-* Copy the code below, append it to the `resource-importing.yaml` file, and save the file:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Parameters:
- Topic1Name:
- Type: String
- Default: Topic1
- Description: Name of the first Amazon SNS topic you created with the Amazon SNS console.
-
-Resources:
- SNSTopic1:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: !Ref Topic1Name
-:::
-
-
-::alert[All resources you import must have a [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) attribute set in your template for the import operation to succeed. For more information, see [Considerations during an import operation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-considerations).]{type="info"}
-
-In this next step, you will use the AWS CloudFormation to [create a stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-new-stack.html) using the `resource-importing.yaml` template:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Create a text file to describe the resources for an `IMPORT` operation.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch resources-import.txt
-:::
-1. Copy and Paste the below code to the `resources-import.txt` text file, Save it. For the [**ResourceIdentifier Value**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview), update the value for the topic ARN you noted after you created `Topic1`.
-:::code{language=json showLineNumbers=false showCopyAction=true}
-[
- {
- "ResourceType":"AWS::SNS::Topic",
- "LogicalResourceId":"SNSTopic1",
- "ResourceIdentifier": {
- "TopicArn":"arn:aws:sns:us-east-1:123456789012:Topic1"
- }
- }
-]
-:::
-1. Let's create a change set of type `IMPORT` to import the resources from the template by using the following AWS CLI command. The template requires you to provide a value for `Topic1Name` input parameter. For Example, Specify a name for the stack `cfn-workshop-resource-importing` and for the change set `cfn-workshop-resource-import-change-set` and provide the parameter value for `Topic1Name` to `Topic1`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set \
---change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://resource-importing.yaml \
---parameters ParameterKey=Topic1Name,ParameterValue=Topic1
-:::
-1. Review the change set to make sure the correct resources are imported.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
-:::
-1. Execute the change set to import the resources.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation execute-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
-:::
-1. Wait until the `IMPORT` operation is complete, by using the [wait stack-import-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-import-complete.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-resource-importing
-:::
-1. Verify import complete by using the [describe-stacks](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stacks --stack-name cfn-workshop-resource-importing
-:::
-1. If the `describe-stacks` command was successfully sent, CloudFormation will return the stack information with `"StackStatus": "IMPORT_COMPLETE"` on line 17.
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=17}
-{
- "Stacks": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-importing/43d74040-f44e-11ed-9921-0a4da8431f6d",
- "StackName": "cfn-workshop-resource-importing",
- "ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/cfn-workshop-resource-import-change-set/3f86b48d-a0bf-434b-96de-2ec316a04134",
- "Description": "AWS CloudFormation workshop - Resource Importing.",
- "Parameters": [
- {
- "ParameterKey": "Topic1Name",
- "ParameterValue": "Topic1"
- }
- ],
- "CreationTime": "2023-05-17T01:00:50.284000+00:00",
- "LastUpdatedTime": "2023-05-17T01:05:31.414000+00:00",
- "RollbackConfiguration": {},
- "StackStatus": "IMPORT_COMPLETE",
- "DisableRollback": false,
- "NotificationARNs": [],
- "Tags": [],
- "EnableTerminationProtection": false,
- "DriftInformation": {
- "StackDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From **Create stack**, choose **With existing resources (import resources)**.
-1. Read the **What you'll need** information, and choose **Next**.
-1. From **Specify template**, choose **Upload a template file**. Upload the `resource-importing.yaml` template, and choose **Next**.
-1. For the [**Identifier Value**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview), specify the value for the topic ARN you noted after you created `Topic1`, choose **Next**
-1. Enter a **Stack name**. For example, specify `cfn-workshop-resource-importing`. Make sure you specify `Topic1` for the `Topic1Name` parameter value, and choose **Next**
-1. In the next page, choose **Import resources**.
-
-Your stack status will show `IMPORT_COMPLETE` once your Amazon SNS topic is successfully imported into your stack.
-
-For more information, see also [Import an existing resource into a stack using the AWS CLI](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-existing-stack.html#resource-import-existing-stack-cli).
-::::
-:::::
-
-Congratulations! You imported a resource, that you created earlier with the Amazon SNS Console, into a new stack!
-
-### Lab Part 2
-
-In this lab, you will learn how to import a resource into an existing stack. To get started, follow steps below:
-
-1. Navigate to the [Amazon SNS Console](https://console.aws.amazon.com/sns/) to create a second topic. Follow steps you used on lab part 1, and specify **Topic2** for the name of your new topic.
-1. When your topic is successfully created, take a note of its [**Amazon Resource Name (ARN)**](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) under the **Details** section for `Topic2`; you will use this information later on in this lab (example ARN pattern: `arn:aws:sns:us-east-1:123456789012:MyTopic`).
-1. Copy the example below, and **append it to the `Parameters` section** of the `resource-importing.yaml` template, that you used for the previous lab:
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=17}
-Topic2Name:
- Type: String
- Default: Topic2
- Description: Name of the second Amazon SNS topic you created with the Amazon SNS console.
-:::
-1. Next, copy the example below, and **append it to the `Resources` section** of the `resource-importing.yaml` template. Save the template file when done.
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=29}
-SNSTopic2:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: !Ref Topic2Name
-:::
-1. The `resource-importing.yaml` template you just updated will now include 2 parameters (`Topic1Name` and `Topic2Name`), and 2 resources (`SNSTopic1` and `SNSTopic2`). Let’s import the new topic into the existing stack!
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. Copy the below code and update it to the `resource-import.txt` text file. For the [**ResourceIdentifier Value**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview), update the value for the topic ARN you noted after you created `Topic2`.
- :::code{language=json showLineNumbers=false showCopyAction=true}
- [
- {
- "ResourceType":"AWS::SNS::Topic",
- "LogicalResourceId":"SNSTopic2",
- "ResourceIdentifier": {
- "TopicArn":"arn:aws:sns:us-east-1:123456789012:Topic2"
- }
- }
-]
- :::
- 1. Let's create a change set of type `IMPORT` to import the resources from the template by using the following AWS CLI command. Specify the parameter values for `Topic1Name` to `Topic1` and for `Topic2Name` to `Topic2` as described below.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set \
---change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://resource-importing.yaml \
---parameters ParameterKey=Topic1Name,ParameterValue=Topic1 ParameterKey=Topic2Name,ParameterValue=Topic2
- :::
- 1. Review the change set to make sure the correct resources are imported.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
- :::
- 1. Execute the change set to import the resources.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation execute-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
- :::
- 1. Wait until the `IMPORT` operation is complete, by using the [wait stack-import-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-import-complete.html) AWS CLI command.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-resource-importing
- :::
- 1. Verify import complete by using the [describe-stacks](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) AWS CLI command.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation describe-stacks --stack-name cfn-workshop-resource-importing
- :::
- 1. If the `describe-stacks` command was successfully sent, CloudFormation will return the stack information with `"StackStatus": "IMPORT_COMPLETE"` on line 21.
- :::code{language=json showLineNumbers=true showCopyAction=false highlightLines=21}
- {
- "Stacks": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-importing/43d74040-f44e-11ed-9921-0a4da8431f6d",
- "StackName": "cfn-workshop-resource-importing",
- "ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/cfn-workshop-resource-import-change-set/b45266b6-01c9-4c23-99d6-d65731fc575c",
- "Description": "AWS CloudFormation workshop - Resource Importing (uksb-1q9p31idr).",
- "Parameters": [
- {
- "ParameterKey": "Topic2Name",
- "ParameterValue": "Topic2"
- },
- {
- "ParameterKey": "Topic1Name",
- "ParameterValue": "Topic1"
- }
- ],
- "CreationTime": "2023-05-17T01:00:50.284000+00:00",
- "LastUpdatedTime": "2023-05-17T01:35:38.408000+00:00",
- "RollbackConfiguration": {},
- "StackStatus": "IMPORT_COMPLETE",
- "DisableRollback": false,
- "NotificationARNs": [],
- "Tags": [],
- "EnableTerminationProtection": false,
- "DriftInformation": {
- "StackDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
- :::
- ::::
- ::::tab{id="local" label="Local development"}
- 1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
- 1. Select the stack named `cfn-workshop-resource-importing` and, from **Stack actions**, choose **Import resources into stack**.
- 1. Read the **What you'll need** information and choose **Next**.
- 1. From **Specify template**, choose **Upload a template file**. Upload the `resource-importing.yaml` template you updated with this lab part, and choose **Next**.
- 1. For the [**Identifier Value**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview), specify the topic ARN value you noted after you created `Topic2`, and choose **Next**.
- 1. For parameters, make sure you specify `Topic1` for `Topic1Name`, and `Topic2` for `Topic2Name`. Choose **Next**.
- 1. In the next page, choose **Import resources**.
- Your stack status will show `IMPORT_COMPLETE` once your Amazon SNS topic is successfully imported into your stack.
- ::::
- :::::
-
-Congratulations! You have learned how to import a resource into an existing stack! For more information, see also [Import an existing resource into a stack using the AWS CLI](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-existing-stack.html#resource-import-existing-stack-cli).
-
-### Lab Part 3
-
-In this part of the lab, you will learn how to [move resources between stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/refactor-stacks.html). You will remove the `SNSTopic1` resource from the `cfn-workshop-resource-importing` stack, and you will import it into a new one; note that since you specified `Retain` for the `DeletionPolicy` attribute of `SNSTopic1`, the `SNSTopic1` resource will not be deleted when you will update the stack. Let's get started:
-
-1. Remove the code below from the **Parameters** section of the `resource-importing.yaml` template you used for lab part 2:
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=12}
-Topic1Name:
- Type: String
- Default: Topic1
- Description: Name of the first Amazon SNS topic you created with the Amazon SNS console.
-:::
-2. Remove the code below from the **Resources** section of the `resource-importing.yaml` template, and save the template file.
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=23}
-SNSTopic1:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: !Ref Topic1Name
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Let's create the change set of type `UPDATE` to remove the resource `SNSTopic1` from the stack by using the following AWS CLI command. Provide a name for the stack as `cfn-workshop-resource-importing` and for the change set name use `cfn-workshop-resource-import-change-set`, Specify the parameter values for `Topic2Name` to `Topic2`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set \
---change-set-type UPDATE \
---template-body file://resource-importing.yaml \
---parameters ParameterKey=Topic2Name,ParameterValue=Topic2
-:::
-1. Review the change set to make sure the correct resources are removed.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
-:::
-1. Execute the change set to import the resources.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation execute-change-set \
---stack-name cfn-workshop-resource-importing \
---change-set-name cfn-workshop-resource-import-change-set
-:::
-1. Wait until the `UPDATE` operation is complete, by using the [wait stack-update-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-update-complete.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-resource-importing
-:::
-1. Verify update complete by using the [describe-stacks](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stacks --stack-name cfn-workshop-resource-importing
-:::
-1. If the `describe-stacks` command was successfully sent, CloudFormation will return the stack information with `"StackStatus": "UPDATE_COMPLETE"` on line 17.
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=17}
-{
- "Stacks": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-importing/43d74040-f44e-11ed-9921-0a4da8431f6d",
- "StackName": "cfn-workshop-resource-importing",
- "ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/cfn-workshop-resource-import-change-set/11e65a07-b12b-4430-ba7a-d06edf53d2d5",
- "Description": "AWS CloudFormation workshop - Resource Importing (uksb-1q9p31idr).",
- "Parameters": [
- {
- "ParameterKey": "Topic2Name",
- "ParameterValue": "Topic2"
- }
- ],
- "CreationTime": "2023-05-17T01:00:50.284000+00:00",
- "LastUpdatedTime": "2023-05-17T02:00:46.392000+00:00",
- "RollbackConfiguration": {},
- "StackStatus": "UPDATE_COMPLETE",
- "DisableRollback": false,
- "NotificationARNs": [],
- "Tags": [],
- "EnableTerminationProtection": false,
- "DriftInformation": {
- "StackDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-1. Verify update complete by using the [describe-stack-resources](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stack-resources.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources --stack-name cfn-workshop-resource-importing
-:::
-1. If the `describe-stack-resources` command was successfully sent, CloudFormation will return the stack resource information with only `SNSTopic2`.
-:::code{language=json showLineNumbers=true showCopyAction=false}
-{
- "StackResources": [
- {
- "StackName": "cfn-workshop-resource-importing",
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-importing/43d74040-f44e-11ed-9921-0a4da8431f6d",
- "LogicalResourceId": "SNSTopic2",
- "PhysicalResourceId": "arn:aws:sns:us-east-1:123456789012:Topic2a.fifo",
- "ResourceType": "AWS::SNS::Topic",
- "Timestamp": "2023-05-17T01:35:50.535000+00:00",
- "ResourceStatus": "UPDATE_COMPLETE",
- "DriftInformation": {
- "StackResourceDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Select the stack named `cfn-workshop-resource-importing` and choose **Update**.
-1. Choose **Replace current template** and upload the `resource-importing.yaml` template. Choose **Next**.
-1. In the parameters section, choose to accept the parameter value for `Topic2Name` as `Topic2`. Choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page, and choose **Next**.
-1. Choose **Submit** in the next page.
-1. To confirm the removal of `SNSTopic1` resource from the stack, select the `cfn-workshop-resource-importing` stack and choose **Resources**. You should see only one resource: `SNSTopic2`.
-::::
-:::::
-Choose to import the `SNSTopic1` resource into a new stack:
-1. Make sure you are in the `code/workspace/resource-importing` directory.
-2. Open the `moving-resources.yaml` template file with your favorite text editor.
-3. Append the example below to the `moving-resources.yaml` template, and save it.
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Parameters:
- Topic1Name:
- Type: String
- Default: Topic1
- Description: Name of the first Amazon SNS topic you created with the Amazon SNS console.
-
-Resources:
- SNSTopic1:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: !Ref Topic1Name
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Copy the code below and replace it to the `resources-import.txt` file.
-:::code{language=json showLineNumbers=false showCopyAction=true}
-[
- {
- "ResourceType":"AWS::SNS::Topic",
- "LogicalResourceId":"SNSTopic1",
- "ResourceIdentifier": {
- "TopicArn":"arn:aws:sns:us-east-1:123456789012:Topic1"
- }
- }
-]
-:::
-1. For the [**ResourceIdentifier Value**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview), update the value for the topic ARN you noted after you created `Topic1` from **Lab1**.
-1. Let's create a change set of type `IMPORT` to import the resources from the template by using the following AWS CLI command. Provide `cfn-workshop-moving-resources` as name of the stack and for the change set use `moving-resource-change-set`, Specify `Topic1` as parameter value for `Topic1Name`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-moving-resources \
---change-set-name cfn-workshop-moving-resources-change-set \
---change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://moving-resources.yaml \
---parameters ParameterKey=Topic1Name,ParameterValue=Topic1
-:::
-1. Review the change set to make sure the correct resources are imported.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-change-set \
---stack-name cfn-workshop-moving-resources \
---change-set-name cfn-workshop-moving-resources-change-set
-:::
-1. Execute the change set to import the resources.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation execute-change-set \
---stack-name cfn-workshop-moving-resources \
---change-set-name cfn-workshop-moving-resources-change-set
-:::
-1. Wait until the `IMPORT` operation is complete, by using the [wait stack-import-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-import-complete.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-moving-resources
-:::
-1. Verify import complete by using the [describe-stacks](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stacks --stack-name cfn-workshop-moving-resources
-:::
-1. If the `describe-stacks` command was successfully sent, CloudFormation will return the stack information with `"StackStatus": "IMPORT_COMPLETE"` on line 17.
-:::code{language=json showLineNumbers=true showCopyAction=false highlightLines=17}
-{
- "Stacks": [
- {
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-moving-resources/70f207d0-f459-11ed-9c39-123ae332d1a1",
- "StackName": "cfn-workshop-moving-resources",
- "ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/cfn-workshop-moving-resources-change-set/695b51cd-6d16-49e8-99f7-7b93a932f1fe",
- "Description": "AWS CloudFormation workshop - Resource Importing (uksb-1q9p31idr).",
- "Parameters": [
- {
- "ParameterKey": "Topic1Name",
- "ParameterValue": "Topic1"
- }
- ],
- "CreationTime": "2023-05-17T02:20:50.451000+00:00",
- "LastUpdatedTime": "2023-05-17T02:21:03.424000+00:00",
- "RollbackConfiguration": {},
- "StackStatus": "IMPORT_COMPLETE",
- "DisableRollback": false,
- "NotificationARNs": [],
- "Tags": [],
- "EnableTerminationProtection": false,
- "DriftInformation": {
- "StackDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-1. Verify update complete by using the [describe-stack-resources](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stack-resources.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-resources --stack-name cfn-workshop-moving-resources
-:::
-1. If the `describe-stack-resources` command was successfully sent, CloudFormation will return the stack resource information with `SNSTopic1`.
-:::code{language=json showLineNumbers=true showCopyAction=false}
-{
- "StackResources": [
- {
- "StackName": "cfn-workshop-moving-resources",
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-moving-resources/70f207d0-f459-11ed-9c39-123ae332d1a1",
- "LogicalResourceId": "SNSTopic1",
- "PhysicalResourceId": "arn:aws:sns:us-east-1:123456789012:Topic1.fifo",
- "ResourceType": "AWS::SNS::Topic",
- "Timestamp": "2023-05-17T02:21:15.205000+00:00",
- "ResourceStatus": "UPDATE_COMPLETE",
- "DriftInformation": {
- "StackResourceDriftStatus": "NOT_CHECKED"
- }
- }
- ]
-}
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From **Create stack**, choose **With existing resources (import resources)**.
-1. Read the **Import Overview** and choose **Next**.
-1. From **Specify template**, choose **Upload a template file**. Upload the `moving-resources.yaml` template and choose **Next.**
-1. For the [**Identifier Value**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview), specify the topic ARN value you noted after you created `Topic1`, and choose **Next**
-1. Enter a **Stack name**. For example, specify `cfn-workshop-moving-resources`. Make sure you specify `Topic1` for the `Topic1Name` parameter.
-1. Choose **Import Resources** in the next page.
-
-The stack status will show `IMPORT_COMPLETE` once your Amazon SNS topic is successfully imported into your stack.
-::::
-:::::
-
-Congratulations! You have learned how to move resources between stacks.
-
-::alert[To revert an import operation for a given resource, first set the `DeletionPolicy` to `Retain` for the resource in your template, and then update the stack to apply the change. Next, remove the resource from the template, and update the stack again: in doing so, you will remove the resource from your stack, but you retain the resource.]{type="info"}
-
-### **Best Practices while importing a resource**
-
-1. To fetch the properties of an existing resource, use the AWS Management Console page for the relevant AWS service, or use a _Describe_ API call to describe the resource and fetch properties you want to include in the resource definition. For example, use the `aws ec2 describe-instances` [CLI command](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html) to describe your Amazon EC2 instance you want to import, using the instance ID as shown in the following example:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ec2 describe-instances --instance-ids i-1234567890abcdef0
-:::
-
-::alert[Make sure you verify that resource properties you define in a template match the actual configuration of the resource, to avoid unexpected changes.]{type="info"}
-
-2. When you describe in your template a resource you wish to import, make sure you specify all required properties for your resource. For example, [AssumeRolePolicyDocument](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-assumerolepolicydocument) is a required property for the [AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html) resource type.
-3. Once a resource import is successful, run [Drift Detection](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-drift.html) to verify resource properties in the template match the actual configuration of the resource.
-
-For more information, see [Considerations during an import operation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-considerations).
-
-### Challenge
-
-In this exercise, you will need to use the knowledge gained from lab parts 1, 2, and 3 to complete the provided task. You are tasked with solving the following issue: one of the resources in a CloudFormation template, an EC2 instance, has a property value that was modified outside of CloudFormation as a result of a human error. You will troubleshoot and solve this issue, so that you can continue maintaining your desired resource configuration with CloudFormation.
-
-Let's start with an example template that describes an EC2 instance and an Amazon S3 bucket.
-
-To begin, follow the steps below:
-
-1. Make sure you are in the directory: `code/workspace/resource-importing`.
-2. Open the `resource-import-challenge.yaml` file.
-3. Add the example below to the `resource-import-challenge.yaml` template, and save the file.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Parameters:
- LatestAmiId:
- Description: Fetching the latest AMI ID for Amazon Linux
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
- InstanceType:
- Description: Select the type of the EC2 instance.
- Type: String
- AllowedValues:
- - t2.nano
- - t2.micro
- - t2.small
-
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: !Ref InstanceType
- Tags:
- - Key: Name
- Value: InstanceImport
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Let's **Create Stack** by using the code below. For example, Specify **Stack Name** as `cfn-workshop-resource-import-challenge` and `t2.nano` for `InstanceType` parameter.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-resource-import-challenge \
---template-body file://resource-import-challenge.yaml \
---parameters ParameterKey=InstanceType,ParameterValue=t2.nano
-:::
-1. Wait until the stack status to `CREATE_COMPLETE` by using the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-resource-import-challenge
-:::
-::::
-::::tab{id="LocalDevelopment" label="LocalDevelopment"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From **Create stack**, choose **With new resources (standard)**.
-1. From **Specify template**, choose **Upload a template file**. Upload the `resource-import-challenge.yaml` template and choose **Next**.
-1. Enter a **Stack name**. For example, specify `cfn-workshop-resource-import-challenge`. Specify `t2.nano` for `InstanceType`. Choose **Next**.
-1. In **Configure Stack Options**, choose **Next**.
-1. In the next page, choose **Submit**.
-::::
-:::::
-After the stack is created, select the `cfn-workshop-resource-import-challenge` stack, and choose **Resources**. Take a note of the **Physical ID** for `Instance`, that uses this format: `i-12345abcd6789`.
-
-Let’s now reproduce the human error by changing the instance type outside the management purview of your stack. Choose to [Change the instance type of existing EBS-backed instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-resize.html#change-instance-type-of-ebs-backed-instance) by following the steps below:
-
-1. Navigate to the [Amazon EC2 Console](https://console.aws.amazon.com/ec2/).
-1. Locate the **Instances** section, select the instance with the name `InstanceImport`, and choose **Instance state**, **Stop instance**.
-1. For the same instance, once you see the instance has reached the **Stopped** state, choose **Actions**, **Instance settings**, **Change instance type.**
-1. Choose `t2.micro`, and then choose **Apply**.
-1. Select again the `InstanceImport` instance, and choose **Instance state**, **Start instance**.
-
-You initially created an Amazon EC2 instance with your stack. To reproduce the human error, you updated the instance out of band (not using CloudFormation), instead of using the [instance type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-instancetype) property in your template, and updating your stack next.
-
-:::alert{type="info"}
-When you change the instance type, this causes [some interruptions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-some-interrupt), such as the instance will stop and start again. For more information on resizing instances, see [Change the instance type](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-resize.html).
-:::
-Your task is to reconcile the instance type value, that in your stack is currently set to `t2.nano`, with the new, actual instance configuration setting - `t2.micro` - made out of band, without making additional changes to the `InstanceType` property when you update the stack.
-
-:::expand{header="Need a hint?"}
-Think about a way to use concepts you learned in Lab part 3.
-:::
-
-:::::::expand{header="Want to see the solution?"}
-1. Update the `resource-import-challenge.yaml` template: add a `DeletionPolicy` attribute, with a value of `Retain`, to the `Instance` resource. Save the file.
-1. Update the stack by using the updated `resource-import-challenge.yaml` template without changing parameter values.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-resource-import-challenge \
---template-body file://resource-import-challenge.yaml \
---parameters ParameterKey=InstanceType,ParameterValue=t2.nano
-:::
-1. Once you updated the stack, and the `DeletionPolicy` attribute is set to `Retain` for your instance, remove the instance resource definition and relevant parameters in the `Parameters` section from the template: in this example, remove the `Parameters` section itself, as you do not have any more parameters to describe. To do so, remove the two following code blocks from the `resource-import-challenge.yaml` template:
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11 highlightLines=11-15,17-23}
-Parameters:
- LatestAmiId:
- Description: Fetching the latest AMI ID for Amazon Linux
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-
- InstanceType:
- Description: Select the type of the EC2 instance.
- Type: String
- AllowedValues:
- - t2.nano
- - t2.micro
- - t2.small
-:::
- :::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=30 highlightLines=31}
- Instance:
- DeletionPolicy: Retain
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: !Ref InstanceType
- Tags:
- - Key: Name
- Value: InstanceImport
- :::
-1. Save the template file. Update the stack again with the updated `resource-import-challenge.yaml` template, which now has no parameters section, and no instance resource definition. This action will remove the instance from the stack, but will not delete it because you previously described and applied the `DeletionPolicy` attribute set to `Retain`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-resource-import-challenge \
---template-body file://resource-import-challenge.yaml
-:::
-1. After this stack update, add the two removed code blocks from Step 3 back to the `resource-import-challenge.yaml` template, and save it.
-1. Let's **Import the Resources to the Stack**
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. Copy the code below and replace the `resources-import.txt`. For the [**Identifier Value**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview), specify the instance's **Physical ID**, that you noted earlier as part of this challenge.
- :::code{language=json showLineNumbers=false showCopyAction=true}
- [
- {
- "ResourceType":"AWS::EC2::Instance",
- "LogicalResourceId":"Instance",
- "ResourceIdentifier": {
- "InstanceId":"i-12345abcd6789"
- }
- }
-]
- :::
- 1. Update the `cfn-workshop-resource-import-challenge` Stack to **Import resources** by using the following code. Specify `t2.micro` for the `InstanceType` parameter.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-change-set \
---stack-name cfn-workshop-resource-import-challenge \
---change-set-name import-challenge --change-set-type IMPORT \
---resources-to-import file://resources-import.txt \
---template-body file://resource-import-challenge.yaml \
---parameters ParameterKey=InstanceType,ParameterValue=t2.micro
- :::
- 1. Execute the change set by using the following code
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation execute-change-set \
---stack-name cfn-workshop-resource-import-challenge \
---change-set-name import-challenge
- :::
- 1. Wait until the `IMPORT` operation is complete by using the following AWS CLI command
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-import-complete \
---stack-name cfn-workshop-resource-import-challenge
- :::
- ::::
- ::::tab{id="LocalDevelopment" label="Local development"}
- 1. Select the stack named `cfn-workshop-resource-import-challenge` and, from **Stack actions**, choose **Import resources into stack**.
- 1. Read the **What you'll need** information and choose **Next**.
- 1. From **Specify template**, choose **Upload a template file**. Upload your updated `resource-import-challenge.yaml` template, and choose **Next**.
- 1. For the [**Identifier Value**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import.html#resource-import-overview), specify the instance's **Physical ID**, that you noted earlier as part of this challenge, and choose **Next**
- 1. Select `t2.micro` for the instance type parameter: here you are matching the actual instance type configuration setting, that is `t2.micro`, and choose **Next**
- 1. In the next page, choose **Import resources**.
- ::::
- :::::
-
-You can find the template for the solution in the `code/solutions/resource-importing/resource-import-challenge-solution.yaml` example template.
-:::::::
-
-Great work! You have now learned how to match the CloudFormation stack configuration with the actual configuration on the resource when there is an out-of-band change.
-
-**Resource importing use cases**
-
-1. You previously created an AWS resource (for example, an Amazon S3 bucket) with e.g., the AWS Management Console or the AWS CLI, and you would like to manage your resource using CloudFormation.
-2. You want to reorganize resources by lifecycle and ownership into single stacks for easier management (for example, security group resources, etc.).
-3. You want to nest an existing stack within an existing one. For more information, see [Nesting an existing stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-nested-stacks.html).
-4. You want to match the CloudFormation configuration for a resource which was updated out of band.
-
-### Cleanup
-
-Choose to follow cleanup steps shown next to clean up resources you created with this lab:
-
-1. Make sure you are in the directory: `code/workspace/resource-importing`
-2. Update the `resource-importing.yaml` template file to remove the `DeletionPolicy: Retain` line from the `SNSTopic2` resource definition, and save the template.
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. Update the **Stack** by using the following AWS CLI command
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack \
---stack-name cfn-workshop-resource-importing \
---template-body file://resource-importing.yaml
- :::
- 1. Wait until the `UPDATE` operation is complete by using the following AWS CLI command
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-resource-importing
- :::
- 1. Delete the stack by running the following AWS CLI command
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation delete-stack \
- --stack-name cfn-workshop-resource-importing
- :::
- 1. Repeat steps (1-3) above for the stack: `cfn-workshop-moving-resources`, by updating the `moving-resources.yaml` template to remove the `DeletionPolicy: Retain` line from the `SNSTopic1` resource definition, updating the stack, and deleting it after successful update. Choose to accept the existing parameter value when you update the stack.
- 1. Update the `resource-import-challenge.yaml` template to remove the `DeletionPolicy: Retain` line from the `Instance` resource definition. Now update the stack by running the following AWS CLI command
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack \
---stack-name cfn-workshop-resource-import-challenge \
---template-body file://resource-import-challenge.yaml \
---parameters ParameterKey=InstanceType,ParameterValue=t2.micro
- :::
- 1. Repeat steps (2-3) above for stack: `cfn-workshop-resource-import-challenge` to delete the stack.
- ::::
- ::::tab{id="LocalDevelopment" label="Local development"}
- 1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
- 1. Select the stack named `cfn-workshop-resource-importing` and choose **Update**.
- 1. Choose **Replace current template** and **upload a template file**. Upload the `resource-importing.yaml` template. Choose **Next**.
- 1. In the parameters section, choose to accept the existing parameter value. Choose **Next**.
- 1. Choose to accept default values in the **Configure stack options** page, and choose **Next**.
- 1. Choose **Submit** in the next page.
- 1. After your stack update is complete, select the `cfn-workshop-resource-importing` stack and choose **Delete**.
- 1. Repeat steps (2-9) above for the stack: `cfn-workshop-moving-resources`, by updating the `moving-resources.yaml` template to remove the `DeletionPolicy: Retain` line from the `SNSTopic1` resource definition, updating the stack, and deleting it after successful update. Choose to accept the existing parameter value when you update the stack.
- 1. Repeat steps (2-9) above for stack: `cfn-workshop-resource-import-challenge` by updating the `resource-import-challenge.yaml` template to remove the `DeletionPolicy: Retain` line from the `Instance` resource definition, updating the stack, and deleting it after successful update. Choose to accept existing parameter values when you update the stack.
- ::::
- :::::
-
----
-
-### Conclusion
-
-Great job! You have now learned how to import resources, as well as use cases and considerations to make when you import resources.
diff --git a/content/intermediate/operations/stack-policy-and-prevention-controls/index.ja.md b/content/intermediate/operations/stack-policy-and-prevention-controls/index.ja.md
deleted file mode 100644
index ba81339ef..000000000
--- a/content/intermediate/operations/stack-policy-and-prevention-controls/index.ja.md
+++ /dev/null
@@ -1,281 +0,0 @@
----
-title: "スタックポリシーと誤操作防止のためのコントロール"
-weight: 300
----
-
-### 概要
-
-[AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/) を使用してコードでインフラストラクチャを記述する場合、意図しない操作を防ぐためのポリシーを実装できます。例えば、[スタックポリシー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html)、[削除保護](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html)、[DeletionPolicy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) 属性、[UpdateReplacePolicy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html) 属性により、スタックに記述したリソースの偶発的な終了、更新、削除を防ぎます。
-
-### 取り上げるトピック
-
-このラボを修了すると、次のことができるようになります。
-
-* CloudFormation スタックに [スタックポリシー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html) を設定して、スタックで管理しているリソースに対して実行できる更新アクションを設定する方法を学びます。
-* [削除保護](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html) を有効にしてスタックの削除を防ぐ方法を学びます。
-* [DeletionPolicy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) 属性を使用して、スタックからリソースを削除するとき、またはスタックを削除するときに、スタックに記述したリソースを保持 (場合によってはバックアップ) する方法について学びます。
-
-### ラボを開始
-
-* `code/workspace/stack-policy-and-prevention-controls` ディレクトリに移動します。
-* `stack-policy-lab.yaml` ファイルを開きます。
-* このラボの手順に従って、テンプレートのコンテンツを更新します。
-
-### **ラボパート 1 - スタックポリシーと削除保護**
-
-[スタックポリシー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html) は、スタックリソースの更新操作を定義および制御するためにスタック上にセットアップする JSON 形式のドキュメントです。[削除保護](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html) は、スタックが削除されないようにするためにスタック上で有効にするスタックオプションです。
-
-このラボでは、まず [Amazon Simple Notification Service](https://aws.amazon.com/jp/sns/) (Amazon SNS) [トピック](https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-create-topic.html) をスタック内に作成します。トピックの更新を拒否するスタックポリシーを設定し、スタックの削除保護を有効にします。次に、作成したスタックを更新してトピックを更新し、スタックリソースに設定したスタックポリシーをテストします。後ほど、スタックを削除して、有効にした削除保護設定をテストします。
-
-開始するには、次の手順に沿って進んでください。
-
-* 以下のコードをコピーして `stack-policy-lab.yaml` ファイルに追加し、ファイルを保存します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Parameters:
- SNSTopicTagValue:
- Description: Tag value for your Amazon SNS topic
- Type: String
- Default: Topic-Tag-1
- MinLength: 1
- MaxLength: 256
-
-Resources:
- SNSTopic:
- Type: AWS::SNS::Topic
- Properties:
- TopicName: Topic-1
- Tags:
- - Key: TagSNS
- Value: !Ref SNSTopicTagValue
-:::
-
-
-この次のステップでは、`stack-policy-lab.yaml` テンプレートファイルを使用してスタックを作成します。次の手順に沿って進んでください。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-次の手順でスタックを作成します。
-1. **Code Editor のターミナル** で `code/workspace/stack-policy-and-prevention-controls` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/stack-policy-and-prevention-controls
-:::
-1. スタックポリシーを記述するため新しい JSON ファイルを作成します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch policy-body.json
-:::
-1. Code Editorでこのファイルを開き、次の JSON をペーストします。
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "Statement" : [
- {
- "Effect" : "Deny",
- "Principal" : "*",
- "Action" : "Update:Modify",
- "Resource" : "LogicalResourceId/SNSTopic"
- },
- {
- "Effect" : "Allow",
- "Principal" : "*",
- "Action" : "Update:*",
- "Resource" : "*"
- }
- ]
-}
-:::
-1. テンプレートは入力パラメータとして `SNSTopicTagValue` を必要とします。例えば `Topic-Tag-1` と入力します。
-1. 次のコマンドを実行してスタックを作成しましょう。(ここでは例として `us-east-1` リージョンを利用します。必要に応じてリージョンを変更してください。):
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---region us-east-1 \
---stack-name cfn-workshop-stack-policy \
---template-body file://stack-policy-lab.yaml \
---stack-policy-body file://policy-body.json \
---parameters ParameterKey=SNSTopicTagValue,ParameterValue=Topic-Tag-1 \
---enable-termination-protection
-:::
-1. CloudFormation は次の結果を返却します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-stack-policy/330b0120-1771-11e4-af37-50ba1b98bea6"
-:::
-1. `cfn-workshop-stack-policy` が作成されるまで、CloudFormation コンソールで待機するか AWS CLI の [stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) コマンドを使って待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-stack-policy
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. **スタックの作成** から、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルをアップロード** を選択します。`stack-policy-lab.yaml` テンプレートをアップロードし、 **次へ** をクリックします。
-1. スタック名を入力します。例えば、`cfn-workshop-stack-policy` と入力します。パラメータセクションで、`SnStopicTagValue` のパラメータ値を `Topic-Tag-1` とします。 **次へ** をクリックします。
-1. **スタックオプションの設定** ページの **スタックポリシー** セクションで、 **スタックポリシーを入力する** を選択し、スタックポリシーに次のコードを貼り付けます。 **スタック作成オプション** で、 **削除保護** を **有効** とし、 **次へ** をクリックします。
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "Statement" : [
- {
- "Effect" : "Deny",
- "Principal" : "*",
- "Action" : "Update:Modify",
- "Resource" : "LogicalResourceId/SNSTopic"
- },
- {
- "Effect" : "Allow",
- "Principal" : "*",
- "Action" : "Update:*",
- "Resource" : "*"
- }
- ]
-}
-:::
-1. 次のページで、 **送信** をクリックします。
-::::
-:::::
-
-::alert[スタックポリシーをスタックに適用すると、そのスタック内のすべてのリソースがデフォルトで保護されます。従って、他のすべてのリソースを更新できるようにするには、スタックポリシーに明示的な `Allow` ステートメントを指定する必要があります。]
-
-上記で `cfn-workshop-stack-policy` スタックに設定したスタックポリシーは、[論理 ID](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html#resources-section-structure-resource-fields) が `SNSTopic` であるリソースの更新を拒否します。
-
-それでは、作成したスタックを更新して、適用したスタックポリシーをテストしてみましょう。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-次のコマンドを使って `SNSTopicTagValue` の値を `Topic-Tag-1` から `Topic-Tag-2` に更新します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-stack-policy \
---use-previous-template \
---parameters ParameterKey=SNSTopicTagValue,ParameterValue=Topic-Tag-2
-:::
-CloudFormation は次の結果を返却します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-stack-policy/330b0120-1771-11e4-af37-50ba1b98bea6"
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. `cfn-workshop-stack-policy` という名前のスタックを選択し、 **更新** を選択します。
-1. 次のページで、 **現在のテンプレートの使用** を選択します。 **次へ** をクリックします。
-1. パラメーターセクションで、`SNSTopicTagValue` の値を `Topic-Tag-1` から `Topic-Tag-2` に更新します。 **次へ** をクリックします。
-1. **スタックオプションの設定** ページでデフォルト値のまま、 **次へ** をクリックします。
-1. 次のページで **送信** をクリックします。
-::::
-:::::
-
-スタックの更新は失敗します。[AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)でスタックの **イベント** ペインを見ると、[論理 ID](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html#resources-section-structure-resource-fields) が `SNSTopic` であるリソースの `Action denied by stack policy` というエラーが表示されます。
-
-それでは、`cfn-workshop-stack-policy` スタックで有効にした削除保護機能をテストしてみましょう。
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. `cfn-workshop-stack-policy` という名前のスタックを選択し、 **削除** を選択します。
-
-スタックで **削除保護** が有効になっていることを知らせるメッセージウィンドウが表示されます。スタックを削除する前に無効にする必要があります。 **キャンセル** を選択してください。
-
-おめでとうございます! これで、CloudFormation スタック内のリソースの更新操作を定義し、スタックが削除されないようにする方法を学習しました。
-
-
-### **ラボパート 2 - DeletionPolicy**
-
-[DeletionPolicy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) は、スタックからリソースを削除する場合やスタック自体を削除する場合に、スタック内のリソースを保持 (場合によってはバックアップ) するように設定する CloudFormation リソース属性です。デフォルトでは、リソースに `DeletionPolicy` が設定されていない場合、またはその値が `Delete` に設定されている場合、CloudFormation はスタックの削除時にリソースを削除します。
-
-このラボでは、まず Amazon SNS トピックリソースを含む CloudFormation スタックを作成し、`DeletionPolicy` 属性値を `Retain` に設定してリソースを保存します。次に、スタックを削除し、リソースがまだ存在するかどうかを確認します。
-
-開始するには、次の手順に沿って進んでください。
-
-* `code/workspace/stack-policy-and-prevention-controls` ディレクトリにいることを確認します。
-* 以下のコードをコピーして `deletion-policy-lab.yaml` ファイルに追加し、ファイルを保存します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Resources:
- SNSTopic:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: Topic-2
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-**スタックの作成** を行うためにターミナルで次のコマンドを実行します
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-stack-policy-deletion \
---template-body file://deletion-policy-lab.yaml
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. **スタックの作成** から、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルをアップロード** を選択します。`deletion-policy-lab.yaml` テンプレートをアップロードし、 **次へ** をクリックします。
-1. スタック名を入力します。例えば、`deletion-policy-lab` と入力します。 **次へ** をクリックします。
-1. **スタックオプションの設定ページ** でデフォルト値のまま、ページの一番下までスクロールして **次へ** をクリックします。
-1. 次のページで、 **送信** をクリックします。
-::::
-:::::
-
-`DeletionPolicy` 属性に `Retain` 値を使用するときは、スタックからリソースを削除するとき、またはスタックを削除するときにリソースを保持するように指定します。
-
-スタックが作成されたら、リソースに設定した `DeletionPolicy` をテストしてみましょう。
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. `cfn-workshop-deletion-policy` という名前のスタックを選択し、 **削除** を選択します。次に、 **削除** を選択して確定します。
-
-スタックイベントペインで、論理 ID が `SNSTopic` のリソースが削除をスキップしたことがわかります。リソースが保持されていることを確認するには、以下の手順に従います。
-
-1. [Amazon SNS コンソール](https://console.aws.amazon.com/sns/) に移動し、 **トピック** を選択します。
-1. スタックで作成したトピック `Topic-2` がまだ存在していることから、スタックの削除中に削除されなかったことが分かります。
-
-おめでとうございます! これで、リソースに `DeletionPolicy` リソース属性を定義して、スタックの削除時にそのリソースを保持する方法を学習しました。詳しい情報については、[`DeletionPolicy` 属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) と [`DeletionPolicy` オプション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html#aws-attribute-deletionpolicy-options)をご参照ください。
-
-::alert[スタックの更新時に、`UpdateReplacePolicy` [属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html) を使用して、スタックの更新中にリソースが置き換えられた際、特定のリソースを保持するか、バックアップするかを選択できます。]
-
-### チャレンジ
-
-これで、[論理 ID](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html#resources-section-structure-resource-fields) に基づいてリソースの更新を拒否するスタックポリシーを作成する方法がわかりました。この演習では、特定のタイプのリソースに適用されるスタックポリシーを作成します。タスクは、`AWS::RDS::DBInstance` リソースタイプへのすべての更新アクションを拒否するスタックポリシーを作成することです。
-
-:::expand{header= "ヒントが必要ですか?"}
-- [Condition](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html#stack-policy-reference) キーを使用して `ResourceType` を定義します。
-- すべての更新アクションを含めるには、 `Action` をどのように指定しますか?
-- `Resource` にはどの値を指定すべきですか?
-:::
-
-::::expand{header= "解決策を確認しますか?"}
-`"Effect" : "Deny"` に対して、次に示すように `Action`、`Resource`、`Condition` ブロックを含むスタックポリシーを作成します。
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "Statement" : [
- {
- "Effect" : "Deny",
- "Principal" : "*",
- "Action" : "Update:*",
- "Resource" : "*",
- "Condition" : {
- "StringEquals" : {
- "ResourceType" : ["AWS::RDS::DBInstance"]
- }
- }
- },
- {
- "Effect" : "Allow",
- "Principal" : "*",
- "Action" : "Update:*",
- "Resource" : "*"
- }
- ]
-}
-:::
-::::
-
-これで、特定のリソースタイプの更新を拒否するスタックポリシーを作成する方法がわかりました。
-
-### クリーンアップ
-次に示す手順に従って、このラボで作成したリソースをクリーンアップしてください。
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. `cfn-workshop-stack-policy` という名前のスタックを選択し、 **削除** を選択します。
-1. メッセージウィンドウで、 **削除保護を編集する** を選択し、 **削除保護** を **無効** とします。 **保存する** をクリックします。
-1. `cfn-workshop-stack-policy` という名前のスタックを選択し、 **削除** を選択し、 **削除** を選択して確定します。
-1. [Amazon SNS コンソール](https://console.aws.amazon.com/sns/) に移動し、 **トピック** を選択します。次に、トピック `Topic-2` を選択し、 **削除** を選択します。メッセージペインに `これを削除` と入力し、 **削除** を選択して確定します。
-
-___
-
-### まとめ
-おめでとうございます! これで、意図しない更新を防ぎ、スタックが削除されないように保護し、意図せずにスタックが削除された場合にリソースを保存する方法を学習しました。
diff --git a/content/intermediate/operations/stack-policy-and-prevention-controls/index.md b/content/intermediate/operations/stack-policy-and-prevention-controls/index.md
deleted file mode 100644
index 7de5b6e48..000000000
--- a/content/intermediate/operations/stack-policy-and-prevention-controls/index.md
+++ /dev/null
@@ -1,278 +0,0 @@
----
-title: "Stack policy and prevention controls"
-weight: 300
----
-
-### Overview
-
-When you describe your infrastructure with code using [AWS CloudFormation](https://aws.amazon.com/cloudformation/), you have the choice of implementing policies to prevent unintentional operations. For example, you can choose to use CloudFormation features that include [Stack Policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html), [Termination Protection](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html), [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html), and [UpdateReplacePolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html) to prevent accidental stack terminations, updates and deletions of resources you describe in your stack.
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* Learn how to set a [Stack Policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html) on a CloudFormation stack to determine which update actions you can perform on resources you manage with your stack.
-* Learn how to prevent stack deletion by enabling [Termination Protection](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html).
-* Learn how to use the [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) attribute to retain - or backup, in some cases - resources that you describe in your stack when you remove resources from the stack, or when you delete the stack.
-
-### Start Lab
-
-* Change directory to `code/workspace/stack-policy-and-prevention-controls`.
-* Open the `stack-policy-lab.yaml` file.
-* Update the content of the template as you follow along steps on this lab.
-
-### **Lab Part 1 - Stack Policy and Termination Protection**
-
-[Stack policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html) is a JSON-formatted document you set up on a stack to define and control update operations for your stack resources. [Termination Protection](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html) is a stack option that you enable on the stack to protect your stack from deletion.
-
-In this lab, you will first create an [Amazon Simple Notification Service](https://aws.amazon.com/sns/) (Amazon SNS) [topic](https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html) in a stack: you will set up a stack policy to deny updates to the topic, and enable termination protection for your stack. Next, you will update the stack you created to update the topic, and test the stack policy you configured for the stack resource. Later, you will delete the stack to test the termination protection setting you enabled.
-
-To get started, follow steps shown next:
-
-* Copy the code below, append it to the `stack-policy-lab.yaml` file, and save the file:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Parameters:
- SNSTopicTagValue:
- Description: Tag value for your Amazon SNS topic
- Type: String
- Default: Topic-Tag-1
- MinLength: 1
- MaxLength: 256
-
-Resources:
- SNSTopic:
- Type: AWS::SNS::Topic
- Properties:
- TopicName: Topic-1
- Tags:
- - Key: TagSNS
- Value: !Ref SNSTopicTagValue
-:::
-
-In this next step, you will use the AWS CloudFormation to create a stack using the `stack-policy-lab.yaml` template file. Follow steps shown next:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-Create a stack by following these steps:
-1. In the **Code Editor terminal** navigate to `code/workspace/stack-policy-and-prevention-controls`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/stack-policy-and-prevention-controls
-:::
-1. Create a new JSON file for the stack policy.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-touch policy-body.json
-:::
-1. Open this file in Code Editor and paste in the following JSON code:
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "Statement" : [
- {
- "Effect" : "Deny",
- "Principal" : "*",
- "Action" : "Update:Modify",
- "Resource" : "LogicalResourceId/SNSTopic"
- },
- {
- "Effect" : "Allow",
- "Principal" : "*",
- "Action" : "Update:*",
- "Resource" : "*"
- }
- ]
-}
-:::
-1. The template requires you to provide a value for the `SNSTopicTagValue` input parameter. For example use `Topic-Tag-1`
-1. Let's create the stack from the template using the following command (the example uses `us-east-1` for the AWS region, change this value as needed):
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---region us-east-1 \
---stack-name cfn-workshop-stack-policy \
---template-body file://stack-policy-lab.yaml \
---stack-policy-body file://policy-body.json \
---parameters ParameterKey=SNSTopicTagValue,ParameterValue=Topic-Tag-1 \
---enable-termination-protection
-:::
-1. CloudFormation returns the following output:
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-stack-policy/330b0120-1771-11e4-af37-50ba1b98bea6"
-:::
-1. Wait until the `cfn-workshop-stack-policy` stack is created, by using the CloudFormation console or the [stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) wait command of the AWS CLI
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-stack-policy
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From **Create stack**, choose **With new resources (standard)**.
-1. From **Specify template**, choose **Upload a template file**. Upload the `stack-policy-lab.yaml` template, and choose **Next**.
-1. Enter a Stack name. For example, specify `cfn-workshop-stack-policy`. In the parameters section, choose to accept the parameter value for `SNSTopicTagValue` as `Topic-Tag-1`. Choose **Next**.
-1. In **Configure Stack Options** page; under **Stack policy**, choose **Enter stack policy** and paste the following code for the stack policy. Under **Stack creation options**, choose **Activated** for **Termination protection**, and choose **Next**.
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "Statement" : [
- {
- "Effect" : "Deny",
- "Principal" : "*",
- "Action" : "Update:Modify",
- "Resource" : "LogicalResourceId/SNSTopic"
- },
- {
- "Effect" : "Allow",
- "Principal" : "*",
- "Action" : "Update:*",
- "Resource" : "*"
- }
- ]
-}
-:::
-1. In the next page, choose **Submit**.
-::::
-:::::
-
-::alert[When you apply a stack policy to a stack, all the resources in that stack are protected by default. Hence, you will need to specify an explicit `Allow` statement in your stack policy to allow updates to all other resources.]
-
-The stack policy you configured above for your `cfn-workshop-stack-policy` stack denies updates to the resource whose [Logical ID](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html#resources-section-structure-resource-fields) is `SNSTopic`.
-
-Let’s now test the stack policy you applied, by updating the stack you created!
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-Run the following command in the terminal to update the value of `SNSTopicTagValue` from `Topic-Tag-1` to `Topic-Tag-2`
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-stack-policy \
---use-previous-template \
---parameters ParameterKey=SNSTopicTagValue,ParameterValue=Topic-Tag-2
-:::
-CloudFormation returns the following output:
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-stack-policy/330b0120-1771-11e4-af37-50ba1b98bea6"
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Select the stack named `cfn-workshop-stack-policy`, and choose **Update**.
-1. In the next page, choose to accept **Use current template**. Choose **Next**.
-1. In the parameters section, update the value of `SNSTopicTagValue` from `Topic-Tag-1` to `Topic-Tag-2`. Choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page, and choose **Next**.
-1. Choose **Submit** on the next page.
-::::
-:::::
-
-The stack update will fail. When looking in the **Events** pane for your stack in [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/), you will see the `Action denied by stack policy` error, for the resource whose [Logical ID](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html#resources-section-structure-resource-fields) is `SNSTopic`.
-
-Let’s now test the termination protection feature, that you enabled on your `cfn-workshop-stack-policy` stack:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Select the stack named `cfn-workshop-stack-policy`, and choose **Delete**.
-
-You will observe a message window informing you that **Termination protection** is enabled on the stack, and you will need to disable it before deleting the stack. Choose **Cancel**.
-
-Congratulations! You have now learned how to define update operations for resources in a CloudFormation stack, and prevent the stack from deletion.
-
-### **Lab Part 2 - DeletionPolicy**
-
-[DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) is a CloudFormation resource attribute you configure for resources in your stack to preserve - or backup, in some cases - such resources when you e.g., remove the resource from the stack, or when you delete the stack. By default, CloudFormation will delete the resource on stack deletion if no `DeletionPolicy` is configured for the resource, or if its value is set to `Delete`.
-
-In this lab, you will first create a CloudFormation stack with an Amazon SNS topic resource, and set the `DeletionPolicy` attribute value to `Retain` to preserve the resource. You will then delete the stack, and check if the resource still exists.
-
-To get started, follow steps shown next:
-
-* Make sure you are in the `code/workspace/stack-policy-and-prevention-controls` directory.
-* Copy the code below, append it to the `deletion-policy-lab.yaml` file, and save the file:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=11}
-Resources:
- SNSTopic:
- DeletionPolicy: Retain
- Type: AWS::SNS::Topic
- Properties:
- TopicName: Topic-2
-:::
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-Run the following command in the terminal to **Create Stack**:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-stack-policy-deletion \
---template-body file://deletion-policy-lab.yaml
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From **Create stack**, choose **With new resources (standard)**.
-1. From **Specify template**, choose **Upload a template file**. Upload the `deletion-policy-lab.yaml` template, and choose **Next**.
-1. Enter a Stack name. For example, specify `cfn-workshop-stack-policy-deletion`. Choose **Next**.
-1. Choose to accept default values on the **Configure stack options page**; scroll to the bottom of the page, and choose **Next**.
-1. In the next page, choose **Submit**.
-::::
-:::::
-When you use a `Retain` value for the `DeletionPolicy` attribute, you indicate to retain the resource when you remove it from the stack, or when you delete the stack.
-
-After the stack is created, let’s now test the `DeletionPolicy` you set on the resource:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-2. Select the stack named `cfn-workshop-deletion-policy`, and choose **Delete**. Next, choose **Delete** to confirm.
-
-In the stack events pane, you will observe the resource whose Logical ID is `SNSTopic` skipped the deletion. To confirm the resource was retained, follow the steps below:
-
-1. Navigate to the [Amazon SNS Console](https://console.aws.amazon.com/sns/), and choose **Topics**.
-2. You will observe the topic `Topic-2` you created in the stack is still present, and was not deleted during stack deletion.
-
-Congratulations! You have now learned how to define a `DeletionPolicy` resource attribute on a resource to preserve it during stack deletion. For more information, see [`DeletionPolicy` attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) and [`DeletionPolicy` options](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html#aws-attribute-deletionpolicy-options).
-
-::alert[On stack updates, you can choose to use the `UpdateReplacePolicy` [attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html) to retain - or, in some cases, backup - a given resource when the resource is replaced during the stack update.]
-
-### Challenge
-
-You have learned how to create a stack policy to deny updates to a resource based on a [Logical Resource ID](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html#resources-section-structure-resource-fields). In this exercise, you are tasked with creating a stack policy that applies to resources of a specific type: your task is to create a stack policy to deny all update actions to the `AWS::RDS::DBInstance` resource type.
-
-:::expand{header="Need a hint?"}
-- Make use of the [Condition](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html#stack-policy-reference) key to define `ResourceType`.
-- How do you specify, in `Action`, your intent of including all update actions?
-- Which value should you specify for `Resource`?
-:::
-
-::::expand{header="Want to see the solution?"}
-Create a stack policy that, for `"Effect" : "Deny"`, contains `Action`, `Resource`, and `Condition` blocks specified as shown next:
-:::code{language=json showLineNumbers=false showCopyAction=true}
-{
- "Statement" : [
- {
- "Effect" : "Deny",
- "Principal" : "*",
- "Action" : "Update:*",
- "Resource" : "*",
- "Condition" : {
- "StringEquals" : {
- "ResourceType" : ["AWS::RDS::DBInstance"]
- }
- }
- },
- {
- "Effect" : "Allow",
- "Principal" : "*",
- "Action" : "Update:*",
- "Resource" : "*"
- }
- ]
-}
-:::
-::::
-
-Great work! You have now learned how to create a stack policy to deny updates for a given resource type.
-
-### Cleanup
-Choose to follow steps shown next to clean up resources you created with this lab:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-2. Select the stack named `cfn-workshop-stack-policy` and choose **Delete**.
-3. In the message window, select **Edit termination protection**, and select **Deactivated** for **Termination protection**. Choose **Save**.
-4. Select the stack named `cfn-workshop-stack-policy` and choose **Delete**, and then choose **Delete** to confirm.
-5. Navigate to the [Amazon SNS Console](https://console.aws.amazon.com/sns/), and choose **Topics**. Next, select the topic `Topic-2`, and choose **Delete**. In the message pane, enter `delete me`, and choose **Delete** to confirm.
-
-___
-
-### Conclusion
-Congratulations! You have learned how to prevent unintentional updates, protect a stack from deletion, and preserve resources in case of an unintentional stack deletion.
diff --git a/content/intermediate/operations/stacksets/index.ja.md b/content/intermediate/operations/stacksets/index.ja.md
deleted file mode 100644
index dbfed421f..000000000
--- a/content/intermediate/operations/stacksets/index.ja.md
+++ /dev/null
@@ -1,326 +0,0 @@
----
-title: "スタックセットによるオーケストレーション"
-weight: 700
----
-
-_ラボ実施時間 : 45分程度_
-
----
-
-### 概要
-
-[AWS CloudFormation StackSets](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/what-is-cfnstacksets.html) を使用して、同じインフラストラクチャを複数の AWS [リージョン](https://aws.amazon.com/jp/about-aws/global-infrastructure/regions_az/)または複数の AWS アカウントにデプロイできます。CloudFormation StackSets を使用すると、1 回の操作で複数のアカウントや AWS リージョンにまたがるスタックを作成、更新、削除できます。管理アカウントから CloudFormation テンプレートを定義および管理し、そのテンプレートを基にして任意のターゲットアカウントまたはリージョンにスタックをプロビジョニングできます。[出力値のエクスポートとインポート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html)によってスタックセットの間でパラメータを共有したり、スタックセットに依存関係を設定したりすることもできます。
-
-StackSets を使用して複数の AWS アカウントやリージョンにデプロイすることもできますが、このラボでは、1 つのアカウントを使用して複数のリージョンにデプロイする方法を学習することに重点を置きます。最終的な状態のアーキテクチャ図を以下に示します。
-
-
-
-### 取り上げるトピック
-
-このラボを修了すると、次のことができるようになります。
-
-* CloudFormation StackSets を活用して、1 つのアカウントでリソースをプロビジョニングし、1 回の操作で複数のリージョンにまたがってリソースをプロビジョニングします。
-* スタックセットのインスタンスから出力パラメータをエクスポートし、別のスタックセットのインスタンスにインポートする方法を理解します。
-
-### ラボを開始
-
-#### 事前準備
-
-AWS CloudFormation StackSets が複数の AWS アカウントにスタックをデプロイしたり、複数の AWS リージョンにスタックをデプロイしたりするには、特定の権限が必要です。StackSets の操作を実行するには管理ロールが必要で、ターゲットアカウントに実際のスタックをデプロイするには実行ロールが必要です。これらのロールには特定の命名規則が必要です。管理者ロールには**AWSCloudFormationStackSetAdministrationRole**、実行ロールには**AWSCloudFormationStackSetExecutionRole** となります。これらのロールがないと、StackSets の実行は失敗します。
-
-::alert[クロスアカウントデプロイでは、スタックセットを作成するアカウント(管理アカウント)に**AWSCloudFormationStackSetAdministrationRole** を作成する必要があることに注意してください。**AWSCloudFormationStackSetExecutionRole** は、スタックをデプロイしたい各ターゲットアカウントで作成する必要があります。CloudFormation スタックセットの[セルフマネージド型のアクセス許可を付与する](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stacksets-prereqs-self-managed.html) で詳細をご覧ください。アカウントが AWS Organizations を使用して管理されている場合は、[信頼できるアクセスを有効にする](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stacksets-orgs-activate-trusted-access.html)を実行すると、CloudFormation が全てのアカウントに必要なロールのプロビジョニングを行います。]{type="info"}
-
-このラボを開始するには、CloudFormation を使用して管理者ロールと実行者ロールを作成します。
-
-1. 管理者ロール CloudFormation テンプレートをダウンロードします: https://s3.amazonaws.com/cloudformation-stackset-sample-templates-us-east-1/AWSCloudFormationStackSetAdministrationRole.yml
-2. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation) に移動し、**米国東部 (バージニア北部)** リージョンにいることを確認します。
-3. **スタックの作成** を選択し、**新しいリソースを使用 (標準)** を選択します。
-4. **テンプレートを作成** 設定は以下のように設定します。
- 1. **テンプレートソース** では、**テンプレートファイルをアップロード** を選択します。
- 2. **ファイルを選択**を選択し、ダウンロードした CloudFormation テンプレート (*AWSCloudFormationStackSetAdministrationRole.yml*)を指定します。**次へ** を選択します。
-5. **スタック名** には、`StackSetAdministratorRole` を使用してください。**次へ** を選択します。
-6. **スタックオプションの設定** では、キーとバリューのペアであるタグを設定できます。タグは、スタックとスタックによって作成されるリソースを識別するのに役立ちます。例えば、左側の列にタグキーである *Owner* を入力し、右側の列にタグ値である電子メールアドレスを入力します。ページの他の設定はデフォルト値をそのまま使用します。**次へ** を選択します。
-7. **レビュー** でページの内容を確認します。ページの下部で、**AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。** にチェックを入れます。
-8. **送信** を選択します。
-
-スタックの作成の **ステータス** が `CREATE_COMPLETE` になるまで待ってください。
-
-StackSets の管理者ロールを作成しました。次に実行ロールを作成します。
-
-1. 実行ロール CloudFormation テンプレートをダウンロードします: https://s3.amazonaws.com/cloudformation-stackset-sample-templates-us-east-1/AWSCloudFormationStackSetExecutionRole.yml
-2. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)で、**スタックの作成** を選択し、**新しいリソースを使用 (標準)** を選択します。
-3. **テンプレートを作成** 設定は、以下のように設定します。
- 1. **テンプレートソース** では、**テンプレートファイルをアップロード** を選択します。
- 2. **ファイルを選択** を選択し、ダウンロードした CloudFormation テンプレート (*AWSCloudFormationStackSetExecutionRole.yml*) を指定します。**次へ** を選択します。
-4. **スタックの詳細を指定** ページで、**スタック名** には `StackSetExecutionRole` を使用してください。
-5. **パラメータ** に、このラボで使用している AWS アカウントの 12 桁のアカウント ID を入力します。**次へ** を選択します。
-6. **スタックオプションの設定** では、前述のようにタグを設定することができます。例えば、タグキーには *Owner* と入力し、タグ値にはメールアドレスを入力します。ページの他の設定はデフォルト値をそのまま使用します。**次へ** を選択します。
-7. **レビュー** で、ページの内容を確認します。ページの下部で、**AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。** を選択します。
-8. **送信** を選択します。
-
-スタックの作成の **ステータス** が `CREATE_COMPLETE` になるまで待ってください。
-
-必要な権限を作成したので、ラボのパート 1 に進みます。
-
-#### ラボパート 1
-
-このラボのパート 1 では、サンプルの CloudFormation テンプレート `example_network.yaml` を使用して、StackSets 機能で同じアカウントの 2 つのリージョンにスタックを作成します。このラボのパート 2 では、別のサンプル CloudFormation テンプレート `example_securitygroup.yaml` を使用して、前のスタックセットで作成したネットワークごとにセキュリティグループを作成します。`example_network.yaml` で記述するリソースのアーキテクチャ図を以下に示します。
-
-
-
-開始するには、以下の手順に従ってく進んでださい。
-
-1. `code/workspace/stacksets` ディレクトリに移動します。
-2. お好みのテキストエディターで `example_network.yaml` CloudFormation テンプレートを開きます。
-3. テンプレート内のサンプルリソースの設定を確認しておいてください。この例では以下のことを意図しています。
- 1. [Amazon Virtual Private Cloud](https://aws.amazon.com/jp/vpc/)、インターネットゲートウェイ、2 つのパブリックサブネット、ルートテーブル、およびインターネットへの 2 つのルートを作成します。CloudFormation StackSets で 1 回の作成オペレーションで、これらのリソースを複数のリージョンにデプロイできるようにします。
- 2. VPC ID とサブネット ID を[エクスポート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html)に出力します。エクスポートはリージョンによって異なります。
-
-前述のネットワークリソースを含む `example_network.yaml` テンプレートを使用して、同じアカウントの 2 つのリージョン(`us-east-1` と `us-west-2`) にテンプレートをデプロイします。
-
-次のステップでは、AWS CloudFormation コンソールを使用して `example_network.yaml` テンプレートからスタックセットを作成します。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次の AWS CLI コマンドを使用して、**Create StackSet** をしてみましょう。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-set \
---stack-set-name cfn-workshop-network \
---template-body file://example_network.yaml
-:::
-1. 次の AWS CLI コマンドを使用して、スタックセットにスタックインスタンスを作成します。このコマンドでは、このラボで使用するアカウントの 12 桁の AWS アカウント ID を指定する必要があります。AWS アカウント ID は、画面の右上の ユーザ/ロール ドロップダウンメニューを選択すると確認できます。リージョンには、米国東部 (バージニア北部) と米国西部 (オレゴン) の両方にデプロイすることを選択します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-instances \
---stack-set-name cfn-workshop-network \
---accounts 123456789012 \
---regions us-east-1 us-west-2
-:::
-1. CloudFormation は次の出力を返却します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"OperationId": "d7995c31-83c2-xmpl-a3d4-e9ca2811563f"
-:::
-1. スタックインスタンスが正常に作成されたことを確認します。ステップ 3 の出力の一部として返された `operation-id` を使用して `DescribeStackSetOperation` を実行します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-set-operation \
---stack-set-name cfn-workshop-network \
---operation-id operation_ID
-:::
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。ページの左側にあるパネルから、**StackSets** タブを選択します。
-1. `cfn-workshop-network` を選択すると、**スタックインスタンス** の下に 2 つのスタックがデプロイされているはずです。1 つは `us-east-1` にあり、もう 1 つは `us-west-2` にあります。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. ページの左側のパネルから、**StackSets** タブを選択します。**StackSet の作成** を選択します。
-1. **アクセス許可** セクションで、**IAM 管理ロール ARN** の値は空白のままにし、**IAM 実行ロール名** を**AWSCloudFormationStackSetExecutionRole** に設定します。
-1. **前提条件 - テンプレートの準備** セクションから、**テンプレートの準備完了** を選択します。
-1. **テンプレートを指定** セクションで、**テンプレートソース** で **テンプレートファイルのアップロード** を選択します。**ファイル名の選択** を選択し、前述の CloudFormation テンプレート `example_network.yaml` を指定して、**次へ** を選択します。
-1. **StackSet の詳細を指定** ページで、名前、説明、設定パラメータを指定します。
- 1. **StackSet 名** を指定します。例えば、`cfn-workshop-network` を入力します。
- 1. **StackSet の説明**を入力します。例えば、`Provisions VPC, internet gateway, two public subnets, and two routes to the Internet` を入力します。
- 1. **パラメータ** はデフォルト値をそのまま使用してください。**次へ** を選択します。
-1. **StackSet オプションの設定** では、**実行設定** はそのままにします。**次へ** を選択します。
-1. **デプロイオプションの設定** ページの **スタックセットにスタックを追加** セクションで、**新しいスタックのデプロイ** を選択します。
-1. **アカウント** で、**スタックをアカウントにデプロイ** を選択します。
-1. **アカウント番号** テキストボックスに、このラボで使用しているアカウントの 12 桁のアカウント ID を入力します。この値は、画面の右上にある ユーザ/ロール ドロップダウンメニューを選択すると確認できます。
-
-1. **リージョンの指定** では、**米国東部 (バージニア北部)** と **米国西部 (オレゴン)** にデプロイすることを選択します。
-1. **デプロイオプション** はデフォルト値をそのまま使用し、**次へ** を選択します。
-1. **レビュー** ページで、ページの内容を確認し、**送信** を選択します。
-1. **CREATE** ステータスが `SUCCEEDED` になるまで StackSet 作成ページを更新します。
-
-1. **スタックインスタンス** タブで、2 つのスタックがデプロイされているはずです。1 つは `us-east-1` にあり、もう 1 つは `us-west-2` にあります。
-
-::::
-:::::
-左のパネルで **エクスポート** を選択します。`AWS-CloudFormationWorkshop-SubnetId1`、`AWS-CloudFormationWorkshop-SubnetId2`、`AWS-CloudFormationWOrkshop-VPCID` という名前の 3 つのエクスポートが表示されるはずです。これらのエクスポートは、スタックセットをデプロイした各リージョン (`us-east-1` と `us-west-2`) で作成されます。
-
-
-
-おめでとうございます! 1 回のオペレーションでインフラストラクチャを複数のリージョンにデプロイできました。
-
-#### ラボパート 2
-
-ラボのこのパートでは、新しい CloudFormation テンプレート `example_securitygroup.yaml` を使用して、特定のリージョンで以前作成した VPC に関連付けるセキュリティグループを記述します。また、**セキュリティグループ ID** の出力をエクスポートして、このワークショップラボの *チャレンジ* の部分で後で使用できるようにします。`example_securitygroup.yaml` テンプレートで記述するセキュリティグループリソースを表現したアーキテクチャ図を以下に示します。
-
-
-
-それでは、始めましょう。
-
-1. `code/workspace/stacksets` ディレクトリに移動します。
-2. `example_securitygroup.yaml` テンプレートをお好みのテキストエディタで開きます。
-3. テンプレート内のサンプルセキュリティグループの設定を確認してください。この例では、以下のことを意図しています。
- 1. CloudFormation StackSets を使用して 1 回の作成操作で、2 つのリージョンのそれぞれで先に作成した VPC にセキュリティグループを作成します。VPC ID は `Fn::ImportValue` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) を使用して参照します。
- 2. `SecurityGroupID` の出力をエクスポートします。エクスポートはリージョンによって異なります。
-
-次のステップでは、AWS CloudFormation コンソールを使用して `example_securitygroup.yaml` テンプレートからスタックセットを作成します。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次の AWS CLI コマンドを使用して、**Create StackSet** を実行しましょう。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-set \
---stack-set-name cfn-workshop-security \
---template-body file://example_securitygroup.yaml
-:::
-1. 次の AWS CLI コマンドを使用して、スタックセットにスタックインスタンスを作成します。このコマンドでは、ラボで使用するアカウントの 12 桁の AWS アカウント ID を指定する必要があります。この値は、画面の右上にある ユーザー/ロール ドロップダウンメニューを選択すると確認できます。リージョンの場合には、米国東部 (バージニア北部) と米国西部 (オレゴン) の両方にデプロイすることを選択します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-instances \
---stack-set-name cfn-workshop-security \
---accounts 123456789012 \
---regions us-east-1 us-west-2
-:::
-1. CloudFormation は次の出力を返却します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"OperationId": "d7995c31-83c2-xmpl-a3d4-e9ca2811563f"
-:::
-1. スタックインスタンスが正常に作成されたことを確認します。ステップ 3 の出力の一部として返却された `operation-id` を使用して `DescribeStackSetOperation` を実行します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-set-operation \
---stack-set-name cfn-workshop-security \
---operation-id operation_ID
-:::
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。左側のパネルから、**StackSets** を選択します。
-2. `cfn-workshop-security` を選択すると、**スタックインスタンス** の下に 2 つのスタックがデプロイされているはずです。1 つは `us-east-1` にあり、もう 1 つは `us-west-2` にあります。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. ページの左側のパネルから、**StackSets** タブを選択します。**StackSet の作成** を選択します。
-1. **アクセス許可** セクションで、**IAM 管理ロール ARN** 配下には、ドロップダウンから **IAM ロール名** を選択し、隣のドロップダウンから **AWSCloudFormationStackSetAdministrationRole** を選択します。**IAM 実行ロール名** を **AWSCloudFormationStackSetExecutionRole** に設定します。
-1. **前提条件 - テンプレートの準備** セクションから、**テンプレートの準備完了** を選択します。
-1. **テンプレートを指定** セクションで、**テンプレートソース** で **テンプレートファイルのアップロード** を選択します。**ファイル名の選択** を選択し、前述の CloudFormation テンプレート `example_securitygroup.yaml `を指定して、**次へ** を選択します。
-1. **StackSet の詳細を指定** ページで、名前、説明、設定パラメータを指定します。
- 1. **StackSet 名**を指定します。例えば、`cfn-workshop-security`を選択します。
- 1. **StackSet の説明**を入力します。例えば、`Provisions a security group, and associates it to the existing VPC` を入力します。
- 1. **パラメータ** はデフォルト値をそのまま使用してください。**次へ** を選択します。
-1. **StackSet オプションの設定** では、**実行設定** はそのままにします。**次へ** を選択します。
-1. **デプロイオプションの設定** ページの **スタックセットにスタックを追加** セクションで、**新しいスタックのデプロイ** を選択します。
-1. **アカウント** で、**アカウントにスタックをデプロイ** オプションを選択します。
-1. **アカウント番号** テキストボックスに、このラボで使用しているアカウントの 12 桁の AWS アカウント ID を入力します。
-1. **リージョンの指定** では、**米国東部 (バージニア北部)** と **米国西部 (オレゴン)** にデプロイすることを選択します。
-1. **デプロイオプション** はデフォルト値をそのまま使用します。**同時アカウントの最大数** は **1** で、**障害耐性** は **0** で、**リージョンの同時実行** を **順次** であることを確認してください。**次へ** を選択します。
-1. **レビュー** ページで、内容を確認し、**送信** を選択します。
-1. **CREATE** ステータスが `SUCCEEDED` になるまで StackSet 作成ページを更新します。
-1. **スタックインスタンス** タブで、2 つのスタックがデプロイされているはずです。1 つは `us-east-1` にあり、もう 1 つは `us-west-2` にあります。
-::::
-:::::
-
-左のパネルで **エクスポート** に移動します。「AWS-CloudFormationWorkshop-SecurityGroupId」という名前の新しいエクスポートが表示されるはずです。
-
-
-
-おめでとうございます!スタックセットインスタンスから出力値をエクスポートし、別のスタックセットインスタンスにインポートする方法を学びました。
-
-### チャレンジ
-
-この演習では、ラボの前半で得た知識を使用します。あなたのタスクは、既存の VPC に [Amazon Elastic Compute Cloud (Amazon EC2)](https://docs.aws.amazon.com/ja_jp/ec2/) インスタンスをプロビジョニングする新しい `cfn-workshop-ec2instance` スタックセットを作成し、先ほど作成したセキュリティグループをアタッチすることです。また、このラボのパート 1 でエクスポートした `SubnetId1` の値をインポートするように `example_ec2instance.yaml` テンプレートを更新することも課題です。スタックセットを作成する時は、StackSets オペレーションを **並行** にデプロイするようにしてください。このチャレンジで定義する EC2 インスタンスを表すアーキテクチャ図を以下に示します。
-
-
-
-::::expand{header="ヒントが必要ですか?"}
-* `code/workspace/stacksets` ディレクトリに移動していることを確認してください。
-* お好みのテキストエディターで `example_ec2instance.yaml` CloudFormation テンプレートを開きます。
-
-:::alert{type="info"}
-[Amazon Machine Image (AMI)](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/AMIs.html) リソースはリージョンごとに異なります。リージョン固有の AMI ID を使用するには、テンプレートの `Parameter` セクションにある次のコードスニペットを使用して、特定のリージョンの最新の AMI ID を取得します。また、テンプレートの **Resources** セクションで `ImageId` で `LatestAmId` を参照します。
-:::
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-LatestAmiId:
- Description: The ID of the region-specific Amazon Machine Image to use.
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-:::
-* テンプレートの `Resources` セクションを編集して、第 1 回でエクスポートした `SubnetId1` の値をインポートします。VPC ID をインポートしたのと同じ方法で、`example_network.yaml` から `example_securitygroup.yaml` に任意のパラメータをインポートできます。
-::::
-
-::::::expand{header="解決策を確認しますか?"}
-ソリューションの全文は `code/solutions/stacksets/example_ec2instance.yaml` テンプレートにあります。
-
-EC2 インスタンスのプロパティにこのコードを追加します: `SubnetId: !ImportValue AWS-CloudFormationWorkshop-SubnetId1`
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. ディレクトリを `cfn101-workshop/code/solutions/stacksets` に変更します。
-2. 更新したテンプレートを使用し、次の AWS CLI コマンドを使用して新しい **StackSet** を作成します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-set \
---stack-set-name cfn-workshop-ec2instance \
---template-body file://example_ec2instance.yaml
-:::
-1. 次の AWS CLI コマンドを使用して、スタックセットにスタックインスタンスを作成します。StackSet のオペレーションを並行してデプロイするには、`--operation-preferences` の `RegionConcurrencyType` を **PARALLEL** に指定します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-instances \
---stack-set-name cfn-workshop-ec2instance \
---accounts 123456789012 \
---regions us-east-1 us-west-2 \
---operation-preferences RegionConcurrencyType=PARALLEL
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-更新したテンプレートを使用して、新しい `cfn-workshop-ec2instance` スタックセットを作成して、先に選択した 2 つのリージョンに EC2 インスタンスリソースをデプロイします。StackSets のオペレーションを並行してデプロイするには、**リージョンの同時実行** を **並行** に設定します。これにより、StackSets のオペレーションを両方のリージョンに並行してデプロイできるため、時間を節約できます。
-::::
-:::::
-::::::
-
-### クリーンアップ
-
-最後に、作成したリソースを削除します。スタックセットを削除するには、まずスタックインスタンスを削除し、次に空のスタックセットを削除します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. AWS CLI からスタックセットを削除する前に、**StackSet** のスタックインスタンスを削除してください。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack-instances \
---stack-set-name cfn-workshop-ec2instance \
---accounts 123456789012 \
---regions us-east-1 us-west-2 \
---no-retain-stacks
-:::
-1. `DELETE-STACK-INSTANCE` 操作が完了するのを待ってから、次のコマンドを実行して **StackSet** を削除します
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack-set \
---stack-set-name cfn-workshop-ec2instance
-:::
-1. 他の 2 つのスタックセットについては、`cfn-workshop-security` と `cfn-workshop-network` の順序で、ステップ 1 〜 2 を実行します。
-1. 次の AWS CLI コマンドを実行して、このラボで作成した IAM ロールを削除します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-set-name StackSetAdministratorRole
-:::
-1. ステップ 4 を繰り返して、実行ロールスタック `StackSetAdministratorRole` を **削除** します。
-::::
-::::tab{id="local" label="ローカル開発"}
-
-**スタックセット内の AWS CloudFormation スタックを削除する方法**
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-2. 削除したいスタックから CloudFormation スタックセットを選択します。最後に作成したスタックセット、つまり `cfn-workshop-ec2instance` を選択します。
-3. ページの右上のセクションから**アクション**を選択し、**StackSet からスタックを削除**を選択します。
-4. **アカウント**で、**デプロイロケーション**で**アカウントにスタックをデプロイ**を選択します。
-5. **アカウント番号**に、このラボで使用しているアカウントの 12 桁の AWS アカウント IDを入力します。
-6. **リージョンを指定**では、**全てのリージョンを追加**を選択します。これにより、StackSet がデプロイされた AWS リージョンが自動的に選択されます。 **次へ**を選択します。
-7. **レビュー**ページで、ページの内容を確認し、**送信**を選択します。
-8. **ステータス**が `Pending`に変わります。
-9. **ステータス**が `SUCCEEDED` になるまで更新します。
-10. 他の 2 つのスタックセットについては、`cfn-workshop-security` と `cfn-workshop-network` の順番で、ステップ 2 〜 8 を実行します。
-
-各 StackSet 内のスタックを削除したので、次は空の StackSet を削除することを選択します。
-
-**AWS CloudFormation スタックセットを削除する方法**
-
-1. [AWS CloudFormation StackSets コンソール](https://console.aws.amazon.com/cloudformation/home#/stacksets) に移動します。
-2. 削除するスタックセットを選択します。
-3. **アクション** を選択し、**StackSet の削除** を選択します。
-4. 表示されるポップアップで、**削除** を選択して、このスタックセットの削除を確定します。
-5. 画面を更新すると、StackSet は表示されなくなります。
-6. 他の 2 つのスタックセットについては、ステップ 2 〜 5 を実行します。
-
-**AWS CloudFormation スタックを削除する方法**
-
-1. [AWS CloudFormation スタック コンソール](https://console.aws.amazon.com/cloudformation/home#/stacksets) に移動します。
-2. スタック `StackSetAdministratorRole` を選択し、**削除** を選択します。
-3. 示されるポップアップで、**削除** を選択してこのスタックの削除を確定します。
-4. 画面を更新すると、スタック `StackSetAdministratorRole` は表示されなくなります。
-5. このラボで作成したもう 1 つの `StackSetExecutionRole` スタックに対しても、ステップ 2 ~ 4 を実行します。
-::::
-:::::
-
-### まとめ
-
-CloudFormation StackSets を使用して 1 回のオペレーションで複数の AWS リージョンにテンプレートをデプロイする方法と、あるスタックセットのスタックインスタンスから出力パラメータをエクスポートして別のスタックセットのスタックインスタンスにインポートする方法を学びました。
diff --git a/content/intermediate/operations/stacksets/index.md b/content/intermediate/operations/stacksets/index.md
deleted file mode 100644
index 3afc0ea1c..000000000
--- a/content/intermediate/operations/stacksets/index.md
+++ /dev/null
@@ -1,326 +0,0 @@
----
-title: "Orchestrating with StackSets"
-weight: 700
----
-
-_Lab Duration: ~45 minutes_
-
----
-
-### Overview
-
-You can deploy the same infrastructure in multiple AWS [Regions](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) and/or multiple AWS accounts using [AWS CloudFormation StackSets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/what-is-cfnstacksets.html). With CloudFormation StackSets, you can create, update, or delete stacks across multiple accounts and AWS regions with a single operation. From an administrator account, you can define and manage a CloudFormation template, and use the template as a basis for provisioning stacks into target accounts or regions of your choice. You can also share parameters between stack sets by [exporting and importing output values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html), and establish dependencies in your stack sets.
-
-Although you can use StackSets to deploy across multiple AWS accounts and regions, in this lab you will focus on learning how to deploy across regions using one account. An architecture diagram of the target state is shown next:
-
-
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* Leverage CloudFormation StackSets to provision resources in one account and across multiple regions using a single operation.
-* Understand how you can export output parameters from a stack set instance, and import them into another stack set instance.
-
-### Start Lab
-
-#### Prerequisites
-
-Specific permissions are required by AWS CloudFormation StackSets to deploy stacks in multiple AWS accounts - and across multiple AWS Regions. You will need an administrator role to perform StackSets operations, and an execution role to deploy the actual stacks in target account(s). These roles require specific naming conventions: **AWSCloudFormationStackSetAdministrationRole** for the administrator role, and **AWSCloudFormationStackSetExecutionRole** for the execution role. StackSets execution will fail if these roles are missing.
-
-::alert[Note that, on cross-account deployments, the **AWSCloudFormationStackSetAdministrationRole** should be created in the account where you are creating the stack set (the Administrator account). The **AWSCloudFormationStackSetExecutionRole** should be created in each target account where you wish to deploy the stack. Learn more about [granting self-managed permissions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-prereqs-self-managed.html) for CloudFormation StackSets. If your accounts are managed using AWS Organizations, you can [enable trusted access](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-enable-trusted-access.html), and CloudFormation will take care of provisioning all the necessary roles across the accounts.]{type="info"}
-
-To get started with this lab, use CloudFormation to create the administrator and execution roles:
-
-1. Download the administrator role CloudFormation template: https://s3.amazonaws.com/cloudformation-stackset-sample-templates-us-east-1/AWSCloudFormationStackSetAdministrationRole.yml
-2. Navigate to the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation), and make sure you are in the **US East (N. Virginia)** region.
-3. Choose **Create Stack**, and select **With new resources**.
-4. Leave the **Prepare template** setting as is.
- 1. For **Template source**, select **Upload a template file**.
- 2. Select **Choose file**, and supply the CloudFormation template you downloaded: *AWSCloudFormationStackSetAdministrationRole.yml*. Choose **Next**.
-5. For **Stack name**, use `StackSetAdministratorRole`. Choose **Next**.
-6. In **Configure stack options** you may choose to configure tags, which are key-value pairs, that can help you identify your stacks and the resources they create. For example, enter *Owner* in the left column which is the tag key, and your email address in the right column which is the tag value. Accept default values for the other settings in the page. Choose **Next**.
-7. Under **Review,** review the contents of the page. At the bottom of the page, select **I acknowledge that AWS CloudFormation might create IAM resources with custom names**.
-8. Choose **Submit**.
-
-Wait until the stack creation completes with a `CREATE_COMPLETE` **Status**.
-
-You created the administrator role for StackSets; next, you will create the execution role.
-
-1. Download the execution role CloudFormation template: https://s3.amazonaws.com/cloudformation-stackset-sample-templates-us-east-1/AWSCloudFormationStackSetExecutionRole.yml
-2. In the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation), select **Create Stack** and choose **With new resources**.
-3. Leave the **Prepare template** setting as is.
- 1. For **Template source**, select **Upload a template file**.
- 2. Select **Choose file**, and supply the CloudFormation template you downloaded: *AWSCloudFormationStackSetExecutionRole.yml*. Choose **Next**.
-4. In the **Specify stack details** page: for **Stack name**, use `StackSetExecutionRole`.
-5. In **Parameters**, enter the 12-digit account ID for the AWS account you are using for this lab. Choose **Next**.
-6. For **Configure stack options** you may choose to configure tags, as mentioned earlier. For example, enter *Owner* for the tag key, and your email address for the tag value. Accept default values for the other settings in the page. Choose **Next**.
-7. Under **Review**, review the contents of the page. At the bottom of the page, select **I acknowledge that AWS CloudFormation might create IAM resources with custom names**.
-8. Select **Submit**.
-
-Wait until the stack creation completes with a `CREATE_COMPLETE` **Status**.
-
-Now that you created necessary permissions, you will proceed with Part 1 of the lab.
-
-#### Part 1
-
-In part 1 of this lab, you'll use an example CloudFormation template, `example_network.yaml`, to create stacks in two Regions of the same account using StackSets. In part 2 of this lab, you'll use another example CloudFormation template, `example_securitygroup.yaml`, and create a security group for each network you created with the previous stack set. The architecture diagram of resources you'll describe with `example_network.yaml` is shown next:
-
-
-
-To get started, follow steps shown next:
-
-1. Navigate to the `code/workspace/stacksets` directory.
-1. Open the `example_network.yaml` CloudFormation template in the text editor of your choice.
-1. Familiarize with the configuration for the example resources in the template. In the example, your intents are to:
- 1. create an [Amazon Virtual Private Cloud](https://aws.amazon.com/vpc/), Internet Gateway, two public subnets, route table, and two routes to the Internet: you will choose to deploy these resources in multiple regions using a single create operation via CloudFormation StackSets;
- 1. [export](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) the VPC ID and Subnet IDs outputs. Exports are region-specific.
-
-You will use the `example_network.yaml` template, that contains the network resources mentioned earlier, to deploy the template in two regions (`us-east-1` and `us-west-2`) of the same account.
-
-In this next step, you will use the AWS CloudFormation Console to create a stack set from the `example_network.yaml` template:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Let's **Create StackSets** by using the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-set \
---stack-set-name cfn-workshop-network \
---template-body file://example_network.yaml
-:::
-1. Create stack instances to your stackset by using the following AWS CLI command. This command requires you specify the 12-digit AWS Account ID for the account you are using for this Lab. You can find this value by choosing the user/role drop-down menu in the top-right corner.For regions, choose to deploy in US East (N. Virginia) and US West (Oregon).
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-instances \
---stack-set-name cfn-workshop-network \
---accounts 123456789012 \
---regions us-east-1 us-west-2
-:::
-1. CloudFormation returns the following output.
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"OperationId": "d7995c31-83c2-xmpl-a3d4-e9ca2811563f"
-:::
-1. Verify that the stack instances were created successfully. Run `DescribeStackSetOperation` with the `operation-id` that is returned as part of the output of step 3.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-set-operation \
---stack-set-name cfn-workshop-network \
---operation-id operation_ID
-:::
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/). From the panel on the left of the page, select the **StackSets** tab.
-1. Select `cfn-workshop-network`,Under **Stack instances**, you should see two stacks deployed. One in `us-east-1` and another in `us-west-2`
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From the panel on the left of the page, select the **StackSets** tab. Choose **Create StackSet**.
-1. In the **Permissions** section; leave the value for **IAM Admin role ARN** empty; set **IAM execution role name** to **AWSCloudFormationStackSetExecutionRole**.
-1. From the **Prerequisite - Prepare template** section, choose **Template is ready**.
-1. In **Specify template** section, under **Template source** choose **Upload a template file**. Select **Choose file** and supply the CloudFormation template `example_network.yaml` mentioned earlier, and then choose **Next**.
-1. In **Specify StackSet details** page, provide name, description, and set parameters:
- 1. Specify a **StackSet** name. For example, choose `cfn-workshop-network`.
- 2. Provide a **StackSet description**. For example, choose `Provisions VPC, internet gateway, two public subnets, and two routes to the Internet`.
- 3. Accept default values for **Parameters**. Choose **Next**.
-1. On **Configure StackSet options**, leave **Execution configuration** as is. Choose **Next**.
-1. In **Set deployment options** page, in **Add stacks to stack set** section, choose to **Deploy new stacks**.
-1. Under **Accounts**, choose **Deploy stacks in accounts**.
-1. In the **Account numbers** text box, enter the 12-digit AWS account ID for the account you are using for this lab. You can find this value by choosing the user/role drop-down menu in the top-right corner.
-
-1. For **Specify regions**, choose to deploy in **US East (N. Virginia)** and **US West (Oregon)**.
-1. Accept default values for **Deployment options**, and choose **Next**.
-1. On the **Review** page, review the contents of the page and choose **Submit**.
-1. Refresh the StackSet creation page until you see **CREATE** status as `SUCCEEDED`.
-
-1. Under **Stack instances**, you should see two stacks deployed. One in `us-east-1` and another in `us-west-2`.
-
-::::
-:::::
-Navigate to **Exports**. You should see 3 exports named `AWS-CloudFormationWorkshop-SubnetId1`, `AWS-CloudFormationWorkshop-SubnetId2,` and `AWS-CloudFormationWorkshop-VpcId`. These exports are created in each region where you deployed your stack sets (`us-east-1` and `us-west-2`).
-
-
-
-Congratulations! You have deployed your infrastructure to multiple AWS Regions using a single operation.
-
-#### Part 2
-
-In this part of the lab, you will use a new CloudFormation template, `example_securitygroup.yaml`, describing a security group that you will associate to the VPC you created earlier in a given region. You will also export the output for the **Security Group ID**, so that you can consume it later in the *Challenge* portion of this workshop lab. The architecture diagram highlighting the security group resource you will describe with the `example_securitygroup.yaml` template is shown next:
-
-
-
-Let’s get started:
-
-1. Navigate to the `code/workspace/stacksets` directory.
-1. Open the `example_securitygroup.yaml` template in your favorite text editor.
-1. Familiarize with the configuration for the example security group in the template. In the example, your intents are to:
- 1. create a security group for the VPC you created earlier in each of the two regions with a single create operation using CloudFormation StackSets. You will reference the VPC ID using the `Fn::ImportValue` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html);
- 2. export the `SecurityGroupId` output. Exports are region-specific
-
-In this next step, you will use the AWS CloudFormation console to create a stack set from the `example_securitygroup.yaml` template:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Let's **Create StackSets** by using the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-set \
---stack-set-name cfn-workshop-security \
---template-body file://example_securitygroup.yaml
-:::
-1. Create stack instances to your stackset by using the following AWS CLI command. This command requires you specify the 12-digit AWS Account ID for the account you are using for this Lab. You can find this value by choosing the user/role drop-down menu in the top-right corner. For regions, choose to deploy in US East (N. Virginia) and US West (Oregon).
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-instances \
---stack-set-name cfn-workshop-security \
---accounts 123456789012 \
---regions us-east-1 us-west-2
-:::
-1. CloudFormation returns the following output.
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"OperationId": "d7995c31-83c2-xmpl-a3d4-e9ca2811563f"
-:::
-1. Verify that the stack instances were created successfully. Run `DescribeStackSetOperation` with the `operation-id` that is returned as part of the output of step 3.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation describe-stack-set-operation \
---stack-set-name cfn-workshop-security \
---operation-id operation_ID
-:::
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/). From the panel on the left of the page, select the **StackSets** tab.
-1. Select `cfn-workshop-security`,Under **Stack instances**, you should see two stacks deployed. One in `us-east-1` and another in `us-west-2`
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Select the **StackSets** tab. Choose **Create StackSet**.
-1. In the **Permissions** section: for **IAM Admin role ARN**, select **IAM role name** from the drop-down menu, and set it to **AWSCloudFormationStackSetAdministrationRole**; set **IAM execution role name** to **AWSCloudFormationStackSetExecutionRole**.
-1. From **Prepare template**, choose **Template is ready**.
-1. For **Template source**, choose **Upload a template file**. Select **Choose file** and supply the CloudFormation template `example_securitygroup.yaml` mentioned earlier, and then choose **Next**.
-1. In **Specify StackSet details** page, provide name, description, and set parameters:
- 1. Specify a **StackSet name**. For example, choose `cfn-workshop-security`.
- 1. Provide a **StackSet description**. For example, choose `Provisions a security group, and associates it to the existing VPC`.
- 1. Accept default values for **Parameters**. Choose **Next**.
-1. On **Configure StackSet options**, leave **Execution Configuration** as is. Choose **Next**.
-1. In **Set deployment options** page, in **Add stacks to stack set** section, choose to **Deploy new stacks**.
-1. Under **Accounts**, choose **Deploy stacks in accounts** option.
-1. In the **Account numbers** text box, enter the 12-digit AWS account ID for the account you are using for this lab.
-1. For **Specify regions**, choose to deploy in **US East (N. Virginia)** and **US West (Oregon)**.
-1. Accept default values for **Deployment options**. Ensure **Maximum concurrent accounts** is set to **1**, **Failure tolerance** to **0** and **Region Concurrency** to **Sequential**. Choose **Next**.
-1. On the **Review** page, review the contents of the page, and choose **Submit**.
-1. Refresh the StackSet creation page until you see the **Status** of the **CREATE** operation as `SUCCEEDED`.
-1. Under **Stack instances**, you should see two stacks deployed. One in `us-east-1` and another in `us-west-2`.
-::::
-:::::
-
-Navigate to **Exports**. You should see a new export named `AWS-CloudFormationWorkshop-SecurityGroupId`.
-
-
-
-Congratulations! You have learned how export an output value from a stack set instance, and import it into another stack set instance.
-
-### Challenge
-
-In this exercise, you will use the knowledge gained from earlier parts of this lab. Your task is to create a new `cfn-workshop-ec2instance` stack set that will provision an [Amazon Elastic Compute Cloud (Amazon EC2)](https://docs.aws.amazon.com/ec2/) instance in the existing VPC, and attach the security group you created earlier. Your task is also to update the `example_ec2instance.yaml` template to import the value for `SubnetId1` that you exported as part of Part 1 of this lab. When you create the stack set, choose to deploy StackSets operations in **Parallel**. The architecture diagram highlighting the EC2 instance you will describe as part of this challenge is shown next:
-
-
-
-::::expand{header="Need a hint?"}
-* Make sure you are in the directory named `code/workspace/stacksets`.
-* Open the `example_ec2instance.yaml` CloudFormation template in the text editor of your choice.
-
-:::alert{type="info"}
-[Amazon Machine Image (AMI)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) resources are unique in each region. To use region-specific AMI IDs, you use the following code snippet in the `Parameters` section of your template to query the ID of the latest AMI for a given region; you also reference `LatestAmiId` in the **Resources** section of your template in `ImageId`.
-:::
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-LatestAmiId:
- Description: The ID of the region-specific Amazon Machine Image to use.
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-:::
-* Edit the `Resources` section of the template to import the value for `SubnetId1` that you exported in Part 1. You can import the parameter of your choice the same way you imported the ID of the VPC, from `example_network.yaml` to `example_securitygroup.yaml`.
-::::
-
-::::::expand{header="Want to see the solution?"}
-You can find the full solution in the `code/solutions/stacksets/example_ec2instance.yaml` template.
-
-Append the following to the EC2 instance properties: `SubnetId: !ImportValue AWS-CloudFormationWorkshop-SubnetId1`.
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Change the directory to `cfn101-workshop/code/solutions/stacksets`.
-1. Use the updated template, and create a new **StackSet** using the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-set \
---stack-set-name cfn-workshop-ec2instance \
---template-body file://example_ec2instance.yaml
-:::
-1. Create stack instances to your stackset by using the following AWS CLI command. To deploy StackSets operations in parallel, choose **Parallel** for `RegionConcurrencyType` from `--operation-preferences`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack-instances \
---stack-set-name cfn-workshop-ec2instance \
---accounts 123456789012 \
---regions us-east-1 us-west-2 \
---operation-preferences RegionConcurrencyType=PARALLEL
-:::
-::::
-::::tab{id="local" label="Local development"}
-Use the updated template, and create a new `cfn-workshop-ec2instance` stack set to deploy the EC2 instance resources in the 2 regions you chose earlier. To deploy StackSets operations in parallel, from **Deployment Options** choose **Parallel**. This will deploy StackSets operations in both regions in parallel, thus saving time.
-::::
-:::::
-::::::
-
-### Cleanup
-
-You will now tear down the resources you created. To delete a stack set, you will first delete its stack instances, and then delete the empty stack set.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Delete the stack instances from the **StackSet** before you delete the StackSets from AWS CLI.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack-instances \
---stack-set-name cfn-workshop-ec2instance \
---accounts 123456789012 \
---regions us-east-1 us-west-2 \
---no-retain-stacks
-:::
-1. Wait for `DELETE-STACK-INSTANCE` operation to complete and run the following command to delete the **StackSets**
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack-set \
---stack-set-name cfn-workshop-ec2instance
-:::
-1. Follow the steps 1-2 for other two stack sets, and in the following order: `cfn-workshop-security`, and `cfn-workshop-network`.
-1. Delete the IAM Roles that you created during this lab by running the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-set-name StackSetAdministratorRole
-:::
-1. Repeat the step 4 to **Delete** the execution role stack `StackSetAdministratorRole`.
-::::
-::::tab{id="local" label="Local development"}
-
-**How to delete AWS CloudFormation stacks within stack set**
-
-1. Navigate to the [AWS CloudFormation StackSets console.](https://console.aws.amazon.com/cloudformation/home#/stacksets)
-1. Select the CloudFormation stack set you want to delete the stacks from. Choose the last stack set you created, i.e., `cfn-workshop-ec2instance`.
-1. From top-right section of the page, select **Actions**, and choose **Delete stacks from StackSet**.
-1. Under **Accounts**, select **Deploy stacks in accounts** under **Deployment locations**.
-1. Under **Account numbers** enter the 12-digit AWS account ID for the account you are using for this lab.
-1. For **Specify regions** select **Add all regions**. This will automatically select the AWS Regions that the StackSet deployed stacks into. Choose **Next**.
-1. On the **Review** page, review the contents of the page, and choose **Submit**.
-1. The **Status** changes to `PENDING`.
-1. Refresh until the **Status** changes to `SUCCEEDED`.
-1. Follow steps 2 through 8 for the other two stack sets, and in the following order: `cfn-workshop-security`, and `cfn-workshop-network`.
-
-Now that you have deleted stacks within each StackSet, you will now choose to delete the empty StackSet.
-
-**How to delete an AWS CloudFormation stack set**
-
-1. Navigate to [AWS CloudFormation StackSets console](https://console.aws.amazon.com/cloudformation/home#/stacksets).
-1. Select the stack set you wish to delete.
-1. Choose **Actions**, and then **Delete**.
-1. In the popup that appears, confirm you want to delete this stack set by choosing **Delete StackSet**.
-1. On refresh, your StackSet should no longer be listed.
-1. Follow steps 2 through 5 for the two other stack sets.
-
-**How to delete an AWS CloudFormation stacks**
-
-1. Navigate to [AWS CloudFormation Stacks console](https://console.aws.amazon.com/cloudformation/home#/stacks).
-1. Select the stack `StackSetAdministratorRole`, choose **Delete**.
-1. In the popup that appears, confirm you want to delete this stack set by choosing **Delete**.
-1. On refresh, your stack `StackSetAdministratorRole` should no longer be listed.
-1. Follow steps 2 through 4 for the other stack `StackSetExecutionRole` that you created during this lab .
-::::
-:::::
-
-### Conclusion
-
-Great work! You learned how you can use CloudFormation StackSets to deploy templates in multiple AWS Regions using a single operation, and how to export output parameters from one stack set stack instance and import them into another stack set stack instance.
diff --git a/content/intermediate/operations/understanding-changesets/index.ja.md b/content/intermediate/operations/understanding-changesets/index.ja.md
deleted file mode 100644
index 204123a20..000000000
--- a/content/intermediate/operations/understanding-changesets/index.ja.md
+++ /dev/null
@@ -1,335 +0,0 @@
----
-title: "変更セットの理解"
-weight: 200
----
-
-_ラボ実施時間 : 20分程度_
-
----
-
-### 概要
-[AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/) スタックを更新すると、そのスタック内の 1 つ以上のリソースを目的の新しい状態に更新します。リソースの依存関係、[スタックリソースの更新動作](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html)、またはユーザーエラーなどの要因により、特定の状態と実際の新しい状態との間に違いが生じる可能性があります。
-
-スタックを[直接](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-direct.html)更新するか、[変更セット](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html) で更新するかを選べます。後者では、適用前に提案された変更のプレビューが表示され、予期しないリソース変更や置換を防ぐのに役立ちます。
-
-変更セットは、テンプレートのパラメータ値を変更するか、変更内容を記述した最新のテンプレートを提供することで作成できます。要件に最も適した変更セットを実行する前に、同じスタックに対して複数の変更セットを作成することもできます。
-
-### 取り上げるトピック
-このラボでは次のことを学びます。
-
-* 変更セットの作成方法
-* 更新後にスタックがどのようになるかを理解するための変更セットの読み方
-* CloudFormation がどのリソースを置き換える必要があるかを判断する方法と、静的評価と動的評価の仕組み
-
-### ラボを開始
-サンプルテンプレートを使用して、CloudFormation スタックを作成します。次に、このスタックに 2 つの異なる変更セットを作成します。1 つはテンプレートの編集によるもので、もう 1 つはパラメータ値の変更によるものです。
-
-それでは、始めましょう。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-
-1. **Code Editor ターミナル** で `code/workspace/understanding-changesets` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/understanding-changesets
-:::
-1. `Code Editor` エディターで `bucket.yaml` CloudFormation テンプレートを開き、サンプルテンプレートの内容をよく理解してください。
-1. 次の手順に従ってスタックを作成します。
- 1. このテンプレートでは、`BucketName` 入力パラメータに一意の値を指定する必要があります。詳細については、 [バケットの名前付け](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/bucketnamingrules.html)を参照してください。
- 1. 次のコマンドを使用してテンプレートからスタックを作成しましょう (この例では AWS リージョンに `us-east-1` を使用しています。必要に応じてこの値を変更してください)。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
---region us-east-1 \
---stack-name cfn-workshop-understanding-changesets \
---template-body file://bucket.yaml \
---parameters ParameterKey=BucketName,ParameterValue='YOUR_UNIQUE_BUCKET_NAME-HERE'
- :::
- 1. CloudFormation は次の出力を返します。
- :::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-understanding-changesets/330b0120-1771-11e4-af37-50ba1b98bea6"
- :::
- 1. CloudFormation コンソールまたは [wait stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) コマンドを使用して `cfn-workshop-understanding-changesets` スタックが作成されるまでお待ちください。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-understanding-changesets
- :::
- ::::
-::::tab{id="local" label="ローカル開発"}
-1. `code/workspace/understanding-changesets` ディレクトリに移動します。
-1. お好みのテキストエディタで `bucket.yaml` CloudFormation テンプレートを開き、サンプルテンプレートの内容をご確認ください。
-1. 以下の手順に従ってスタックを作成します。
- 1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
- 1. **スタックの作成** から、 **新しいリソースを使用 (標準)** を選択します。
- 1. **テンプレートの準備** セクションで、 **テンプレート準備完了** を選択します。
- 1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。`bucket.yaml` テンプレートファイルを選択し、 **次へ** をクリックします。
- 1. スタック名を指定します (例: `cfn-workshop-understanding-changesets`)。
- 1. `BucketName` パラメータには必ず一意の値を指定します。詳細については、[バケットの名前付け](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/bucketnamingrules.html) をご参照ください。 **次へ** をクリックします。
- 1. 次のページで、すべてのオプションをデフォルト値のままにし、 **次へ** をクリックします。
- 1. レビューページで、 **送信** をクリックします。
- 1. スタックのステータスが `CREATE_COMPLETE` になるまで、スタックの作成ページを更新します。
-::::
-:::::
-
-### ラボパート 1
-ラボのこの部分では、特定のリソースタイプについて、スタックの更新時に [中断を伴わない更新](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt) を必要とするプロパティを指定します。次に、変更セットを作成して変更をプレビューし、変更セット操作の出力を確認します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-`Code Editor` エディタで `bucket.yaml` CloudFormation テンプレートを開き、以下に示すように `VersioningConfiguration` を追加します。ファイルを保存します。
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-MyS3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketName: !Ref BucketName
- VersioningConfiguration:
- Status: Enabled
-:::
-次に、最初の変更セットを作成します。
-1. ターミナルから以下のコマンドを **変更セットの作成** に対して実行し、変更セットの名前を指定します (例:`bucket-versioning-update`)。次に、上の例で選択した `bucketName` パラメーターを指定します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-understanding-changesets \
---change-set-name bucket-versioning-update \
---template-body file://bucket.yaml \
---parameters ParameterKey=BucketName,ParameterValue='TYPE_UNIQUE_BUCKET_NAME-HERE'
-:::
-1. CloudFormation は AWS CLI の以下の出力を返します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-understanding-changesets/330b0120-1771-11e4-af37-50ba1b98bea6",
-"Id": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/bucket-versioning-update/a470cff7-cb2c-4cba-bf27-2b3b9ccc1333"
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-
-お好みのテキストエディタで `bucket.yaml` CloudFormation テンプレートを開き、以下に示すように `VersioningConfiguration` を追加し、ファイルを保存します。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-MyS3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketName: !Ref BucketName
- VersioningConfiguration:
- Status: Enabled
-:::
-
-次に、最初の変更セットを作成します。
-
-1. CloudFormation コンソールで `cfn-workshop-understanding-changesets` スタックを選択し、 **スタックアクション** から **既存スタックの変更セットを作成** を選択します。
-1. **テンプレートの準備** セクションで、 **既存テンプレートを置き換える** を選択します。 **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択し、更新した `bucket.yaml` テンプレートを選択し、 **次へ** をクリックします。
-1. **スタックの詳細を指定** ページと **スタックオプションの設定** ページの両方で **次へ** を **選択** し、 **変更セットの作成** をクリックします。
-1. 変更セットの名前を指定します (例: `bucket-versioning-update`)。また、`MyS3Bucket のバケットバージョニングを有効にする`などの説明を指定し、 **送信** をクリックします。
-1. 変更セットのステータスが `CREATE_COMPLETE` になるまでページを更新します。
-::::
-:::::
-
-1. [AWS CloudFormation](https://console.aws.amazon.com/cloudformation/) コンソールで、このワークショップで作成したスタックを選択します。たとえば、 `cfn-workshop-understanding-changesets` などです。
-1. **変更セット** タブから、 **bucket-versioning-update** を選択します。
-1. **JSON の変更** タブに移動すると詳細が表示されます。このタブは次のようになっているはずです。
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[
- {
- "resourceChange": {
- "logicalResourceId": "MyS3Bucket",
- "action": "Modify",
- "physicalResourceId": "understanding-changesets-123",
- "resourceType": "AWS::S3::Bucket",
- "replacement": "False",
- "moduleInfo": null,
- "details": [
- {
- "target": {
- "name": "VersioningConfiguration",
- "requiresRecreation": "Never",
- "attribute": "Properties"
- },
- "causingEntity": null,
- "evaluation": "Static",
- "changeSource": "DirectModification"
- }
- ],
- "changeSetId": null,
- "scope": [
- "Properties"
- ]
- },
- "hookInvocationCount": null,
- "type": "Resource"
- }
-]
-:::
-
-`resourceChange` 構造では、リソースの論理 ID、CloudFormation が実行するアクション、リソースの物理 ID、リソースのタイプ、および CloudFormation がリソースを置き換えるかどうかが表示されます。`details` 構造では、CloudFormation は、[バージョニング設定](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-properties)プロパティを更新しても中断を必要としないため、バケットを再作成 (replacement) する必要がない直接的な変更としてラベル付けしています。
-
-この変更セットを実行しても、CloudFormation は指定した設定に基づいてバケットを置き換えることはありません。変更セットの実行を控えて、別の変更セットを作成しましょう。
-
-### ラボパート 2
-スタックの更新時に [置換](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) を必要とするプロパティ `BucketName` の値を変更します。次に、変更セットを作成して変更をプレビューし、変更セット操作の出力を確認します。
-
-それでは、始めましょう。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. ターミナルから次のコマンドで **変更セットの作成** を実行し、新しい固有の[バケット名](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/bucketnamingrules.html)を指定して `bucketName` パラメータの値を変更し、前と同じように残りのプロセスを実行して変更セットの作成を完了します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-understanding-changesets \
---change-set-name replace-change-set \
---template-body file://bucket.yaml \
---parameters ParameterKey=BucketName,ParameterValue='YOUR-NEW-UNIQUE-BUCKET-NAME-HERE'
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. CloudFormation コンソールで `cfn-workshop-understanding-changesets` スタックを選択し、 **スタックアクション** から **既存スタックの変更セットを作成** を選択します。
-1. **テンプレートの準備** セクションで、 **現在のテンプレートの使用** を選択し、 **次へ** をクリックします。
-1. 新しい一意の[バケット名](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/bucketnamingrules.html)を指定して `BucketName` パラメータの値を変更し、前の手順に従って変更セットの作成を完了します。
-::::
-:::::
-
-この変更セットの **JSON の変更** は次のようになります。
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[
- {
- "resourceChange": {
- "logicalResourceId": "MyS3Bucket",
- "action": "Modify",
- "physicalResourceId": "understanding-changesets-123",
- "resourceType": "AWS::S3::Bucket",
- "replacement": "True",
- "moduleInfo": null,
- "details": [
- {
- "target": {
- "name": "BucketName",
- "requiresRecreation": "Always",
- "attribute": "Properties"
- },
- "causingEntity": null,
- "evaluation": "Dynamic",
- "changeSource": "DirectModification"
- },
- {
- "target": {
- "name": "BucketName",
- "requiresRecreation": "Always",
- "attribute": "Properties"
- },
- "causingEntity": "BucketName",
- "evaluation": "Static",
- "changeSource": "ParameterReference"
- }
- ],
- "changeSetId": null,
- "scope": [
- "Properties"
- ]
- },
- "hookInvocationCount": null,
- "type": "Resource"
- }
-]
-:::
-
-前の例とは 2 つの重要な違いがあることがわかります。まず、`resourceChange` 構造の `replacement` プロパティの値が `True` に設定されています。次に、`detail` 構造の下に `Static` と `Dynamic` の 2 つの評価が表示されます。これらの点について詳しく説明しましょう。
-
-置換が必要な `BucketName` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-properties) を更新したため、`replacement` の値は `True` です。CloudFormation は新しいリソース (この場合は新しいバケット) を作成し、古いリソースを削除します。特定のリソースに複数の変更を加え、それぞれの `requiresRecreation` フィールドの値が異なる場合、CloudFormation は再作成が必要になったときにリソースを置き換えます。言い換えると、多くの変更のうちの 1 つだけを置き換える必要がある場合、リソースを置き換えるために `replacement` フィールドを `True` に設定します。
-
-`replacement` フィールドの値は、`target` 構造の `requiresRecreation` フィールドで示されます。`requiresRecreation` フィールドが `Never` の場合、`replacement` フィールドは `False` になります。`requiresRecreation` フィールドが `Always` で、`evaluation` フィールドが `Static` の場合、`replacement` は `True` になります。ただし、`RequiresRecreation` フィールドが `Always` で、`evaluation` フィールドが `Dynamic` の場合、`replacement` は `Conditionally` になります。
-
-上の例で同じリソースに対して 2 つの異なる評価がある理由を理解するために、それぞれの意味を見てみましょう。
-
-`Static` 評価とは、変更を評価するために必要な情報がすべて揃っているため、CloudFormation が変更セットを実行する前に値を決定できることを意味します。
-
-CloudFormation では、変更セットを実行した後に初めて値を決定できる場合があります。CloudFormation は、これらの変更を `Dynamic` 評価としてラベル付けします。つまり、条件付きで置き換えられた更新済みリソースを参照する場合、CloudFormation は更新されたリソースへの参照が変更されるかどうかを判断できません。例えば、テンプレートに条件付きで置き換えられるリソースへの参照が含まれている場合、リソースを再作成するかどうかによって、参照の値 (リソースの物理 ID) が変わることがあります。リソースを再作成すると、新しい物理 ID が割り当てられるため、そのリソースへのすべての参照も更新されます。 上の例では、更新されたパラメータを参照していて、その結果として `Dynamic` 評価が行われています。
-
-次に、変更に関する静的評価関連データに注目しましょう。 上の例で、静的評価では、パラメータ参照値 `ParameterReference` が変更された結果であることが示されています。変更された正確なパラメータは `causingEntity` フィールド (この場合は `BucketName`) で示されます。
-
-### チャレンジ
-お好みのテキストエディタで、`code/workspace/understanding-changesets` ディレクトリにある `changeset-challenge.yaml` という名前のテンプレートファイルを開きます。このファイルは、以前に使用した `bucket.yaml` テンプレートの修正版です。`MyS3Bucket` ではなく `NewS3Bucket` の Amazon S3 バケットリソースの論理 ID を書き留めてください。テンプレートには、`MySqsQueue` 論理 ID を持つ [Amazon Simple Queue Service](https://aws.amazon.com/jp/sqs/) (SQS) [queue](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html#aws-resource-sqs-queue-properties) という新しいリソースも記述されていることに注意してください。
-
-`changeset-challenge.yaml` ファイルを使用して `cfn-workshop-understanding-changesets` スタックの新しい変更セットを作成したらどうなると思いますか? リソースはいくつ追加されますか? リソースは削除されますか? 変更セットの **JSON の変更** からキューの物理 ID を取得できますか?
-
-このファイルを使用して変更セットを作成し、提案された変更を正しく判断できたかどうかを確認してください。
-
-:::expand{header="ヒントが必要ですか?"}
-テンプレート内のリソースの論理 ID を変更し、更新したテンプレートでスタックを更新すると、CloudFormation はリソースを置き換えようとします。
-:::
-
-::::expand{header= "解決策を確認しますか?"}
-* CloudFormation は、新しい `MySqsQueue` キューリソースを追加することに加えて、`NewS3Bucket` 論理 ID を使用して新しいバケットを作成し、`MyS3Bucket` を削除しようとします。新しいリソースの物理 ID は作成されるまで使用できません。 **JSON の変更** は次のようになるはずです。
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[
- {
- "resourceChange": {
- "logicalResourceId": "MyS3Bucket",
- "action": "Remove",
- "physicalResourceId": "understanding-changesets-123",
- "resourceType": "AWS::S3::Bucket",
- "replacement": null,
- "moduleInfo": null,
- "details": [],
- "changeSetId": null,
- "scope": []
- },
- "hookInvocationCount": null,
- "type": "Resource"
- },
- {
- "resourceChange": {
- "logicalResourceId": "NewS3Bucket",
- "action": "Add",
- "physicalResourceId": null,
- "resourceType": "AWS::S3::Bucket",
- "replacement": null,
- "moduleInfo": null,
- "details": [],
- "changeSetId": null,
- "scope": []
- },
- "hookInvocationCount": null,
- "type": "Resource"
- },
- {
- "resourceChange": {
- "logicalResourceId": "MySqsQueue",
- "action": "Add",
- "physicalResourceId": null,
- "resourceType": "AWS::SQS::Queue",
- "replacement": null,
- "moduleInfo": null,
- "details": [],
- "changeSetId": null,
- "scope": []
- },
- "hookInvocationCount": null,
- "type": "Resource"
- }
-]
-:::
-::::
-
-### クリーンアップ
-
-このラボで作成したリソースをクリーンアップするには
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-ターミナルから次の AWS CLI コマンドを実行して、作成したスタックを削除します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-understanding-changesets
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. CloudFormation コンソールから、`cfn-workshop-understanding-changesets` という名前のスタックを選択します。
-1. **削除** を選択し、次に **削除** を選択してスタックと、スタック用に作成した変更セットを削除します。
-::::
-:::::
-
----
-
-### まとめ
-
-変更セットを作成する方法、変更セットの出力を読み取る方法、リソース設定の変更に基づいて CloudFormation がどのリソースを置き換える必要があるかを判断する方法を学びました。
diff --git a/content/intermediate/operations/understanding-changesets/index.md b/content/intermediate/operations/understanding-changesets/index.md
deleted file mode 100644
index 8d5692bd2..000000000
--- a/content/intermediate/operations/understanding-changesets/index.md
+++ /dev/null
@@ -1,337 +0,0 @@
----
-title: "Understanding change sets"
-weight: 200
----
-
-_Lab Duration: ~20 minutes_
-
----
-
-### Overview
-When you update an [AWS CloudFormation](https://aws.amazon.com/cloudformation/) stack, you update one or more resources in that stack to a desired new state. Due to factors that include resource dependencies, [update behaviors of stack resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html), or user error, there could be differences between the desired state and the actual, new state of a given resource.
-
-You choose to update your stacks either [directly](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-direct.html), or with [change sets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html): the latter gives you a preview of proposed changes before you apply them, and helps prevent unexpected resource configurations or replacements.
-
-You can create change sets by either modifying template parameter values, or by providing an updated template where you described your changes. You can also choose to create multiple change sets for the same stack, before executing the change set that best suits your requirements.
-
-### Topics Covered
-In this lab, you’ll learn:
-
-* how to create change sets
-* how to read change sets to understand what your stack will look like after the update
-* how CloudFormation decides which resources need replacement, and how static and dynamic evaluations work
-
-### Start Lab
-Using a sample template, you will create a CloudFormation stack. You will then create two different change sets for this stack: one by editing the template, and another one by modifying a parameter value.
-
-Let’s get started!
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-
-1. In the **Code Editor terminal** navigate to `code/workspace/understanding-changesets`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/understanding-changesets
-:::
-1. Open the `bucket.yaml` CloudFormation template in Code Editor, and familiarize yourself with the sample template content.
-1. Create a stack by following these steps:
- 1. The template requires you to provide a unique value for the `BucketName` input parameter. For more information, see [Bucket naming rules](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)
- 1. Let's create the stack from the template using the following command (the example uses `us-east-1` for the AWS region, change this value as needed):
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
---region us-east-1 \
---stack-name cfn-workshop-understanding-changesets \
---template-body file://bucket.yaml \
---parameters ParameterKey=BucketName,ParameterValue='YOUR_UNIQUE_BUCKET_NAME-HERE'
- :::
- 1. CloudFormation returns the following output:
- :::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-understanding-changesets/330b0120-1771-11e4-af37-50ba1b98bea6"
- :::
- 1. Wait until the `cfn-workshop-understanding-changesets` stack is created, by using the CloudFormation console or the [wait stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) AWS CLI command.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-understanding-changesets
- :::
- ::::
-::::tab{id="local" label="Local development"}
-1. Change directory to: `code/workspace/understanding-changesets`.
-1. Open the `bucket.yaml` CloudFormation template in your favorite text editor, and familiarize yourself with the sample template content.
-1. Create a stack by following these steps:
- 1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
- 2. From **Create stack**, choose **With new resources (standard)**.
- 3. From **Prepare template**, choose **Template is ready**.
- 4. From **Template source**, choose **Upload a template file**. Choose the `bucket.yaml` template file, and then choose **Next**.
- 5. Specify a stack name, for example `cfn-workshop-understanding-changesets`.
- 6. Make sure to provide a unique value for the `BucketName` parameter. For more information, see [Bucket naming rules](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html). Choose **Next**.
- 7. In the next page, choose to leave all options to default values, and choose **Next**.
- 8. In the review page, choose **Submit**.
- 9. Refresh the stack creation page until you see your stack in the `CREATE_COMPLETE` status.
-::::
-:::::
-
-### Lab part 1
-In this part of the lab, you will specify a property, for a given resource type, that requires [no interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt) on stack updates. You will then create a change set to preview the changes, and inspect the output of the change set operation.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-Open the `bucket.yaml` CloudFormation template in Code Editor, and add `VersioningConfiguration` as shown below. Save the file.
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-MyS3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketName: !Ref BucketName
- VersioningConfiguration:
- Status: Enabled
-:::
-Next, create your first change set:
-1. From Terminal run the following command to **Create change set**, specify a name for the change set for example:`bucket-versioning-update` and provide the `BucketName` parameter that chosen in above example.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-understanding-changesets \
---change-set-name bucket-versioning-update \
---template-body file://bucket.yaml \
---parameters ParameterKey=BucketName,ParameterValue='TYPE_UNIQUE_BUCKET_NAME-HERE'
-:::
-2. CloudFormation returns the following output of the AWS CLI.
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-understanding-changesets/330b0120-1771-11e4-af37-50ba1b98bea6",
-"Id": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/bucket-versioning-update/a470cff7-cb2c-4cba-bf27-2b3b9ccc1333"
-:::
-::::
-::::tab{id="local" label="Local development"}
-
-Open the `bucket.yaml` CloudFormation template in your favorite text editor, and add `VersioningConfiguration` as shown below. Save the file.
-
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-MyS3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketName: !Ref BucketName
- VersioningConfiguration:
- Status: Enabled
-:::
-
-Next, create your first change set:
-
-1. In the CloudFormation console, select the `cfn-workshop-understanding-changesets` stack, and from **Stack actions**, choose **Create change set for current stack**.
-2. From **Prepare template**, choose **Replace current template**. For **Template source**, choose **Upload a template file**, then select your updated `bucket.yaml` template, and choose **Next**.
-3. Choose **Next** again in both the **Specify stack details** and **Configure stack options** pages, and then choose **Create change set**.
-4. Specify a name for the change set, for example: `bucket-versioning-update`, as well as a description, for example: `Enable bucket versioning for MyS3Bucket.`, and choose **Submit**.
-5. Refresh the page until the status of the change set is `CREATE_COMPLETE`.
-::::
-:::::
-
-1. In the [AWS CloudFormation ](https://console.aws.amazon.com/cloudformation/) console, select the stack you created in this workshop. For example `cfn-workshop-understanding-changesets`.
-1. From **changesets** tab, choose **bucket-versioning-update**.
-1. Navigate to the **JSON changes** tab for more information, which should look similar to this:
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[
- {
- "resourceChange": {
- "logicalResourceId": "MyS3Bucket",
- "action": "Modify",
- "physicalResourceId": "understanding-changesets-123",
- "resourceType": "AWS::S3::Bucket",
- "replacement": "False",
- "moduleInfo": null,
- "details": [
- {
- "target": {
- "name": "VersioningConfiguration",
- "requiresRecreation": "Never",
- "attribute": "Properties"
- },
- "causingEntity": null,
- "evaluation": "Static",
- "changeSource": "DirectModification"
- }
- ],
- "changeSetId": null,
- "scope": [
- "Properties"
- ]
- },
- "hookInvocationCount": null,
- "type": "Resource"
- }
-]
-:::
-
-
-In the `resourceChange` structure, you can see the logical ID of the resource, the action CloudFormation will take, the Physical ID of the resource, the type of resource, and whether CloudFormation will replace the resource or not. In the `Details` structure, CloudFormation labels this change as a direct modification that will never require the bucket to be recreated (replaced) because updating the [Versioning configuration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html#cfn-s3-bucket-versioningconfiguration) property requires no interruption.
-
-If you execute this change set, CloudFormation will then not replace your bucket, based on the configuration you provided; let's hold off on executing the change set, and create another change set.
-
-### Lab part 2
-You will now modify the value for a property, `BucketName`, that requires a [replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) on stack updates. You will then create a change set to preview your changes, and inspect the output of the change set operation.
-
-Let’s get started!
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. From Terminal run the following command to **Create change set**, Change the value for `BucketName` parameter by specifying a new unique bucket [name](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html), and follow the rest of the process as before to finish creating the change set.
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-change-set \
---stack-name cfn-workshop-understanding-changesets \
---change-set-name replace-change-set \
---template-body file://bucket.yaml \
---parameters ParameterKey=BucketName,ParameterValue='YOUR-NEW-UNIQUE-BUCKET-NAME-HERE'
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. In the CloudFormation console, select the `cfn-workshop-understanding-changesets` stack, and from **Stack actions**, choose **Create change set for current stack**.
-1. From **Prepare template**, choose **Use current template** and choose **Next**.
-1. Change the value for `BucketName` parameter by specifying a new unique bucket [name](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html), and follow the rest of the process as before to finish creating the change set.
-::::
-:::::
-
-Here’s what the **JSON changes** for this change set should look like:
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[
- {
- "resourceChange": {
- "logicalResourceId": "MyS3Bucket",
- "action": "Modify",
- "physicalResourceId": "understanding-changesets-123",
- "resourceType": "AWS::S3::Bucket",
- "replacement": "True",
- "moduleInfo": null,
- "details": [
- {
- "target": {
- "name": "BucketName",
- "requiresRecreation": "Always",
- "attribute": "Properties"
- },
- "causingEntity": null,
- "evaluation": "Dynamic",
- "changeSource": "DirectModification"
- },
- {
- "target": {
- "name": "BucketName",
- "requiresRecreation": "Always",
- "attribute": "Properties"
- },
- "causingEntity": "BucketName",
- "evaluation": "Static",
- "changeSource": "ParameterReference"
- }
- ],
- "changeSetId": null,
- "scope": [
- "Properties"
- ]
- },
- "hookInvocationCount": null,
- "type": "Resource"
- }
-]
-:::
-
-You can see there are two key differences from the previous example. First, the value for the `replacement` property under the `resourceChange` structure is set to `True`; second, you see two evaluations, `Static` and `Dynamic`, under the `details` structure. Let's talk about these aspects in more detail.
-
-The value for `replacement` is `True` because you updated the `BucketName` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html#cfn-s3-bucket-bucketname) that requires a replacement. CloudFormation will create a new resource (a new bucket in this case), and then delete the old one. If there are multiple changes you make on a given resource, and each change has a different value for the `requiresRecreation` field, CloudFormation replaces the resource when a recreation is required. In other words, if only one of the many changes requires a replacement, CloudFormation replaces the resources, and therefore sets the `replacement` field to `True`.
-
-The value in the `replacement` field is indicated by the `requiresRecreation` field in the `target` structure. If the `requiresRecreation` field is `Never`, the `replacement` field is `False`. If the `requiresRecreation` field is `Always` and the `evaluation` field is `Static`, `replacement` is `True`. However, if the `requiresRecreation` field is `Always` and the `evaluation` field is `Dynamic`, `replacement` is `Conditionally`.
-
-To understand why there are two different evaluations for the same resource in the above example, let’s see what each of these means.
-
-A `Static` evaluation means that CloudFormation can determine the value before executing the change set because it already has all the information it needs to evaluate the changes.
-
-In some cases, CloudFormation can determine a value only after you execute a change set. CloudFormation labels those changes as `Dynamic` evaluations. In other words, if you reference an updated resource that is conditionally replaced, CloudFormation can't determine whether the reference to the updated resource will change. For example, if your template includes a reference to a resource that is conditionally replaced, the value of the reference (the physical ID of the resource) might change, depending on whether the resource will be recreated. If the resource is recreated, it will have a new physical ID, so all references to that resource will also be updated. In the above example, you are referencing an updated parameter which results in a `Dynamic` evaluation.
-
-Now, let's focus on static evaluation-related data for your changes. In the above example, the static evaluation shows that the change is a result of a modified parameter reference value, `ParameterReference`: the exact parameter that was changed is indicated by the `causingEntity` field, that is `BucketName` in this case.
-
-### Challenge
-Open, in your favorite text editor, the template file named `changeset-challenge.yaml`, that you can find in the `code/workspace/understanding-changesets` directory. This file is a modified version of the `bucket.yaml` template you used earlier: note the logical ID of the Amazon S3 bucket resource, that is `NewS3Bucket` instead of `MyS3Bucket`. Note that there is also a new resource described in the template: an [Amazon Simple Queue Service](https://aws.amazon.com/sqs/) (SQS) [queue](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html), with the `MySqsQueue` logical ID.
-
-What do you think will happen if you create a new change set for the `cfn-workshop-understanding-changesets` stack using the `changeset-challenge.yaml` file? How many resources will be added? Will any resource be removed? Will you be able to get the physical ID of the queue from the **JSON changes** of the change set?
-
-Create a change set with this file, and see if you were able to correctly determine the proposed changes.
-
-:::expand{header="Need a hint?"}
-When you change the logical ID of a resource in your template, and you update your stack with your updated template, CloudFormation tries to replace the resource.
-:::
-
-::::expand{header="Want to see the solution?"}
-* In addition to adding the new `MySqsQueue` queue resource, CloudFormation will try to create a new bucket with the `NewS3Bucket` logical ID, and delete `MyS3Bucket`. Physical IDs of new resources are not available until they are created. Here’s what the **JSON changes** should look like:
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[
- {
- "resourceChange": {
- "logicalResourceId": "MyS3Bucket",
- "action": "Remove",
- "physicalResourceId": "understanding-changesets-123",
- "resourceType": "AWS::S3::Bucket",
- "replacement": null,
- "moduleInfo": null,
- "details": [],
- "changeSetId": null,
- "scope": []
- },
- "hookInvocationCount": null,
- "type": "Resource"
- },
- {
- "resourceChange": {
- "logicalResourceId": "NewS3Bucket",
- "action": "Add",
- "physicalResourceId": null,
- "resourceType": "AWS::S3::Bucket",
- "replacement": null,
- "moduleInfo": null,
- "details": [],
- "changeSetId": null,
- "scope": []
- },
- "hookInvocationCount": null,
- "type": "Resource"
- },
- {
- "resourceChange": {
- "logicalResourceId": "MySqsQueue",
- "action": "Add",
- "physicalResourceId": null,
- "resourceType": "AWS::SQS::Queue",
- "replacement": null,
- "moduleInfo": null,
- "details": [],
- "changeSetId": null,
- "scope": []
- },
- "hookInvocationCount": null,
- "type": "Resource"
- }
-]
-:::
-::::
-
-### Cleanup
-
-To clean up resources you created with this lab:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-From the terminal execute the following AWS CLI command to delete the stacks you created.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-understanding-changesets
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. From the CloudFormation console, select the stack named `cfn-workshop-understanding-changesets`.
-1. Choose **Delete**, and then **Delete** to delete your stack and change sets you created for it.
-::::
-:::::
-
----
-
-### Conclusion
-Nicely done!
-
-You learned how to create change sets, how to read a change set output, and how CloudFormation decides which resources need to be replaced based on resource configuration changes you make.
diff --git a/content/intermediate/operations/update-behaviors-of-stack-resources/index.ja.md b/content/intermediate/operations/update-behaviors-of-stack-resources/index.ja.md
deleted file mode 100644
index ad9299c27..000000000
--- a/content/intermediate/operations/update-behaviors-of-stack-resources/index.ja.md
+++ /dev/null
@@ -1,251 +0,0 @@
----
-title: "スタックリソースの更新動作"
-weight: 100
----
-
-### 概要
-このラボでは、インフラストラクチャの設計および更新への対応方法に関する重要なポイントを学びます。アプリケーションと環境が進化するにつれて、テンプレートに記述されているリソース構成に更新を適用します。
-
-CloudFormation は、変更が適用されたテンプレートと、以前のバージョンのテンプレートで記述したリソース構成との変更を比較することによってリソースを更新します。変更されていないリソース構成は、更新プロセス中も影響を受けません。それ以外の場合、CloudFormation は次のいずれかの[更新動作](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html)を使用します。 **中断を伴わない更新** 、 **一時的な中断を伴う更新** 、 **置換** の各更新動作は、特定の[リソースタイプ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)に従い、テンプレートに追加する新しいプロパティや、変更するプロパティ値によって決まります。
-
-### 対象トピック
-このラボを修了すると、次のことができるようになります。
-
-* スタックリソースの更新動作を学びます。
-* 更新動作がプロビジョニングされたスタックリソースにどのように影響するかについての重要な考慮事項について学びます。
-
-**ラボを開始**
-* `code/workspace/update-behaviors-of-stack-resources` ディレクトリに移動します。
-* お好みのテキストエディタで `update-behaviors-of-stack-resources.yaml` ファイルを開きます。
-* ラボを進めながら、コンテンツをコピーしてファイルに追加します。
-
-テンプレートに [Amazon Elastic Compute Cloud](https://aws.amazon.com/jp/ec2/)(Amazon EC2) インスタンスを記述することから始めましょう。`update-behaviors-of-stack-resources.yaml` テンプレートに以下の `Paramaters` セクションをコピーして追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=5}
-Parameters:
- InstanceType:
- Description: WebServer EC2 instance type
- Type: String
- Default: t2.micro
- AllowedValues: [t2.micro, t2.small, t2.medium]
- ConstraintDescription: must be a valid EC2 instance type.
-
- LatestAmiId:
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-:::
-
-次に、`Resources` セクションと Amazon EC2 インスタンス定義をコピーしてテンプレートに追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=17}
-Resources:
- EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- InstanceType: !Ref InstanceType
- ImageId: !Ref LatestAmiId
- Tags:
- - Key: Name
- Value: cfn-workshop
-:::
-
-
-変更をファイルに保存します。次に、`update-behaviors-of-stack-resources.yaml` テンプレートを使用してスタックを作成します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/update-behaviors-of-stack-resources` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd code/workspace/update-behaviors-of-stack-resources
-:::
-1. AWS CLI を使用してスタックを作成します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-update-behaviors-of-stack-resources --template-body file://update-behaviors-of-stack-resources.yaml
-:::
-1. `create-stack` コマンドが正常に送信されると、CloudFormation は `StackID` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-update-behaviors-of-stack-resources/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. 使用したい[リージョン](https://docs.aws.amazon.com/ja_jp/awsconsolehelpdocs/latest/gsg/select-region.html)を選択します。
-1. **スタックの作成** 、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートの準備** セクションで、 **テンプレートの準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。前述の `update-behaviors-of-stack-resources.yaml` テンプレートを選択し、 **次へ** をクリックします。
-1. スタック名を指定します。例えば、`cfn-workshop-update-behaviors-of-stack-resources` と入力します。`InstanceType` パラメータと `LatestAmiID` パラメータのデフォルト値をそのまま使用し、 **次へ** をクリックします。
-1. **スタックオプションの設定** ページはデフォルト値のまま、 **次へ** をクリックします。
-1. **レビュー** ページで一番下までスクロールし、 **送信** をクリックします。
-1. スタックの作成が完了するまでお待ちください。スタックのステータスが `CREATE_COMPLETE` になるまで、コンソールのビューを更新します。
-::::
-:::::
-
-**置換**
-
-ここまで、スタックを使用して Amazon EC2 インスタンスを作成しました。インスタンスの [Amazon Machine Image](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/AMIs.html) (AMI) には、このラボで最新の `x86-64` Amazon Linux 2 AMI を使用しました。次に、Amazon EC2 インスタンスに別の AMI を使用する必要があるシナリオを考えてみましょう。このラボでは、前に作成した CloudFormation スタック `cfn-workshop-update-behaviors-of-stack-resources` を更新し、`LatestAmiId` のパラメータ値を `/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-ebs` でオーバーライドします。
-
-::alert[リソースのプロパティ値を変更するときは、必ずドキュメント内の特定のリソースプロパティの [Update requires](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-imageid)の値を確認してください。この場合、`ImageID` プロパティの値を更新すると、リソース[置換 (Replacement)](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) 動作が実行されます。]{type="info"}
-
-いよいよスタックを更新しましょうに移動し、`cfn-workshop-update-behaviors-of-stack-resources` スタックを更新します。
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. `cfn-workshop-update-behaviors-of-stack-resources` スタックを作成した[リージョン](https://docs.aws.amazon.com/ja_jp/awsconsolehelpdocs/latest/gsg/select-region.html)を必ず選択してください。
-1. 先ほど作成したスタック (例えば、`cfn-workshop-update-behaviors-of-stack-resources`) を選択します。
-1. **更新** を選択します。
-1. **テンプレートの準備** で **現在のテンプレートの使用** を選択し、 **次へ** をクリックします。
-1. **パラメータ** ページで、`InstanceType` のデフォルト値をそのまま使用し、`LatestAmiID` パラメータの既存の値を `/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs` という新しい値に置き換えます。準備ができたら、 **次へ** をクリックします。
-1. **スタックオプションの設定** ページでデフォルト値のまま、 **次へ** をクリックします。
-1. **レビュー** ページで一番下までスクロールし、 **送信** を選択します。
-
-スタックの更新中に、[Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/)に移動し、 **インスタンス** を選択します。新しいインスタンスが起動され、このラボで以前に作成したインスタンスが終了することを確認できます。上記で行った AMI の変更によるスタック更新を実施すると、CloudFormation は最初に新しいインスタンスを作成し、前のインスタンスを削除しました。この例では、 **置換** 動作を示しています。
-
-おめでとうございます! **置換** 動作を学習しました。
-
-
-**一時的な中断を伴う更新**
-
-
-ワークロードの要件が変わり、CPU とメモリの要件に合わせて新しい [Amazon EC2](https://aws.amazon.com/jp/ec2/instance-types/) インスタンスタイプが必要だと判断した例を見てみましょう。例えば、`cfn-workshop-update-behaviors-of-stack-resources` スタックで管理するインスタンスのタイプを、`t2.micro` から `t2.small` に変更します。
-
-:::alert{type="info"}
-インスタンスの `InstanceType` プロパティ値を変更する場合、まず [Update requires](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-instancetype) で説明されている動作を確認し、スタックを更新するとどうなるのかを理解する必要があります。
-:::
-
-さっそくスタックを更新しましょう:
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. `cfn-workshop-update-behaviors-of-stack-resources` スタックを作成した[リージョン](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/select-region.html)を必ず選択してください。
-1. 先ほど作成したスタック (例えば、`cfn-workshop-update-behaviors-of-stack-resources`) を選択します。
-1. **更新** を選択します。
-1. **テンプレートの準備** で **現在のテンプレートの使用** を選択し、 **次へ** をクリックします。
-1. 次のページで、`LatestAmiId` パラメータのデフォルト値をそのまま使用し、`InstanceType` パラメータ値として `t2.small` を選択します。 **次へ** をクリックします。
-1. **スタックオプションの設定** ページでデフォルト値のまま、 **次へ** をクリックします。
-1. **レビュー** ページで一番下までスクロールし、 **送信** をクリックします。
-
-スタックの更新中に、[Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/)に移動し、 **インスタンス** を選択します。インスタンスは最初に停止されるため、一時的に使用できなくなります。インスタンスタイプが `t2.small` に変更されると、まもなく running ステータスになることを確認できます。この例は、 **一時的な中断を伴う更新** の動作を示しています。
-
-おめでとうございます! **一時的な中断を伴う更新** 動作について学習しました。
-
-
-**中断を伴わない更新**
-
-前の例を続けてみましょう。インスタンスは現在、[基本モニタリング](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-cloudwatch-new.html)を使用しており、インスタンスのメトリクスデータが 5 分間隔で[Amazon CloudWatch](https://aws.amazon.com/jp/cloudwatch/) に送信されます。ワークロードのメトリクスデータを 1 分間隔で利用できるようにする必要があり、インスタンスの[詳細モニタリング](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-cloudwatch-new.html)を有効にします。
-
-次に、`update-behaviors-of-stack-resources.yaml` テンプレートに記載したインスタンスに `Monitoring` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-monitoring)を `true` に設定して追加します。
-
-::alert[この新しいプロパティを追加する際は、`Monitoring` の [Update requires](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-monitoring) の値を見て、スタックを更新するとどうなるかを確認してください。]{type="info"}
-
-既存の `update-behaviors-of-stack-resources.yaml` テンプレートを更新し、`EC2Instance` の定義に `Monitoring` プロパティを指定します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=17 highlightLines=22}
-EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- InstanceType: !Ref InstanceType
- ImageId: !Ref LatestAmiId
- Monitoring: true
- Tags:
- - Key: Name
- Value: cfn-workshop
-:::
-
-変更をファイルに保存します。次に、スタックを更新します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/update-behaviors-of-stack-resources` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd code/workspace/update-behaviors-of-stack-resources
-:::
-1. AWS CLI を使用してスタックを更新します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name update-behaviors-of-stack-resources --template-body file://update-behaviors-of-stack-resources.yaml
-:::
-1. `update-stack` が正常に送信された場合、CloudFormation は `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/drift-detection-workshop/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **UPDATE_COMPLETE** になっているかどうかを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. `cfn-workshop-update-behaviors-of-stack-resources` スタックを作成した[リージョン](https://docs.aws.amazon.com/ja_jp/awsconsolehelpdocs/latest/gsg/select-region.html)を選択してください。
-1. 先ほど作成したスタック (例えば、`cfn-workshop-update-behaviors-of-stack-resources`) を選択します。
-1. **更新** を選択します。
-1. **テンプレートの準備** セクションで **既存テンプレートを置き換える** を選択し、 **テンプレートの指定** セクションの **テンプレートファイルのアップロード** で、`update-behaviors-of-stack-resources.yaml` テンプレートファイルを選択します。準備ができたら、 **次へ** をクリックします。
-1. パラメータページで、`LatestAmiId` パラメータと `InstanceType` パラメータのデフォルト値をそのまま使用し、 **次へ** をクリックします。
-1. **スタックオプションの設定** ページでデフォルト値のまま、 **次へ** をクリックします。
-1. **レビュー** ページで一番下までスクロールし、 **送信** をクリックします。
-::::
-:::::
-
-[Amazon EC2 コンソール](https://console.aws.amazon.com/ec2/)に移動し、 **インスタンス** を選択します。スタックが更新されている間、インスタンスは実行中の状態のままであることに注意してください。これは、 **中断を伴わない更新** の動作を示しています。
-
-おめでとうございます! **中断を伴わない更新** の動作を学習しました。
-
-### チャレンジ
-このラボで使用したテンプレートの `EC2Instance` の `Name` タグキーの `Value` を更新する任務があります。この情報をインスタンスの `Tags` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-tags)に記述します。`update-behaviors-of-stack-resources.yaml` テンプレートで、`Name` タグの `Value` に `cfn-workshop-new-value` を指定します。スタックを更新するときに、3 つの更新動作のうちどれが適用されるかわかりますか?
-
-:::expand{header="ヒントが必要ですか?"}
-* CloudFormation ドキュメントのどこで、特定のリソースタイプ (この場合 `AWS::EC2::Instance` [リソース](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html))について、特定のリソースプロパティの更新動作について知ることができますか?
-:::
-
-::::::expand{header="解決策を確認しますか?"}
-次に示すように、テンプレートの `Name` タグの `Value` の情報を更新します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=17 highlightLines=25}
-EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- InstanceType: !Ref InstanceType
- ImageId: !Ref LatestAmiId
- Monitoring: true
- Tags:
- - Key: Name
- Value: cfn-workshop-new-value
-:::
-
-変更内容を `update-behaviors-of-stack-resources.yaml` テンプレートに保存します。更新したテンプレートでスタックを更新する前に、`Tags` プロパティの **Update requires** [セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-tags)を参照してください。この場合、[中断を伴わない更新](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)になります。
-
-スタックの更新:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/update-behaviors-of-stack-resources` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd code/workspace/update-behaviors-of-stack-resources
-:::
-1. AWS CLI を使用してスタックを更新します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name update-behaviors-of-stack-resources --template-body file://update-behaviors-of-stack-resources.yaml
-:::
-1. `update-stack` が正常に送信された場合、CloudFormation は `StackId` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/drift-detection-workshop/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **UPDATE_COMPLETE** になっているかどうかを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. `cfn-workshop-update-behaviors-of-stack-resources` スタックを作成した[リージョン](https://docs.aws.amazon.com/ja_jp/awsconsolehelpdocs/latest/gsg/select-region.html)を選択してください。
-1. 先ほど作成したスタック (例えば、`cfn-workshop-update-behaviors-of-stack-resources`) を選択します。
-1. **更新** を選択します。
-1. **テンプレートの準備** セクションで **既存テンプレートを置き換える** を選択し、次に `update-behaviors-of-stack-resources.yaml` テンプレートを選択します。準備ができたら、 **次へ** をクリックします。
-1. 次のページで、`LatestAmiId` と `InstanceType` パラメータのデフォルト値をそのまま使用し、 **次へ** をクリックします。
-1. **スタックオプションの設定** ページでデフォルト値のまま、 **次へ** をクリックします。
-1. **レビュー** ページで一番下までスクロールし、 **送信** をクリックします。
-::::
-:::::
-::::::
-
-### クリーンアップ
-次に示す手順に従って、このラボで作成したリソースをクリーンアップしてください。
-
-* CloudFormation コンソールで、このラボで作成した `cfn-workshop-update-behaviors-of-stack-resources` スタックを選択します。
-* **削除** を選択した後、 **削除** を押して確定します。
-
----
-
-### まとめ
-おめでとうございます! これで、スタックリソースの更新動作がわかりました!
diff --git a/content/intermediate/operations/update-behaviors-of-stack-resources/index.md b/content/intermediate/operations/update-behaviors-of-stack-resources/index.md
deleted file mode 100644
index 8c88505e4..000000000
--- a/content/intermediate/operations/update-behaviors-of-stack-resources/index.md
+++ /dev/null
@@ -1,243 +0,0 @@
----
-title: "Update behaviors of stack resources"
-weight: 100
----
-
-### Overview
-In this lab, you will learn important aspects of how to design and address updates of your infrastructure. As your applications and environments evolve, you apply updates to resource configurations described in your templates.
-
-CloudFormation updates resources by comparing changes between the updated template you provide, and resource configurations you described in the previous version of your template. Resource configurations that haven't changed remain unaffected during the update process; otherwise, CloudFormation uses one of the following [update behaviors](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html): **Update with No Interruption**, **Updates with Some Interruption**, and **Replacement**, depending on which new property you add, or on which property value you modify, for a given [resource type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) you describe in your template.
-
-### Topics Covered
-By the end of this lab, you will be able to:
-
-* Learn update behaviors of stack resources.
-* Learn important considerations of how update behaviors affect your provisioned stack resources.
-
-**Start Lab**
-* Change directory to: `code/workspace/update-behaviors-of-stack-resources`.
-* Open the `update-behaviors-of-stack-resources.yaml` file with your favorite text editor.
-* Copy and append content to the file, as you go through the lab.
-
-Let’s get started with describing an [Amazon Elastic Compute Cloud](https://aws.amazon.com/ec2/) (Amazon EC2) instance in your template. Copy and append the `Parameters` section shown next to the `update-behaviors-of-stack-resources.yaml` template:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=5}
-Parameters:
- InstanceType:
- Description: WebServer EC2 instance type
- Type: String
- Default: t2.micro
- AllowedValues: [t2.micro, t2.small, t2.medium]
- ConstraintDescription: must be a valid EC2 instance type.
-
- LatestAmiId:
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-:::
-
-Next, copy and append the following `Resources` section and the Amazon EC2 instance definition to your template:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=17}
-Resources:
- EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- InstanceType: !Ref InstanceType
- ImageId: !Ref LatestAmiId
- Tags:
- - Key: Name
- Value: cfn-workshop
-:::
-
-Save your changes to the file. Next, create your stack with the `update-behaviors-of-stack-resources.yaml` template:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/update-behaviors-of-stack-resources`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd code/workspace/update-behaviors-of-stack-resources
-:::
-1. Use the AWS CLI to create the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-update-behaviors-of-stack-resources --template-body file://update-behaviors-of-stack-resources.yaml
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-update-behaviors-of-stack-resources/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. [Choose a Region](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/select-region.html) you wish to use.
-1. From **Create stack**, choose **With new resources (standard)**.
-1. In **Prepare template**, choose **Template is ready**.
-1. From **Template source**, choose **Upload a template file**. Choose the `update-behaviors-of-stack-resources.yaml` template mentioned earlier, and then choose **Next**.
-1. Specify a stack name: for example, `cfn-workshop-update-behaviors-of-stack-resources`. On the same page, accept default values for `InstanceType` and `LatestAmiId` parameters, and choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page. Choose **Next**.
-1. On the **Review** page, scroll down to the bottom, and choose **Submit**.
-1. Wait until the stack creation is complete. Refresh the view in the console until you see your stack to be in the `CREATE_COMPLETE` status.
-::::
-:::::
-
-**Replacement**
-
-So far, you've created an Amazon EC2 instance with your stack. For your instance's [Amazon Machine Image](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) (AMI), you used the latest `x86-64` Amazon Linux 2 AMI in this lab. Let's now consider a scenario where you have a requirement to use a different AMI for your Amazon EC2 instance. In this lab, you choose to update the CloudFormation stack you created earlier, `cfn-workshop-update-behaviors-of-stack-resources`, and override the parameter value for `LatestAmiId` with `/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-ebs`.
-
-::alert[When you change a property value for a resource, always look at the value for [Update requires](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-imageid) for the given resource property in the documentation. In this case, updating the value for the `ImageId` property results in a resource [replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) behavior.]{type="info"}
-
-Now it’s time to update your stack! Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/), and update your `cfn-workshop-update-behaviors-of-stack-resources` stack as shown next:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Make sure to choose the [region](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/select-region.html) where you’ve created the stack: `cfn-workshop-update-behaviors-of-stack-resources`.
-1. Choose the stack you created earlier, for example `cfn-workshop-update-behaviors-of-stack-resources`.
-1. Choose **Update**.
-1. In **Prepare template**, choose **Use current template,** and then choose **Next**.
-1. On the **Parameters** page, accept the default value for `InstanceType`, and replace the existing value for the `LatestAmiId` parameter with this new value: `/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-ebs`. When ready, choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page, and choose **Next**.
-1. On the **Review** page, scroll down to the bottom, and choose **Update stack**.
-
-While your stack is updating, navigate to the [Amazon EC2 Console](https://console.aws.amazon.com/ec2/), and choose **Instances**. You will notice a new instance will be launched, and the instance you created earlier in this lab will be terminated. When you updated the stack with the AMI change you made above, CloudFormation created your new instance first, and deleted the previous one: this example illustrates the **Replacement** behavior.
-
-Congratulations! You have learned the **Replacement** behavior.
-
-**Updates with Some Interruption**
-Let’s go over an example where your workload requirements change, and you determine that you need a new [Amazon EC2 instance type](https://aws.amazon.com/ec2/instance-types/) for your CPU and memory requirements. For this, you choose to change the type for the instance, that you manage with your `cfn-workshop-update-behaviors-of-stack-resources` stack, from `t2.micro` to `t2.small` for example.
-
-:::alert{type="info"}
-As you’re changing the `InstanceType` property value for your instance, you first want to look at the behavior described in [Update requires](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-instancetype) for the property, to understand what will happen when you update the stack.
-:::
-
-Let’s go ahead and update the stack:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Make sure you choose the [region](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/select-region.html) where you’ve created the stack: `cfn-workshop-update-behaviors-of-stack-resources`.
-1. Choose the stack you created earlier, for example `cfn-workshop-update-behaviors-of-stack-resources`.
-1. Choose **Update**.
-1. In **Prepare template**, choose **Use current template** and choose **Next**.
-1. On the next page, accept the default value for the `LatestAmiId` parameter, and choose `t2.small` for the `InstanceType` parameter value. Choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page, and choose **Next**.
-1. On the **Review** page, scroll down to the bottom and choose **Update stack**.
-
-While your stack is updating, navigate to the [Amazon EC2 Console](https://console.aws.amazon.com/ec2/), and choose **Instances**. Note that your instance will be first stopped - thus, it will be temporarily not available - and, once the instance type changes to `t2.small`, it will then enter the running status shortly. This example illustrates the **Updates with Some Interruption** behavior.
-
-Congratulations! You have learned the **Updates with Some Interruption** behavior.
-
-**Update with No Interruption**
-
-Let’s continue the previous example: your instance is currently using [basic monitoring](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch-new.html), where instance metric data is sent to [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/) in 5-minute periods. Let’s say that you require metric data to be available on 1-minute periods for your workload, and you choose to enable [detailed monitoring](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch-new.html) for your instance.
-
-You then choose to add the `Monitoring` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-monitoring), set to `true`, for the instance you described in your `update-behaviors-of-stack-resources.yaml` template.
-
-::alert[As you’re adding this new property, look at the value for [Update requires](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-monitoring) for `Monitoring`, to learn what will happen when you update the stack.]{type="info"}
-
-Update your existing `update-behaviors-of-stack-resources.yaml` template, and specify the `Monitoring` property in the definition for `EC2Instance` as shown next:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=17 highlightLines=22}
-EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- InstanceType: !Ref InstanceType
- ImageId: !Ref LatestAmiId
- Monitoring: true
- Tags:
- - Key: Name
- Value: cfn-workshop
-:::
-
-Save your changes to the file. Next, update your stack:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/update-behaviors-of-stack-resources`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd code/workspace/update-behaviors-of-stack-resources
-:::
-1. Use the AWS CLI to update the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name update-behaviors-of-stack-resources --template-body file://update-behaviors-of-stack-resources.yaml
-:::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/drift-detection-workshop/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-2. Make sure you choose the [region](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/select-region.html) where you’ve created the `cfn-workshop-update-behaviors-of-stack-resources` stack.
-3. Choose the stack you created earlier, for example `cfn-workshop-update-behaviors-of-stack-resources`.
-4. Choose **Update**.
-5. In **Prepare template**, choose **Replace current template**, and then choose the `update-behaviors-of-stack-resources.yaml` template file for **Upload a template file** in the **Specify template** section. When ready, choose **Next**.
-6. On the parameters page, accept the default value for `LatestAmiId` and `InstanceType` parameters, and choose **Next**.
-7. Choose to accept default values in the **Configure stack options** page, and choose **Next**.
-8. On the **Review** page, scroll down to the bottom and choose **Update stack**.
-::::
-:::::
-
-Navigate to the [Amazon EC2 Console](https://console.aws.amazon.com/ec2/), and choose **Instances**. While the stack is updating, note that your instance will stay in the running status. This illustrates the **Update with No Interruption** behavior.
-
-Congratulations! You have learned the **Update with No Interruption** behavior.
-
-### Challenge
-You are tasked with updating the `Value` of the `Name` tag key for `EC2Instance` in the template you used in this lab. Choose to describe this information in the `Tags` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-tags) for your instance. In the `update-behaviors-of-stack-resources.yaml` template, choose to specify `cfn-workshop-new-value` for the `Name` tag's `Value`. Can you tell which of the three update behaviors will apply when you update the stack?
-
-:::expand{header="Need a hint?"}
-Where, in the CloudFormation documentation for a given resource type (in this case, for the `AWS::EC2::Instance` [resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html)), can you learn about the update behavior for a given resource property?
-:::
-::::::expand{header="Want to see the solution?"}
-Update the `Value` of the `Name` tag key in your template, as shown next:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=17 highlightLines=25}
-EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- InstanceType: !Ref InstanceType
- ImageId: !Ref LatestAmiId
- Monitoring: true
- Tags:
- - Key: Name
- Value: cfn-workshop-new-value
-:::
-
-Save your changes to the `update-behaviors-of-stack-resources.yaml` template. Before you update the stack with your updated template, see the **Update requires** [section](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-tags) for the `Tags` property; you will notice that **Update requires**, in this case, requires [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt).
-
-Update your stack:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/update-behaviors-of-stack-resources`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd code/workspace/update-behaviors-of-stack-resources
-:::
-1. Use the AWS CLI to update the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack --stack-name update-behaviors-of-stack-resources --template-body file://update-behaviors-of-stack-resources.yaml
-:::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/drift-detection-workshop/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Make sure you choose the [region](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/select-region.html) where you’ve created the `cfn-workshop-update-behaviors-of-stack-resources` stack.
-1. Choose the stack you created earlier, for example `cfn-workshop-update-behaviors-of-stack-resources`.
-1. Choose **Update**.
-1. In **Prepare template**, choose **Replace** **current template**, and then choose the `update-behaviors-of-stack-resources.yaml` template mentioned earlier. When ready, choose **Next**.
-1. On the next page, choose to accept default values for `LatestAmiId` and `InstanceType` parameters, and choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page, and choose **Next**.
-1. On the **Review** page, scroll down to the bottom and choose **Update stack**.
-::::
-:::::
-::::::
-
-### Cleanup
-Follow steps shown next to clean up resources you created in this lab:
-
-* In the CloudFormation console, choose the `cfn-workshop-update-behaviors-of-stack-resources` stack you created in this lab.
-* Choose **Delete** to delete the stack, and then choose **Delete stack** to confirm.
-
----
-
-### Conclusion
-Congratulations! You have now learned the update behaviors of stack resources!
diff --git a/content/intermediate/templates/architecting-templates/index.ja.md b/content/intermediate/templates/architecting-templates/index.ja.md
deleted file mode 100644
index 73e79b79b..000000000
--- a/content/intermediate/templates/architecting-templates/index.ja.md
+++ /dev/null
@@ -1,399 +0,0 @@
----
-title: "テンプレートの設計"
-weight: 650
----
-
-### 概要
-
-インフラストラクチャをコードで記述する場合、インフラストラクチャの成長に合わせて拡張できることと、時間の経過に伴う継続的な保守性を考慮する必要があります。[AWS CloudFormation ベストプラクティス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/best-practices.html) ページには、ワークフローで採用すべきベストプラクティスがまとめられています。このラボでは、コードで記述するリソースの _ライフサイクルと所有権_ の側面と _モジュール性と再利用_ のプラクティスを考慮して、テンプレートの設計に焦点を当てます。これらのプラクティスは、同じアカウントとリージョン内のスタックの値を参照して CloudFormation テンプレートに実装します。テンプレートの入力パラメータも同様です。このワークショップでは、ベストプラクティスの例を示す他のセルフペースラボもあります。例えば、[疑似パラメータ](/basics/templates/pseudo-parameters)、[リンティングとテスト](/basics/templates/linting-and-testing)、[動的参照](/intermediate/templates/dynamic-references) (AWS CloudFormation テンプレート内の機密情報の参照)、[Policy-as-Code with Guard](/intermediate/templates/policy-as-code-with-guard) (JSON および YAML 形式のデータのコードとしてのポリシー検証) です。
-
-
-
-### 取り上げるトピック
-
-このラボを修了すると、次のことを学ぶことができます。
-
-* ライフサイクルと所有権の基準による設計テンプレートを含むデザインパターンを学習
-* 依存関係の値をエクスポートして利用することでスタックを構成する方法を学習
-* モジュール型テンプレートの再利用方法についての概念を学習
-
-
-
-### ラボを開始
-
-このラボでは、AWS クラウドで実行される簡単な Web アプリケーションのためのインフラストラクチャを作成します。
-
-* 特定のリージョン (例: us-east-1) の 2 つの[アベイラビリティーゾーン](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) に 2 つのパブリックサブネットと 2 つのプライベートサブネットが存在する [Amazon Virtual Private Cloud](https://aws.amazon.com/jp/vpc/) (Amazon VPC)を作成します。
-
-* 最低 2 つの [Amazon Elastic Compute Cloud](https://aws.amazon.com/jp/ec2/) (Amazon EC2) インスタンス、最大 4 つの [Auto Scaling グループ](https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/auto-scaling-groups.html) を作成します。インスタンスを 2 つのプライベートサブネットで起動し、簡単な Web アプリケーションを実行します。
-* インターネット向けエンドポイントを持つ [Application Load Balancer](https://aws.amazon.com/jp/elasticloadbalancing/application-load-balancer/) を作成します。このロードバランサーは EC2 インスタンスの前に配置されます。
-* [Amazon Route 53](https://aws.amazon.com/jp/route53/) [ホストゾーン](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/hosted-zones-working-with.html) が 1 つあり、そこにロードバランサーを指す [エイリアス](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html) レコードを保存します。このサンプルラボの実行中にドメイン名を登録する必要はありません。[プライベートホストゾーン](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/hosted-zones-private.html) を作成して、ホストゾーンが関連付けられた VPC で起動した EC2 インスタンスなどのコンピュートリソースからサンプルアプリケーションに HTTP リクエストを送信できるようにします。そのためには、[AWS Cloud9](https://aws.amazon.com/jp/cloud9/) 環境 (このラボの一部を実行するために使用) を作成し、デプロイするアプリケーションに HTTP リクエストを送信します。
-
-デプロイを始める前に、これから構築するアプリケーションについて考えてみましょう。特に、*ジョブロール*について考えてみてください。例えば、ある会社では、セキュリティ、ネットワーク、アプリケーション、データベースなどに関連する機能を所有するさまざまなチームがあります。すべての機能を 1 つのチームが所有することになったとしても、各テンプレートの各機能をその機能に特化した個人のグループが所有し、マッピングできるようにテンプレートを設計するのがベストプラクティスです。これは、トラブルシューティングや再利用が容易な小さなテンプレートを用意する場合にも役立ちます。このようなテンプレートは、必要に応じてさらに小さなテンプレートに分割できます。また、情報を保持するリソース (データベースなど) と、そのデータを消費するリソース (サーバー群など) を別々のスタックにまとめることも検討できます。これにより、関連するリソースを管理するデータベースチームなど、専任のリソース所有者をマッピングするのに役立つだけでなく、時間の経過に伴うトラブルシューティングやリソースの維持も容易になります。例えば、データベースとアプリケーションスタック全体を同じテンプレートに記述する場合、次に作成するスタックで問題が発生した場合、問題の性質によっては、最悪、スタックを削除して新しいスタックを作成する必要があります。影響範囲を絞り込むだけでなく、別のテンプレートを使用してデータベースを記述すると、後でテンプレートを再利用する可能性も高くなります。
-
-では、これから構築するインフラストラクチャを見てみましょう。次のステップに進む前に、このインフラストラクチャをライフサイクルと所有権別に設計するための出発点について考えます。どのように検討を進めますか?
-
-
-
-最初は、次に説明する手順を使用します。後続の各スタックで表現するリソースは、前のスタックで作成するリソースに依存している場合があることに注意してください。
-
-* VPC 関連リソース用の 1 つのテンプレート
-* ホストゾーン用の 1 つのテンプレート
-* アプリケーションとロードバランサーのセキュリティグループ用の 1 つのテンプレート
-* ロードバランサー、EC2 インスタンス、前のテンプレートで作成したホストゾーンに追加する DNS レコードを含む、アプリケーションスタック用の 1 つのテンプレート
-
-また、別のテンプレートを使用して Cloud9 環境を記述します (上の図には示されていません)。
-
-前述の戦略では、所有権 (VPC 関連リソースを所有するネットワークチーム、セキュリティグループのリソースを所有するセキュリティチーム、インフラストラクチャとアプリケーションのデプロイを所有するアプリケーションチーム) を考慮しただけでなく、ライフサイクルも考慮してテンプレートを設計しました。例として、アプリケーションの新しいバージョンをロールアウトする必要があり、それをカットオーバーするための新しいアプリケーションスタックを作成したい場合、アプリケーションインフラストラクチャの依存関係を記述する他のすべての既存のスタックを(必要でない限り)必ずしも再デプロイ、または、更新する必要はありません。
-
-::alert[上のサンプルインフラストラクチャの一部としてデータベースを作成する場合、それを別のテンプレートで記述することも検討できます。また、同じテンプレート内のアプリケーションセキュリティグループから ingress/egress ルールを参照するために、アプリケーションスタックのセキュリティグループと同じテンプレートに、そのセキュリティグループを記述することも選択可能です。その場合、データベース用のセキュリティグループの情報をエクスポートし、データベースを作成するスタックで使用します。]{type="info"}
-
-
-
-### 前提条件
-
-このラボでは後で Cloud9 を使用しますが、最初はワークステーションで作業します。まず、CloudFormation Workshop コードリポジトリのコンテンツをワークステーションに取り込みます。そのためには、次の 2 つのオプションから選択できます。
-
-- オプション 1 (簡単、ワークステーションにツールをインストールする必要がない): [GitHub の CloudFormation Workshop リポジトリページ](https://github.com/aws-samples/cfn101-workshop) を開き、 **Code** ボタンを探して、ドロップダウンメニューから **Download ZIP** を選択します。このアクションにより、リポジトリの `main` ブランチにあるワークショップの内容を含む `cfn101-workshop-main.zip` ファイルが作成されます。このファイルをダウンロードしてワークステーションの任意のディレクトリに展開します。
-- オプション 2: [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) を使用して CloudFormation Workshop リポジトリのクローンを作成します。そのためには、ワークステーションに `git` がインストールされていることを確認するか、任意の方法でインストールしてください。準備ができたら、[ローカル開発の設定](/prerequisites/local-development) の **git を使ってラボのリソースをクローン** セクションに従って、ラボリポジトリをクローンしてください。これにより、リポジトリがワークステーションの `cfn101-workshop` ディレクトリにクローンされます。
-
-
-次に、ZIP ファイルから展開した、またはクローンしたリポジトリの `cfn101-workshop/code/workspace/architecting-templates` ディレクトリを開きます。`base-network.template` ファイルと `cloud9.template` ファイルを見つけます。まず、これらを使用してベースインフラストラクチャと Cloud9 環境をそれぞれ作成します。
-
-### VPC スタックの作成
-
-さあ、始めましょう! CloudFormation を使用してインフラストラクチャを表現するときに、このラボで使用するサンプルテンプレートが一連の依存関係とどのように結び付けられているかを見てみましょう。これらの依存関係は、あるスタックにエクスポートされ、別のスタックにインポートされます。
-
-`base-network.template` ファイルを使用して新しいスタックを作成します。
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. ページ上部のリージョンセレクターから、*バージニア北部* (`us-east-1`) などのリージョンを選択します。
-1. **スタックの作成** から、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートの準備** セクションで、 **テンプレート準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。前述の `base-network.template` ファイルを選択し、 **次へ** をクリックします。
-1. スタック名を指定します。例えば、`cloudformation-workshop-dev-base-network` と入力します。デフォルトのパラメータ値のまま、 **次へ** をクリックします。
-1. 次のページで、 **次へ** をクリックします。
-1. 次のページで、 **送信** をクリックします。
-
-スタックの作成が開始されます。最後に、スタックのステータスが `CREATE_COMPLETE` になります。スタックの作成が進むにつれて、ワークステーションの任意のテキストエディタで `base-network.template` ファイルを開きます。次の点を確認してください。
-
-* リージョン内の別々のアベイラビリティーゾーン (例えば、`us-east-1` リージョンの `us-east-1a`、`us-east-1b` アベイラビリティーゾーン) にサブネットを作成する場合は、各サブネットで `AvailabilityZone` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html) を指定します。サンプルテンプレートでは、アベイラビリティーゾーン名 (`us-east-1a` など) をハードコーディングする代わりに、`Fn::Sub` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) を使用します (テンプレートでは YAML の短縮形 `!sub`) を使用して、リージョンの名前 (例: `AWS::Region` [疑似パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html#cfn-pseudo-param-region) の `us-east-1`) を `a` または `b` のいずれかと連結します。例えば、`AvailabilityZone: !Sub '${AWS::Region}a'` と記述します。連結し、テンプレートの移植性を高めることで、このテンプレートをリージョン間で再利用しやすくできます。
-* テンプレートの `Outputs` セクションで、[エクスポート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) したいリソースの値を書き留めて、次に作成するスタックでそれらの値を使用できるようにします。特定の名前でエクスポートを作成すると、その名前を参照してエクスポートの値を別のスタックで使用できます。各エクスポートは、アカウントやリージョンごとに一意でなければなりません。サンプルテンプレートでは、各エクスポートの名前にはプレフィックスとしてスタック名が含まれています(前述のように、`AWS::StackName` 疑似パラメータが `Fn::Sub` と共に使用されていることに注意してください)。スタック名は特定のアカウントとリージョンでも一意でなければならないため、最初にプレフィックスとしてスタック名を選択するのが妥当な選択です。もちろん、選択するサフィックスとプレフィックスを組み合わせると、アカウントやリージョン内でも一意のエクスポート名になることを確認する必要があります。最終的には、選択したエクスポート名が一意で、使いやすく、同じ命名規則で後続のスタックで派生しやすい形になっていることが重要です。
-
-
-
-### Cloud9 環境の作成
-
-次に、Cloud9 環境を作成します。これを 2 つの目的で使用します。1 つは、このラボ用のインフラストラクチャのデプロイを継続すること、もう 1 つは VPC の範囲内で DNS 設定を検証することです。Cloud9 環境をデプロイする前に、環境そのものを記述するテンプレートでどのようにエクスポートを実行するかを見てみましょう。お好みのテキストエディタで `cloud9.template` ファイルを開き、`AWS::Cloud9::EnvironmentEC2` リソースタイプの `SubnetId` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cloud9-environmentec2.html#cfn-cloud9-environmentec2-subnetid) の値を書き留めておきます。Cloud9 環境の EC2 インスタンスを使用して前述のプライベートホストゾーンの DNS レコードの名前解決をテストするには、プライベートホストゾーン自体に関連付けるのと同じ VPC に属するサブネットでインスタンスを起動します。このラボでは、先ほど作成した最初のパブリックサブネットを指定します。サブネットを指定するには、サブネット ID を含むエクスポート名を参照します。この例では、最初に、エクスポートしたスタック名 (このスタック名を `cloud9.template` に入力パラメータとして渡します)を、 VPC スタックで選択したサフィックス (`Fn::Sub: ${NetworkStackName}-PublicSubnet1Id`) に連結し、最初のパブリックサブネットのエクスポート名を作成します。エクスポートの合成名を使用して、その値を `Fn::ImportValue` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) で利用します。なお、サンプルテンプレートには、YAML の短縮形で示されています。クロススタック参照の詳細については、この [ページ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) の `Fn::ImportValue` の **Note** セクションをご参照ください。
-
-Cloud9 の環境を作ってみましょう! [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) を使用します。
-
-1. 先ほど選択したリージョンと同一のリージョン (*バージニア北部* (`us-east-1`)など) であることを確認してください。
-1. **スタックの作成** から、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートの準備** セクションで、 **テンプレート準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。`cloud9.template` ファイルを選択し、 **次へ** をクリックします。
-1. スタック名を指定します。例えば、`cloudformation-workshop-dev-cloud9` と入力します。デフォルトのパラメータ値のまま、 **次へ** をクリックします。
-1. 次のページで、 **次へ** をクリックします。
-1. 次のページで、 **送信** をクリックします。
-1. スタックのステータスが `CREATE_COMPLETE` になるまで、スタックの作成ページを更新します。名前のプレフィックスが `aws-cloud9-aws-cloudformation-workshop-` となっている別のスタックも作成されることに注意してください。このスタックは、Cloud9 環境のセキュリティグループと EC2 インスタンスを作成します。
-1. 準備ができたら、Cloud9 環境を開きます。[AWS Cloud9 コンソール](https://console.aws.amazon.com/cloud9/home) に移動し、`aws-cloudformation-workshop` 環境を見つけて、 **Open IDE** を選択します。これで、環境が別のウィンドウで開かれるはずです。
-
-
-
-### `cfn-lint` のインストール
-
-ソフトウェア開発ライフサイクル (SDLC) の一環として、*フィードバックループを短縮して時間を節約* するために、コード開発中に問題の発見と修正を開始するには、早期テストが鍵となります。CloudFormation を使用する際のベストプラクティスの一環として、テンプレートが有効な JSON または YAML データ構造を使用しているだけでなく、[AWS CloudFormation リソース仕様](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html) にも準拠していることを検証する必要があります 。早期にテストを実施することで、例えば、間違ったリソースプロパティ名や値を指定した場合、ワークステーションでテンプレートを作成するときに、SDLC の非常に早い段階で誤りを発見できます。
-
-テンプレートを検証するには、[AWS CloudFormation Linter](https://github.com/aws-cloudformation/cfn-lint) を使用します。Cloud9 環境のページの下部にあるコマンドラインターミナルを利用し、次に示すように、`virtualenv` を使用して Python 用の新しい仮想環境を作成し、アクティブ化します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mkdir ~/my-virtual-environments
-virtualenv ~/my-virtual-environments/cloudformation-workshop-venv
-source ~/my-virtual-environments/cloudformation-workshop-venv/bin/activate
-:::
-
-上記の最後のコマンドで、作成した仮想環境がアクティブになっているはずです。シェルプロンプトに `(cloudformation-workshop-venv)` というプレフィックスが付加されているはずです。次に、次のコマンドを実行して、現在のターミナルの仮想環境スコープに `cfn-lint` をインストールします。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install cfn-lint
-:::
-
-::alert[Cloud9 の現在のターミナルを閉じてから新しいターミナルを再度開く場合は、`source ~/my-virtual-environments/cloudformation-workshop-venv/bin/activate` コマンドをもう一度実行して、以前に作成した仮想環境を新しいターミナルでアクティブ化してください。]{type="info"}
-
-インフラストラクチャをデプロイし続ける中で、`cfn-lint` を使用する例を後で説明します。このワークショップでの CloudFormation テストツールの詳細については、[リンティングとテスト](/basics/templates/linting-and-testing) ラボをご参照ください。`cfn-lint` をワークステーションで任意の [サポートされているエディタ](https://github.com/aws-cloudformation/cfn-lint#editor-plugins) のプラグインとしても実行可能です。あなたのプロジェクトにて、`cfn-lint` を `pre-commit` [フック](https://github.com/aws-cloudformation/cfn-lint#pre-commit) として実行することもできます。
-
-::alert[フェイルファスト戦略や使用している SDLC プロセスの一環として、コードで記述したインフラストラクチャが、会社が必要としている統制に準拠していることを確認するためのコンプライアンス検証チェックも含める必要があります。一例として、CloudFormation のツールや機能には [AWS CloudFormation Guard](https://docs.aws.amazon.com/ja_jp/cfn-guard/latest/ug/what-is-guard.html) と [AWS CloudFormation Hooks](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/hooks.html) がありますが、このラボでは説明しません。CloudFormation ワークショップの、[Policy-as-Code with Guard](/mediate/templates/policy-as-code-with-guard) ラボを試してみてください。]{type="info"}
-
-
-
-### Cloud9 環境からのデプロイの継続
-
-リソースのデプロイを続行します。今回は、[AWS Command Line Interface](https://aws.amazon.com/jp/cli/) (AWS CLI) を使用してスタックを作成します。AWS CLI は既に Cloud9 に含まれています。今後の参考として、ご自身のワークステーションにインストールする方法の詳細については、[AWS CLI 入門ガイド](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-getting-started.html) をご参照ください。
-
-インフラストラクチャのデプロイを続けるには、まずこのラボのリポジトリを Cloud9 環境にクローンする必要があります。次に示すように、必ず `~/environment` ディレクトリ内から以下のコマンドを実行してください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd ~/environment
-git clone https://github.com/aws-samples/cfn101-workshop.git
-:::
-
-次に、ディレクトリを `cfn101-workshop/code/workspace/architecting-templates/` に変更します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/architecting-templates/
-:::
-
-
-
-### cfn-lint を実行
-
-`architecting-templates` ディレクトリのテンプレートファイルに対して `cfn-lint` を実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-lint *.template
-:::
-
-上記のコマンドの出力は表示されないはずです。つまり、エラーがないということを示しています。このコマンドを実行することで、テンプレートが前述のリソースタイプの仕様に準拠していることを確認できました。このラボでは、テンプレートアーキテクチャの例を示すことと、ワークスペースを準備するという 2 つの理由のために、VPC と Cloud9 環境のリソースをデプロイしました。ベストプラクティスの一環として、リソースをデプロイしたり、テンプレートをリポジトリに追加したりする前に `cfn-lint` を実行して、プロセスの早い段階で変更を加えます。
-
-`cfn-lint` の機能の例を説明するために、Cloud9 の左側にある *Environment* ナビゲーションタブを使用して `aws-cloudformation-workshop -> cfn101-workshop-> code -> workspace -> architecting-templates` ディレクトリの `hosted-zone.template` ファイルを開きます。 `Name: !Ref 'HostedZoneName'` の行を、一時的に `Names: !Ref 'HostedZoneName'` に変更します (`Name` プロパティを一時的に `Names` に変更します)。次に、先ほど行ったように `cfn-lint` を実行すると、次のようなエラーが表示されるはずです。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-E3002 Invalid Property Resources/HostedZone/Properties/Names
-:::
-
-ここで `cfn-lint` は、指定したプロパティが、[論理 ID](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) が `HostedZone` のリソースに対して有効ではないことを示しています。ご覧のとおり、早めにチェックして、リンティングの観点からテンプレートを検証する機会があります。
-
-::alert[ホストゾーンを作成する前に、忘れずに `Names` を `Name` に戻してください。]{type="warning"}
-
-
-
-### ホストゾーンの作成
-
-Cloud9 で `hosted-zone.template` ファイルを開きます。次の点をご確認ください。
-
-* このラボでは、これから作成するホストゾーンを VPC に関連付けます。VPC の ID を参照する `AWS::Route53::HostedZone` リソースタイプの設定を見ると、このサンプルテンプレートがどのように実装されているかがわかります。そのためには、まずエクスポート名を `Fn::Sub: ${NetworkStackName}-VpcId` で構成し、次に `!ImportValue` 宣言でエクスポート値を利用します。
-* ホストゾーンを作成したら、ホストゾーン情報を利用するアプリケーションスタックを作成します。アプリケーションスタックには、同じスタックで作成するロードバランサーを指す DNS エイリアスレコードを記述し、このレコードの保存場所を知る必要があります。`hosted-zone.template` ファイルでは、ホストゾーンの ID と名前を `Outputs` セクションにエクスポートして、この情報を後でアプリケーションスタックで使用できるようにします。
-
-このテンプレートで表現されているビジネスロジックを理解できたので、次はホストゾーンを作成します。 この作業の実行には、Cloud9 環境に既にインストールされている AWS CLI を使用します。まず、`hosted-zone.template` ファイルと `us-east-1` リージョンに `cloudformation-workshop-dev-hosted-zone` という名前の新しいスタックを作成します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name cloudformation-workshop-dev-hosted-zone \
- --template-body file://hosted-zone.template \
- --region us-east-1
-:::
-
-このコマンドを実行することで、次の抜粋のような出力が得られます。
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-{
- "StackId": "arn:aws:cloudformation: [...]"
-}
-:::
-
-次のコマンドを使用してスタックの作成が完了するのを待ちます (または、CloudFormation コンソールに移動して、スタックのステータスが `CREATE_COMPLETE` になるまで待ちます)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --stack-name cloudformation-workshop-dev-hosted-zone \
- --region us-east-1
-:::
-
-スタックの作成が完了すると、Route 53 のプライベートホストゾーンが作成されます。スタックの作成に使用したデフォルトのテンプレートパラメータを見てください。ホストゾーンの名前は `my-example-domain.com` です。[Route 53 Console](https://console.aws.amazon.com/route53/home) に移動し、 **ホストゾーン** から、作成したホストゾーンを選択すると、詳細ページに `NS` と `SOA` の 2 つの DNS レコードタイプが既にあることがわかります。後で CloudFormation を使用してロードバランサー用のエイリアスレコードを作成します。そのレコードも詳細ページに表示されるはずです。
-
-
-
-### セキュリティグループの作成
-
-Cloud9 で `security-groups.template` ファイルを開きます。このサンプルテンプレートでは、2 つのセキュリティグループについて表現しています。1 つは作成するロードバランサー用、もう 1 つはサンプル Web アプリケーションを実行する EC2 インスタンス用です。どちらのセキュリティグループも、前に見たのと同じ方法で VPC ID を利用することに注意してください。また、セキュリティグループ ID が `Outputs` セクションでエクスポートされ、後でアプリケーションスタックから使用可能としている点にも注目します。
-
-`cloudformation-workshop-dev-security-groups` という名前の新しいスタックでセキュリティグループを作成します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name cloudformation-workshop-dev-security-groups \
- --template-body file://security-groups.template \
- --region us-east-1
-:::
-
-コマンド実行後は、作成が完了するのを待ちます。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --stack-name cloudformation-workshop-dev-security-groups \
- --region us-east-1
-:::
-
-
-
-### アプリケーションスタックの作成
-
-Cloud9 で `application.template` ファイルを開きます。このテンプレートでは、アプリケーションロードバランサーと EC2 インスタンスの Auto Scaling グループを使用して、アプリケーションをデプロイする方法を説明します。次の点に注意してください。
-
-
-* このラボで簡単にテストできるように、ロードバランサーの HTTP リスナーを使用します。
-* Auto Scaling グループ [リソース](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-as-group.html) は `LaunchTemplate` [リソース](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-launchtemplate.html) を使用して各インスタンスをブートストラップします。特に、 `LaunchTemplateData` の下にある `UserData` プロパティ内から、最初に `yum update -y aws-cfn-bootstrap` を使用して各インスタンスで [CloudFormation ヘルパースクリプト](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-helper-scripts-reference.html) がどのようにセットアップされて、次に、`cfn-init` [ヘルパースクリプト](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-init.html) がパッケージ (`httpd` など) インストールとコンテンツの設定にどのように使用されるかがわかります: 例として、デフォルト値が `Hello world!` となっているサンプルテンプレートパラメータから参照されている `/var/www/html/index.html` Web アプリケーションファイルの値に注目してください。
-* `UserData` セクションの `cfn-signal` [ヘルパースクリプト](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-signal.html) は、インスタンスの作成や更新が成功したかどうかを CloudFormation に伝えるよう設定されています。さらに、`cfn-hup` [ヘルパー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-hup.html) は、スタックの更新時に `Metadata` の変化を検出するように設定されています (この例では、検出の `interval` はデフォルト値の `15` の代わりに 2 分ごとにチェックするように設定されていることに注意してください)。必要に応じて変更を適用します。
-* Auto Scaling グループは、`Timeout` を 15 分に設定した CreationPolicy [属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-creationpolicy.html) を使用して、その間に少なくとも 2 つの `Count` シグナル (2 つのインスタンスのそれぞれから 1 つ) を受信して、インスタンスのブートストラップが成功しました。このような信号が 15 分以内に受信されない場合、スタックはロールバックされます。
-* Auto Scaling グループは、`UpdatePolicy` [属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html) と `autoScalingRollingUpdate` [ポリシー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html#cfn-attributes-updatepolicy-rollingupdate) も使用しています。 スタックを更新し、関連するリソースの更新がトリガーされると、ポリシーは `MaxBatchSize` で指定されたとおりに一度に 1 つのインスタンスを更新し、最低 2 つのインスタンスをサービス状態のままにします (`MinInstanceInService` を参照)。さらに、`PauseTime` と `WaitOnResourceSignals` を組み合わせると、追加または置換されたインスタンスから正常にシグナルを受信するまで、Auto Scaling グループが 15 分間 (`PT15M`) 待つように CloudFormation に指示します。
-
-アプリケーションとそのインフラストラクチャを、`cloudformation-workshop-dev-application` という新しいスタックでデプロイします。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name cloudformation-workshop-dev-application \
- --template-body file://application.template \
- --region us-east-1
-:::
-
-そして、作成が完了するのを待ってください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --stack-name cloudformation-workshop-dev-application \
- --region us-east-1
-:::
-
-デプロイの最後には、エイリアスの Route 53 レコードを含む、アプリケーションを作成したスタックが用意されているはずです。次に、このラボで意図したとおりにデプロイされていること検証します。
-
-
-
-### デプロイメントの検証
-
-次の方法で二段階認証を行います。
-
-* ロードバランサーの URL に接続し、HTTP レスポンスで得られるコンテンツを検証することが、このラボの例の一部として実装されています。
-* エイリアスレコードを使用する URL に HTTP リクエストを発行し、HTTP 応答が前のステップで取得したものと同じであることを確認します。
-
-
-
-#### ロードバランサーの URL に接続して検証
-
-CloudFormation コンソールから、`cloudformation-workshop-dev-application` スタックを選択し、`出力`タブを選択します。ブラウザの新しいタブで、`AppUrl` 出力値のリンクを開きます。出力 `Hello world!` が表示されています。
-
-
-
-#### DNS レコード値の URL に接続して検証
-
-Cloud9 で `application.template` ファイルを開き、`AWS::Route53::RecordSet` タイプのリソースを探します。このリソースは、プライベートホストゾーンに `A` 型のエイリアスレコードを作成します (`${HostedZoneStackName}-HostedZoneId` のエクスポートを用いて、`HostedZoneId` を参照します)。`Name` エイリアスレコードの値は `my-example-domain.com` という名前のエントリで、この例ではドメインの Zone Apex と同一です。
-
-このラボでは (代わりにパブリックホストゾーンを指すドメインを登録する代わりに) プライベートホストゾーンを作成したので、VPC のコンテキスト内から上記のエイリアスレコードを解決できるはずです。つまり、VPC で EC2 インスタンスを作成した Cloud9 環境は、名前解決を正常に実行できるはずです。Cloud9 のコンソールターミナルから、以下のコマンドを実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-curl http://my-example-domain.com
-:::
-
-`Hello world!` は、先ほど見たものと同じ出力です。
-
-おめでとうございます! CloudFormation を使用してサンプルアプリケーションとそのインフラストラクチャのデプロイを正常に実行し、検証することができました。
-
-
-
-### チャレンジ
-
-この課題では、再利用とモジュール性に関連する主要な概念を思い出して適用し、それらをデプロイメントのオーケストレーションの観点から拡張します。あなたは、(Cloud9 のワークスペースにある)`application.template` ファイルを `application-blue-green.template` という名前の新しいファイルにコピーし、この新しいファイルを更新して、blue / green のデプロイパターンのコンテキストで 2 つのスタックで使用できるようにします。[Amazon Route 53 DNS ルーティングの更新](https://docs.aws.amazon.com/ja_jp/whitepapers/latest/blue-green-deployments/update-dns-routing-with-amazon-route-53.html)をご参照ください。このチャレンジの要件は次の通りでです。
-
-* 2 つのスタックを用意します。作成した既存の `cloudformation-workshop-dev-application` を更新し、`cloudformation-workshop-dev-application-v2` という名前の新しいスタックを作成して、それぞれ `Hello world!` の代わりに `Blue` と `Green` を出力として表示します。両方のスタックをそれぞれ *Blue* と *Green* と呼び、両方のスタックに新しい `application-blue-green.template` ファイルを使用します。
-* 各スタックは、前に使用したものと同じ `名前` (ホストゾーン名) を持つ新しいエイリアスレコードを作成する必要があります。ただし、これらのレコードは両方とも [加重セット](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/resource-record-sets-values-weighted.html#rrsets-values-weighted-weight) である必要があります。これにより、Route 53 は、[特定のリソースの合計に対する重みの比率](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/routing-policy-weighted.html) に基づいてユーザーが発行したクエリに応答します。最初に、 *Blue* スタックに重み `255` (大きい重み) を割り当て、*Green* スタックに重み `1` (少ない重み) を割り当てます。この方法では、*Blue* は最初にトラフィックの 255 / 256、*Green* はトラフィックの 1 / 256 に割り当てられます。
-* 必ず、テンプレート内の _set identifier_ を更新し、同じテンプレートを使用する 2 つのスタックで値が一意となるようにします。
-
-このラボの例で望ましい状態を示す図を以下に示します。
-
-
-
-`AWS::Route53::RecordSet` リソースタイプの CloudFormation ドキュメント [ページ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html) を参照して、上記の要件を満たすために追加または更新するプロパティを特定してください。
-
-2 つのスタックを作成したら、`my-example-domain.com` エイリアスが最初はほとんどが *Blue* を指していることを `curl` で検証します。次に、両方のスタックで作成したエイリアスレコードのウェイト値を反転させて、もう一度テストすると、ほとんどのトラフィックが *Green* にルーティングされます(つまり、出力が `Green` のサンプルアプリのバージョン 2 をロードします)。
-
-
-
-:::expand{header= "ヒントが必要ですか?"}
-
-* サンプルの `PageTextContent` テンプレートパラメータを再利用し、新しい値を追加して、テンプレートを使用する特定のスタックでの `Blue` または `Green` の実行を実証および検証できるようにする方法をご検討ください。
-* `SetIdentifier` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html#cfn-route53-recordset-setidentifier) をご参照ください。*Blue* スタックを起動するか、*Green* スタックを起動するかに応じて、このプロパティに一意の値を指定します。
-* `Weight` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html#cfn-route53-recordset-weight) をご参照ください。
-* 更新したレコードセットで `Region` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html#cfn-route53-recordset-region) を指定する必要はありません。
-:::
-
-
-
-::::expand{header= "解決策を確認しますか?"}
-
-解決策は、`code/solutions/architecting-templates` ディレクトリにある `application-blue-green.template` ファイルにあります。
-
-代わりに、`application-blue-green.template` ファイルを参照しつつ、以下の手順に従ってあなたのワークスペースを更新してください。
-
-* `AllowedValues` を `PageTextContent` サンプル入力パラメータ (`-Blue`、`-Green`) を、インデントに注意し、2 行に分けて追加します。
-* 新しいテンプレートパラメータ `RecordSetWeight` を追加します。`Type` を `Number` に、`Default` の値を `0` に、`MinValue` を `0` に、`MaxValue` を `255` に設定します。 パラメータの目的をユーザに伝えるための `Decription` を追加します。
-* セット識別子を、ホストゾーンの両方のレコードで一意となる値に更新します。次の例のように、レコードセットの `SetIdentifier` プロパティを更新します。例: `SetIdentifier: !Sub '${AppNameTagValue} application managed with the ${AWS::StackName} stack.'`
-* `AWS::Route53::RecordSet` リソースタイプに `Weight` プロパティを追加して、`RecordsetWeight` テンプレートパラメータを参照します: `Weight: !Ref 'RecordSetWeight'`。
-* レコードセットリソースから `Region: !Ref 'AWS::Region'` 行を削除します。
-* 既存のスタック `cloudformation-workshop-dev-application` を、新しい application-blue-green.template ファイルで更新します。`Blue` を `PageTextContent` のパラメータ値として、`255` を `RecordSetWeight `に渡します。例:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
- --stack-name cloudformation-workshop-dev-application \
- --template-body file://application-blue-green.template \
- --parameters \
- ParameterKey=PageTextContent,ParameterValue=Blue \
- ParameterKey=RecordSetWeight,ParameterValue=255
-:::
-
-* `cloudformation-workshop-dev-application-v2` という名前の新しいスタックを作成し、そこに `Green` を `PageTextContent` のパラメータ値として、`1` を `RecordSetWeight `に渡します。例:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name cloudformation-workshop-dev-application-v2 \
- --template-body file://application-blue-green.template \
- --parameters \
- ParameterKey=PageTextContent,ParameterValue=Green \
- ParameterKey=RecordSetWeight,ParameterValue=1
-:::
-
-* 両方の操作が完了したら、`my-example-domain.com` レコードが主に `Blue` を指していることをテストします。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-curl http://my-example-domain.com
-:::
-
-* 次に、両方のスタックを更新し、`RecordSetWeight` の値を入れ替えます。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
- --stack-name cloudformation-workshop-dev-application \
- --template-body file://application-blue-green.template \
- --parameters \
- ParameterKey=PageTextContent,ParameterValue=Blue \
- ParameterKey=RecordSetWeight,ParameterValue=1
-
-aws cloudformation update-stack \
- --stack-name cloudformation-workshop-dev-application-v2 \
- --template-body file://application-blue-green.template \
- --parameters \
- ParameterKey=PageTextContent,ParameterValue=Green \
- ParameterKey=RecordSetWeight,ParameterValue=255
-:::
-
-* スタックの更新が完了したら、`my-example-domain.com` レコードが主に `Green` を指していることをテストします。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-curl http://my-example-domain.com
-:::
-
-::::
-
-
-
-### クリーンアップ
-
-ワークステーションの CloudFormation コンソールに移動します。このラボで作成したスタックを次の順序で削除します。クロススタック参照を使用していくつかのスタックを参照しているため、値をエクスポートするスタックが利用側スタックで使用されている場合は削除できない点に注意してください。
-
-1. `cloudformation-workshop-dev-application-v2` と `cloudformation-workshop-dev-application` は互いに依存していないため、それぞれが削除されるのを待たずに削除可能です。両方のスタックが削除されたら、次のステップに進みます。
-1. `cloudformation-workshop-dev-security-groups` と `cloudformation-workshop-dev-hosted-zone` は、それぞれが削除されるのを待たずに削除可能です。次のステップに進みます。
-1. `cloudformation-workshop-dev-cloud9` を削除します。このスタックを削除すると、開始した削除アクションによって、名前が `aws-cloud9-aws-cloudformation-workshop-` で始まるスタックも削除されます。両方のスタックが削除されたら、最後のステップに進みます。
-1. `cloudformation-workshop-dev-base-network` スタックを削除します。
-
-
-### まとめ
-
-おめでとうございます! ライフサイクルと所有権を考慮したテンプレートの設計方法と、再利用性とモジュール性を優先して多数の擬似パラメータと組み込み関数を使用する方法を学び、実践しました。また、値をエクスポートおよびインポートしてスタックを作成する方法や、Blue / Green デプロイパターンを例にしてテンプレートを再利用する方法についても学びました。
diff --git a/content/intermediate/templates/architecting-templates/index.md b/content/intermediate/templates/architecting-templates/index.md
deleted file mode 100644
index 50478fff2..000000000
--- a/content/intermediate/templates/architecting-templates/index.md
+++ /dev/null
@@ -1,400 +0,0 @@
----
-title: "Architecting your templates"
-weight: 650
----
-
-### Overview
-
-When you describe your infrastructure with code, you want to take into account the ability to scale as your infrastructure grows, as well as its ongoing maintainability over time. The [AWS CloudFormation best practices](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html) page contains a collection of best practices for you to follow and to adopt in your workflows. In this lab, you will focus on designing your templates by considering _lifecycle and ownership_ aspects for resources you describe with code, as well as _modularity and reuse_ practices, that you will implement in CloudFormation templates by referencing values across stacks within the same account and region, as well as with input parameters for your templates. You can also find other self-paced labs in this workshop that show you examples of best practices, that for example include: [Pseudo parameters](/basics/templates/pseudo-parameters), [Linting and testing](/basics/templates/linting-and-testing), [Dynamic references](/intermediate/templates/dynamic-references) (to reference sensitive information in your AWS CloudFormation templates), [Policy-as-code with Guard](/intermediate/templates/policy-as-code-with-guard) (policy-as-code validation for JSON- and YAML-formatted data).
-
-
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* Learn design patterns that include architecting templates by lifecycle and ownership criteria.
-* Learn how to compose stacks by exporting and consuming values for dependencies.
-* Learn concepts that illustrate how to reuse modular templates.
-
-
-
-### Start Lab
-
-In this lab, you will create an infrastructure that describes an example, simple web application running in the AWS cloud as follows:
-
-* One [Amazon Virtual Private Cloud](https://aws.amazon.com/vpc/) (Amazon VPC), with 2 public and 2 private subnets across 2 [availability zones](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) of a given region, such as the `us-east-1` region.
-* One [Auto Scaling group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-groups.html) with a minimum of 2 [Amazon Elastic Compute Cloud](https://aws.amazon.com/ec2/) (Amazon EC2) instances, and a maximum of 4. You'll launch such instances in the 2 private subnets, and you'll use such instances to run a simple web application.
-* One [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/) with an Internet-facing endpoint; this load balancer will be fronting your EC2 instances.
-* One [Amazon Route 53](https://aws.amazon.com/route53/) [hosted zone](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-working-with.html), where you'll store an [alias](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html) record that points to your load balancer. You will not register a domain name as part of running this example lab: you'll create a [private hosted zone](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-private.html) so that you can make HTTP requests to the sample application from a compute resource - such as an EC2 instance - that you'll launch in the VPC associated with the hosted zone itself. For this, you'll create an [AWS Cloud9](https://aws.amazon.com/cloud9/) environment - that you will use to run parts of this lab - to make HTTP requests to the application you'll deploy.
-
-Before starting the deployment, let's take one step back and think about the application you're going to build. In particular, think about *job roles*. For example, in a company you have different teams owning functions related to security, network, application, database, and so forth. Even if all functions were to be owned by one single team, it is a best practice to architect your templates so that each function for each template can be owned by and mapped to a group of individuals specializing in that function. This also helps with having smaller templates that are easier to troubleshoot, and to reuse; you can further break out such templates into smaller ones as needed. Also, consider organizing resources that persist information - such as a database - and resources that consume that data - for example, a fleet of servers - in separate stacks: not only this helps with potentially mapping dedicate resource owner(s) - such as, a database team maintaining relevant resources - but also makes it easier to troubleshoot and maintain resources over time. If you, for example, describe a database and an entire application stack in the same template, should an issue happen with the stack you'll create next, depending on the nature of the issue you might need - in a worst-case scenario - to delete the stack, and create a new one altogether. Besides narrowing areas of impact, if you describe a database with a separate template this also helps you with potentially reusing the template later on.
-
-Let's take a look at the infrastructure you'll build. Before continuing to next steps, take a moment and think of a reasonable starting point to describe this infrastructure by lifecycle and ownership; how would you do this?
-
-
-
-As a starting point, you'll use steps shown next; note that resources you will describe in each subsequent stack might have dependencies on resources you'll create with the previous one(s):
-
-* One template for your VPC-related resources.
-* One template for your hosted zone.
-* One template for application and load balancer security groups.
-* One template for your application stack, including your load balancer, EC2 instances, and a DNS record to add to the hosted zone you created with a previous template.
-
-You will also use another template to describe your Cloud9 environment (not shown in the diagram above).
-
-With the strategy shown earlier, you have not only designed your templates by taking into account ownership (e.g., a networking team to own the VPC-related resources, a security team to own security group resources, an application team to own the infrastructure and the deployment of their application), but also by lifecycle. As an example, if you need to roll out a new version of the application, and you want to create a new application stack for a cut-over to it, you don't have to necessarily redeploy or update (unless needed) all the other existing stacks that describe application infrastructure dependencies.
-
-::alert[If you would have gotten a database as part of the example infrastructure shown above, you would have chosen to describe it in a separate template as well. Also, you could have chosen to describe its security group in the same template where you also described security groups for the application stack, so that you could have referenced ingress/egress rules for it from the application security group in the same template, in addition to exporting database security group information you would have consumed in a subsequent stack that would have created the database itself.]{type="info"}
-
-
-
-### Prerequisites
-
-You'll use Cloud9 later on for this lab; first, you'll begin with using your workstation. Start with fetching the CloudFormation Workshop code repository content into your workstation: for this, you can choose between two options:
-
-- Option 1 (faster, no tools to install in your workstation): navigate to the [CloudFormation Workshop repository page in GitHub](https://github.com/aws-samples/cfn101-workshop); locate the **Code** button, and choose **Download ZIP** from the dropdown menu. This action should result in a `cfn101-workshop-main.zip` file, containing the content of the workshop in the `main` branch of the repository, that you'll download and expand in your workstation in a directory of your choice.
-- Option 2: use [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) to clone the CloudFormation Workshop repository. For this, make sure that you have `git` installed in your workstation, or install it with a method of your choice. When ready, follow the **Clone lab resources** section in [Get lab resources](/prerequisites/local-development) to clone the lab repository. This will clone the repository into a `cfn101-workshop` directory in your workstation.
-
-
-Next, change directory to the `cfn101-workshop/code/workspace/architecting-templates` directory of the repository that you have either expanded from the ZIP file, or cloned. Locate the `base-network.template` file and the `cloud9.template` file: you'll first use them to create the base infrastructure and your Cloud9 environment respectively.
-
-
-
-### Creating the VPC stack
-
-Let's get started! As you describe your infrastructure with CloudFormation, take a look at how example templates you'll use in this lab are connected together with a series of dependencies, that are exported in one stack and imported into another one(s).
-
-Create a new stack with the `base-network.template` file:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-2. From the region selector on the top of the page, choose a region - such as *N. Virginia* (`us-east-1`).
-3. From **Create stack**, choose **With new resources (standard)**.
-4. From **Prepare template**, choose **Template is ready**.
-5. From **Template source**, choose **Upload a template file**. Choose the `base-network.template` file mentioned earlier, and then choose **Next**.
-6. Specify a stack name: `cloudformation-workshop-dev-base-network`. Choose to accept default parameter values, and then choose **Next**.
-7. On the subsequent page, choose **Next**.
-8. Choose **Create stack** in the next page.
-
-Stack creation will start: at the end of it, you should see your stack in the `CREATE_COMPLETE` status. As the creation of your stack proceeds, open the `base-network.template` file in your favorite text editor in your workstation. Note the following:
-
-* As you want to create your subnets in separate availability zones within a region (for example, `us-east-1a`, `us-east-1b` availability zones in the `us-east-1` region), you specify the `AvailabilityZone` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html) for each subnet. Instead of hard-coding the availability zone name (such as `us-east-1a`), the example template uses the `Fn::Sub` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) (shown in the template using its YAML short form, `!Sub`) to concatenate the name of the region (e.g., `us-east-1`, derived from the `AWS::Region` [pseudo parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html#cfn-pseudo-param-region)) with either `a` or `b`, such as with: `AvailabilityZone: !Sub '${AWS::Region}a'`. This way, it is easier for you to reuse this template across regions by making the template more portable.
-* In the `Outputs` section of the template, note the values of resources that you want to [export](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html), so that you can consume such values in subsequent stack(s) you will create next. You create an export with a given name, so that you can reference that name and consume the export's value in another stack(s). Each export must be unique per account and per region: in the sample template, each export's name contains the stack name as a prefix (note the `AWS::StackName` pseudo parameter being used with `Fn::Sub` as described earlier). As a stack name must be unique in a given account and region as well, the choice of the stack name as a prefix is a reasonable choice to start with. Of course, you want to make sure the suffix you will choose will give you a unique export name within the account and region as well, when you combine it with your prefix. Ultimately, as long as the export name you choose is unique, and easy to consume or to derive in subsequent stacks with a consistent naming convention, that is what matters.
-
-
-
-### Creating your Cloud9 environment
-
-Next, you'll create a Cloud9 environment that you'll use for 2 goals: to continue the deployment of the infrastructure for this lab, and to validate the DNS configuration within your VPC's scope. Before deploying your Cloud9 environment, let's see how you consume an export in the template that describes the environment itself: open the `cloud9.template` file with your favorite text editor, and note the value for the `SubnetId` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloud9-environmentec2.html#cfn-cloud9-environmentec2-subnetid) of the `AWS::Cloud9::EnvironmentEC2` resource type. In order to use your Cloud9 environment's EC2 instance to test the resolution of the DNS record in the private hosted zone as mentioned earlier, you'll launch the instance in a subnet that belongs to the same VPC you'll associate to the private hosted zone itself. In this lab, you choose to specify the first public subnet you created earlier: for this, you'll reference the name of the export whose value holds the ID of the first subnet. The example first composes the name of the export for the first public subnet, by concatenating the name of the stack where you exported the intended value (you'll pass this stack name as an input parameter to `cloud9.template`) to the suffix you chose in the VPC stack: `Fn::Sub: ${NetworkStackName}-PublicSubnet1Id`. With the composed name of the export, you consume its value with the `Fn::ImportValue` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html), that is shown in the example template in its YAML short form. For more information on cross-stack references, see the **Note** section for `Fn::ImportValue` on this [page](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html).
-
-Let's create the Cloud9 environment! You'll use the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/) as you did earlier:
-
-1. Make sure you are in the same region you chose earlier, such as *N. Virginia* (`us-east-1`).
-2. From **Create stack**, choose **With new resources (standard)**.
-3. From **Prepare template**, choose **Template is ready**.
-4. From **Template source**, choose **Upload a template file**. Choose the `cloud9.template` file, and then choose **Next**.
-5. Specify a stack name: `cloudformation-workshop-dev-cloud9`. Choose to accept default parameter values, and choose **Next**.
-6. On the subsequent page, choose **Next**.
-7. Choose **Create stack** in the next page.
-8. Refresh the stack creation page until you see your stack in the `CREATE_COMPLETE` status: note that another stack will be created as well, whose name prefix should read `aws-cloud9-aws-cloudformation-workshop-`: this stack creates the security group and the EC2 instance for your Cloud9 environment.
-9. When ready, open your Cloud9 environment: navigate to the [AWS Cloud9 Console](https://console.aws.amazon.com/cloud9/home), locate the `aws-cloudformation-workshop` environment, and choose **Open IDE**. Your environment should then open in another window.
-
-
-
-### Installing `cfn-lint`
-
-As part of the software development life cycle (SDLC), early testing is key to start to find and correct issues whilst you are developing your code, to *shorten the feedback loop and save time*. As part of best practices when working with CloudFormation, you want to validate that your templates are not only using either a valid JSON or YAML data structure, but that also conform to the [AWS CloudFormation resource specification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html). This way, if you specify an incorrect resource property name or value for example, you have the opportunity to detect this very early in the SDLC, as you develop your templates in your workstation.
-
-To validate your templates, you'll now use the [AWS CloudFormation Linter](https://github.com/aws-cloudformation/cfn-lint): in your Cloud9 environment, locate the command line terminal at the bottom of the page: first, create and activate a new virtual environment for Python with `virtualenv` as shown next:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-mkdir ~/my-virtual-environments
-virtualenv ~/my-virtual-environments/cloudformation-workshop-venv
-source ~/my-virtual-environments/cloudformation-workshop-venv/bin/activate
-:::
-
-The last command above should have activated the virtual environment you created: your shell prompt should indicate so with the `(cloudformation-workshop-venv)` prefix added to it. You'll now install, into your virtual environment scope for your current terminal, `cfn-lint` by running the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install cfn-lint
-:::
-
-::alert[Should you close your current terminal in Cloud9 and then reopen a new one, make sure you run again the command: `source ~/my-virtual-environments/cloudformation-workshop-venv/bin/activate` to activate your previously created virtual environment in your new terminal.]{type="info"}
-
-You'll see an example of using `cfn-lint` later on, as you continue to deploy your infrastructure. For a deeper dive into CloudFormation testing tools with this workshop, see the [Linting and testing](/basics/templates/linting-and-testing) lab. Note that you can also run `cfn-lint` as a plugin for a [supported editor](https://github.com/aws-cloudformation/cfn-lint#editor-plugins) of your choice in your workstation. You can also choose, for your projects, to run `cfn-lint` as a `pre-commit` [hook](https://github.com/aws-cloudformation/cfn-lint#pre-commit).
-
-::alert[As part of a fail-fast strategy and of SDLC processes you use, you also want to include compliance validation checks to verify the infrastructure you describe with code is compliant to controls that your company needs and wants to put in place. As an example, tools and features for CloudFormation include [AWS CloudFormation Guard](https://docs.aws.amazon.com/cfn-guard/latest/ug/what-is-guard.html) and [AWS CloudFormation Hooks](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html) which are not discussed in this lab. As part of this CloudFormation workshop, you can choose try the [Policy-as-code with Guard](/intermediate/templates/policy-as-code-with-guard) lab.]{type="info"}
-
-
-
-### Continuing the deployment from your Cloud9 environment
-
-Continue with the deployment of your resources. This time, you'll use the [AWS Command Line Interface](https://aws.amazon.com/cli/) (AWS CLI) to create your stacks. The AWS CLI is already included with Cloud9: as a future reference, for more information on how to install it in your own workstation, see [Getting started with the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html).
-
-To continue the deployment of your infrastructure, you first want to clone this lab's repository into your Cloud9 environment. Make sure you run the command below from within the `~/environment` directory, as shown next:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd ~/environment
-git clone https://github.com/aws-samples/cfn101-workshop.git
-:::
-
-Next, change directory to `cfn101-workshop/code/workspace/architecting-templates/`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/architecting-templates/
-:::
-
-
-
-### Running cfn-lint
-
-Run `cfn-lint` against template files for this lab you'll find in the `architecting-templates` directory:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-lint *.template
-:::
-
-You should not see any output being emitted by the command above: this means there are no errors. The command verified that your templates conform to the resource type specifications as mentioned earlier. In this lab, you started to deploy resources for your VPC and for your Cloud9 environment directly, to focus on template architecture examples and to prepare your workspace: as part of best practices, you want to run `cfn-lint` before deploying your resources or adding your templates to a repository, so that you have an opportunity to save time and to make changes earlier in the process.
-
-To illustrate an example of `cfn-lint`'s capabilities, use the *Environment* navigation tab on the left side in Cloud9 to expand to the `aws-cloudformation-workshop -> cfn101-workshop-> code -> workspace -> architecting-templates` directory, and open the `hosted-zone.template` file. Locate the `Name: !Ref 'HostedZoneName'` line, and temporarily change it into `Names: !Ref 'HostedZoneName'` (you temporarily changed the `Name` property into `Names`). Next, run `cfn-lint` as you did earlier, and you should see an error similar to the following output excerpt:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-E3002 Invalid Property Resources/HostedZone/Properties/Names
-:::
-
-Here, `cfn-lint` tells you that the property you specified is not valid for the resource whose [logical ID](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) is `HostedZone`. As you can see, you have an early check opportunity to validate your template from a linting perspective.
-
-::alert[Before proceeding to create the hosted zone next, do not forget to change `Names` back to `Name`.]{type="warning"}
-
-
-
-### Creating the hosted zone
-
-Open the `hosted-zone.template` file in Cloud9. Note the following:
-
-* In this lab, you want to associate this hosted zone you are about to create to your VPC: you can see how this example template implements this if you look at the configuration for the `AWS::Route53::HostedZone` resource type, where you reference the ID of your VPC. For this, you first compose the name of the export with `Fn::Sub: ${NetworkStackName}-VpcId`, and then you consume the value of the export with the outer `!ImportValue` declaration.
-* After you create the hosted zone, you will create an application stack that will consume hosted zone information: in the application stack, you will describe a DNS alias record pointing to the load balancer you will create with the same stack, and you will need to know where to store this record. In the `hosted-zone.template` file, you will export the ID and the name of the hosted zone in the `Outputs` section, so that you can consume this information later, in the application stack.
-
-Now that you have familiarized with the business logic described in this template, it's time to create the hosted zone! You'll use the AWS CLI for this, that is already installed in your Cloud9 environment. First, create a new stack called `cloudformation-workshop-dev-hosted-zone` with the `hosted-zone.template` file and in the `us-east-1` region:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name cloudformation-workshop-dev-hosted-zone \
- --template-body file://hosted-zone.template \
- --region us-east-1
-:::
-
-This will result in an output similar to the following excerpt:
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-{
- "StackId": "arn:aws:cloudformation: [...]"
-}
-:::
-
-Wait for the stack creation to complete with the following command (alternatively, navigate to the CloudFormation console, and wait until the stack is in `CREATE_COMPLETE` status):
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --stack-name cloudformation-workshop-dev-hosted-zone \
- --region us-east-1
-:::
-
-At the end of the stack creation, you'll have a Route 53 private hosted zone. Look at default template parameters you used to create the stack: the hosted zone name is called `my-example-domain.com`. Navigate to the [Route 53 Console](https://console.aws.amazon.com/route53/home); from **Hosted zones** choose the hosted zone you created and, in the details page, you'll see there are already two DNS record types, `NS` and `SOA`: later on, you will use CloudFormation to create an alias record for your load balancer, and that record should also show up in this details page.
-
-
-
-### Creating security groups
-
-Open the `security-groups.template` file in Cloud9. This example template describes 2 security groups: one for the load balancer you'll create, and one for EC2 instances running the example web application. Note how both security groups consume the VPC ID in a similar way you've seen earlier. Note also how security group IDs are exported in the `Outputs` section for you to later consume such from the application stack.
-
-Create your security groups with a new stack, called `cloudformation-workshop-dev-security-groups`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name cloudformation-workshop-dev-security-groups \
- --template-body file://security-groups.template \
- --region us-east-1
-:::
-
-and wait for its creation to complete:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --stack-name cloudformation-workshop-dev-security-groups \
- --region us-east-1
-:::
-
-
-
-### Creating the application stack
-
-Open the `application.template` file in Cloud9. This template describes the deployment of your application, by using an application load balancer, and an Auto Scaling group of EC2 instances. Note the following:
-
-
-* For testing easily in this lab, you'll use an HTTP listener for the load balancer.
-* The Auto Scaling group [resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-as-group.html) uses a `LaunchTemplate` [resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-launchtemplate.html) to bootstrap each instance. In particular, from within the `UserData` property underneath `LaunchTemplateData`, you can see how [CloudFormation helper scripts](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-helper-scripts-reference.html) are first set up in each instance with `yum update -y aws-cfn-bootstrap`, and then how the `cfn-init` [helper script](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-init.html) is used to install packages (such as `httpd`), and to set up content: as an example, note the value of the `/var/www/html/index.html` web application file being referenced from a sample template parameter, with a default value of `Hello world!`
-* The `cfn-signal` [helper script](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-signal.html) in the `UserData` section is set up to communicate to CloudFormation whether the instance has been successfully created or updated. Moreover, the `cfn-hup` [helper](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-hup.html) is set up to detect `Metadata` changes as you update the stack (note the detection `interval` is set to check every 2 minutes in this example, instead of the `15` that is the default value), and helps with applying changes as needed.
-* The Auto Scaling group uses a `CreationPolicy` [attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-creationpolicy.html) with a `Timeout` set to 15 minutes, within which to receive at least 2 `Count` signals - one from each of the 2 instances - to determine whether the instance bootstrap succeeded. If such signals are not received within 15 minutes, the stack will roll back.
-* The Auto Scaling group also uses an `UpdatePolicy` [attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html) with an `AutoScalingRollingUpdate` [policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html#cfn-attributes-updatepolicy-rollingupdate): if you update the stack and a relevant resource update is triggered, the policy will update one instance at a time as specified in `MaxBatchSize`, whilst leaving a minimum of 2 instances in service (see `MinInstancesInService`). Moreover, `PauseTime` in conjunction with `WaitOnResourceSignals` tells CloudFormation to wait for 15 minutes (`PT15M`) for the Auto Scaling group to receive successful signals from instances that are either added or replaced.
-
-Deploy the application and its infrastructure with a new stack, called `cloudformation-workshop-dev-application`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name cloudformation-workshop-dev-application \
- --template-body file://application.template \
- --region us-east-1
-:::
-
-and wait for its creation to complete:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
- --stack-name cloudformation-workshop-dev-application \
- --region us-east-1
-:::
-
-At the end of the deployment, you should have a stack that created your application, including an alias Route 53 record: you'll go in more details next, when you'll validate your deployment worked as intended for this lab.
-
-
-
-### Validating your deployment
-
-You'll perform a two-step validation by:
-
-* Connecting to the load balancer URL, and verifying the content you get in an HTTP response is the one intended as part of this lab's examples.
-* Issuing an HTTP request to the URL that uses the alias record, and verifying that the HTTP response is the same to the one you got in the previous step.
-
-
-
-#### Validating by connecting to the load balancer URL
-
-From the CloudFormation Console, choose your `cloudformation-workshop-dev-application` stack, and then choose `Outputs`. Open, in a new tab of your browser, the link you'll find for the `AppUrl` output value: you should see an `Hello world!` output being displayed.
-
-
-
-#### Validating by connecting to the URL with the DNS record value
-
-With the `application.template` file open in Cloud9, locate the resource of type `AWS::Route53::RecordSet`. This resource creates an alias record of type `A` in the private hosted zone (referenced in `HostedZoneId` via the export whose name is derived from `${HostedZoneStackName}-HostedZoneId`). The value for the `Name` alias record is an entry called `my-example-domain.com`, that in this example is the same as the zone apex of the domain.
-
-As you've created a private hosted zone in this lab (in lieu of registering a domain pointing to a public hosted zone instead), you should be able to resolve the alias record above from within the context of your VPC. This means that your Cloud9 environment, whose EC2 instance you created in your VPC, should be able to perform the name resolution successfully. From the console terminal in Cloud9, issue the following command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-curl http://my-example-domain.com
-:::
-
-You should see `Hello world!` as the output, that is the same output you saw earlier.
-
-Congratulations! You have successfully performed and verified the deployment of a sample application and of its infrastructure with CloudFormation!
-
-
-
-### Challenge
-
-In this challenge, you'll recall and apply key concepts related to reuse and modularity, and extend them in terms of deployment orchestration. You are tasked with copying the `application.template` file (that is in your workspace in Cloud9) into a new file called `application-blue-green.template`, and to update this new file so that you can use it for 2 stacks in the context of a blue/green deployment pattern where you'll [Update DNS Routing with Amazon Route 53](https://docs.aws.amazon.com/whitepapers/latest/blue-green-deployments/update-dns-routing-with-amazon-route-53.html). Requirements in this example challenge are as follows:
-
-* Have 2 stacks: update the existing one you created, called `cloudformation-workshop-dev-application`, and create a new one called `cloudformation-workshop-dev-application-v2`, showing `Blue` and `Green` as outputs, respectively, instead of `Hello world!`. Let's refer to both stacks as to *Blue* and *Green*, respectively. Use the new `application-blue-green.template` file for both stacks.
-* Each stack should create a new alias record whose `Name` is the same to the one you used earlier (the hosted zone name). Both of these records though will need to be a [weighted set](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-values-weighted.html#rrsets-values-weighted-weight), so that Route 53 will respond to a query you issue based on the [ratio of the weight for a given resource to the total of weights](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-weighted.html). Initially, you want to assign a weight of `255` (more weight) to the *Blue* stack, and `1` (less weight) to the *Green* stack: this way, *Blue* initially gets 255/256ths of traffic, and *Green* gets 1/256ths of traffic.
-* Make sure you update the _set identifier_ in the template, so that its value will be unique for each of the 2 stacks that will use that same template.
-
-A diagram illustrating the desired state for this lab's example is shown next:
-
-
-
-Reference the CloudFormation documentation [page](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html) for the `AWS::Route53::RecordSet` resource type to identify which properties to add or update to satisfy requirements above.
-
-Once you created the two stacks, validate with `curl` that the `my-example-domain.com` alias points initially mostly to *Blue*. Next, flip weight values for alias records you create in both stacks, so that when you test again most traffic goes mostly to *Green* instead (that is, loads version 2 of your example app whose output reads `Green`).
-
-
-
-:::expand{header="Need a hint?"}
-
-* Look into reusing the example `PageTextContent` template parameter, so that you add new values you can use to demonstrate and validate that you are running either `Blue` or `Green` for a given stack that uses the template.
-* Refer to, and use the `SetIdentifier` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html#cfn-route53-recordset-setidentifier). Choose a way to specify a unique value for this property depending on whether you launch the *Blue* or the *Green* stack.
-* Refer to, and use the `Weight` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html#cfn-route53-recordset-weight).
-* You will not need to specify the `Region` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html#cfn-route53-recordset-region) in your updated record set.
-:::
-
-
-
-::::expand{header="Want to see the solution?"}
-
-The complete solution is available in the `application-blue-green.template` file, that you can find on the `code/solutions/architecting-templates` directory.
-
-Instead, for a step-by-step guide instead, follow the following steps to update your workspace copy of the `application-blue-green.template` file:
-
-* Add the following `AllowedValues` to the `PageTextContent` sample input parameter, in 2 separate lines and by taking care of indentation as needed: `- Blue`, and `- Green`.
-* Add a new template parameter, `RecordSetWeight`. Set its `Type` to `Number`, its `Default` value to `0`, its `MinValue` to `0`, and its `MaxValue` to `255`. Add a `Decription` to tell the user what is the purpose of the parameter.
-* Update the set identifier with a value that will be unique for both records in the hosted zone. Update the `SetIdentifier` property for the record set, as in this example: `SetIdentifier: !Sub '${AppNameTagValue} application managed with the ${AWS::StackName} stack.'`
-* Add the `Weight` property for the `AWS::Route53::RecordSet` resource type, to reference the `RecordSetWeight` template parameter: `Weight: !Ref 'RecordSetWeight'`.
-* Remove the `Region: !Ref 'AWS::Region'` line from the recordset resource.
-* Update the existing stack: `cloudformation-workshop-dev-application`, with the new application-blue-green.template file. Pass `Blue` as a parameter value for `PageTextContent`, and `255` for `RecordSetWeight`. Example:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
- --stack-name cloudformation-workshop-dev-application \
- --template-body file://application-blue-green.template \
- --parameters \
- ParameterKey=PageTextContent,ParameterValue=Blue \
- ParameterKey=RecordSetWeight,ParameterValue=255
-:::
-
-* Create a new stack, called `cloudformation-workshop-dev-application-v2`, to which you pass `Green` as a parameter value for `PageTextContent`, and `1` for `RecordSetWeight`. Example:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
- --stack-name cloudformation-workshop-dev-application-v2 \
- --template-body file://application-blue-green.template \
- --parameters \
- ParameterKey=PageTextContent,ParameterValue=Green \
- ParameterKey=RecordSetWeight,ParameterValue=1
-:::
-
-* Once both operations are complete, test that the `my-example-domain.com` record mainly points to `Blue`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-curl http://my-example-domain.com
-:::
-
-* Next, update both stacks, and swap `RecordSetWeight` values:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
- --stack-name cloudformation-workshop-dev-application \
- --template-body file://application-blue-green.template \
- --parameters \
- ParameterKey=PageTextContent,ParameterValue=Blue \
- ParameterKey=RecordSetWeight,ParameterValue=1
-
-aws cloudformation update-stack \
- --stack-name cloudformation-workshop-dev-application-v2 \
- --template-body file://application-blue-green.template \
- --parameters \
- ParameterKey=PageTextContent,ParameterValue=Green \
- ParameterKey=RecordSetWeight,ParameterValue=255
-:::
-
-* Once stack updates are complete, test that the `my-example-domain.com` record now mainly points to `Green`:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-curl http://my-example-domain.com
-:::
-
-::::
-
-
-
-### Clean up
-
-Navigate to the CloudFormation Console on your workstation. Select and delete, in the following order, stacks you created in this lab. *Note that since you used cross-stack references a number of stacks, you cannot delete a stack that exports a value if that value is still used by a consuming stack*:
-
-1. Delete `cloudformation-workshop-dev-application-v2` and `cloudformation-workshop-dev-application` without waiting for each one of them to be deleted; such stacks do not depend on each other. When both stacks are deleted, continue with the next step.
-2. Delete `cloudformation-workshop-dev-security-groups` and `cloudformation-workshop-dev-hosted-zone` without waiting for each one of them to be deleted as well. Then, continue with next steps.
-3. Delete `cloudformation-workshop-dev-cloud9`: note that when you delete this stack, the delete action you start should also cause the deletion the stack whose name starts with `aws-cloud9-aws-cloudformation-workshop-`. When both stacks are deleted, continue with the last step.
-4. Delete the `cloudformation-workshop-dev-base-network` stack.
-
-
-### Conclusion
-
-Congratulations! You have learned and practiced how to design your templates for lifecycle and ownership, and on how to use a number of pseudo parameters and intrinsic functions to favor reusability and modularity. You have also learned how to compose stack creations by exporting and importing values, and on how to reuse a template with an example blue-green deployment pattern.
diff --git a/content/intermediate/templates/conditions/index.ja.md b/content/intermediate/templates/conditions/index.ja.md
deleted file mode 100644
index 50d57ee1f..000000000
--- a/content/intermediate/templates/conditions/index.ja.md
+++ /dev/null
@@ -1,349 +0,0 @@
----
-title: "条件"
-weight: 100
----
-
-_ラボ実施時間 : 20分程度_
-
----
-
-### 概要
-
-[AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/) を使用してインフラストラクチャを記述する場合、CloudFormation テンプレートでリソースとリソースプロパティを宣言します。リソースを作成したり、条件に基づいてリソースプロパティ値を指定するようなユースケースで利用します。
-
-ベストプラクティスの一環として、アプリケーションのインフラストラクチャ用に作成したテンプレートを、`テスト`や`本番`などのライフサイクル環境全体で最大限に再利用します。例えば、コスト削減のため、`テスト`環境でリソースを少ない容量で実行するケースを想定しましょう。`本番`環境には `t2.small` [Amazon Elastic Compute Cloud](https://aws.amazon.com/jp/ec2/) (Amazon EC2) [インスタンスタイプ](https://aws.amazon.com/jp/ec2/instance-types/)、`テスト`環境には `t2.micro` インスタンスタイプを選択します。また、`本番`インスタンスでは 2 GiB の [Amazon Elastic Block Store](https://aws.amazon.com/jp/ebs/) (Amazon EBS) [ボリューム](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-volumes.html) を作成し、`テスト`インスタンスでは 1 GiB のボリュームを作成します。その他にも、条件が満たされたときだけリソースを作成するといったユースケースがあります。
-
-条件付きでリソースを作成するには、オプションの [Conditions](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) セクションをテンプレートに追加します。条件と関連する基準を決めたら、[Resources](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) と [Outputs](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) のテンプレートセクションで条件を使用します。例えば、Conditions を Resources またはテンプレートに記述した Outputs に関連付けると、条件付きで特定のリソースを作成したり、条件が満たされた場合は指定された出力を作成したりできます。リソースプロパティ値 (EC2 インスタンスのインスタンスタイプなど) を条件付きで指定するには、[条件関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html) を使用します。
-
-テンプレートで条件を使用するには、次のテンプレートセクションにステートメントを含めます。
-* **Parameters** : 条件を評価したいテンプレート入力パラメータを指定
-* **Conditions** : [組み込み条件関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html)を使用して条件を定義
-* **Resources と Outputs** :
- * 条件付きで作成したい Resources または Outputs に条件を関連付け
- * `Fn::If` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if)を使用して、定義した条件に基づいてリソースプロパティ値を条件付きで指定
-
-
-CloudFormation は、スタックの作成時またはスタックの更新時にリソースを作成する前に、テンプレート内のすべての条件を評価します。条件が満たされたリソースは、スタックの作成中または更新時にのみ作成されます。
-
-### 対象トピック
-
-このラボを修了すると、次のことができるようになります。
-
-* Condition 関数を活用するためのサンプルユースケースを定義
-* 条件評価に基づいてリソースをプロビジョニング
-* Condition 関数を使用してリソースプロパティ値を指定
-
-条件関数の利用例を見ていきましょう!
-
-### ラボを開始
-
-#### **リソースレベルでの条件の定義**
-
-* `code/workspace/conditions` ディレクトリに移動します。
-* `condition-resource.yaml` テンプレートを開きます。
-* ラボの手順に従ってテンプレートの内容を更新します。
-
-それでは、始めましょう!
-
-まず、テンプレートを再利用可能にすることに集中しましょう。テンプレートに、ライフサイクル環境の入力パラメータを含む `Parameters` セクションを追加します。`EnvType` パラメータを呼び出し、使用可能な入力値として `test` と `prod` という 2 つの環境名の例を記述します。使用する [Amazon Machine Image](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/AMIs.html) (AMI) の入力パラメータを定義します。この例では、[AWS Systems Manager](https://aws.amazon.com/jp/systems-manager/) [Parameter Store](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html) を使用して、使用可能な最新の Amazon Linux AMI を参照し、`LatestAmiId` というパラメータを呼び出しています。
-
-::alert[詳細については、[AWS Systems Manager Parameter Store を使用して最新の Amazon Linux AMI ID を取得する](https://aws.amazon.com/jp/blogs/news/query-for-the-latest-amazon-linux-ami-ids-using-aws-systems-manager-parameter-store/)をご参照ください。]{type="info"}
-
-以下に示すコンテンツをコピーし、`condition-resource.yaml` ファイルに貼り付けます。
-
-```yaml
-Parameters:
- LatestAmiId:
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-
- EnvType:
- Description: Specify the Environment type of the stack.
- Type: String
- AllowedValues:
- - test
- - prod
- Default: test
- ConstraintDescription: Specify either test or prod.
-```
-次に、[テンプレート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-anatomy.html)の `Conditions` セクションの条件の例である `IsProduction` について説明します。この条件では、`EnvType` パラメータ値が `prod` に等しいかどうかを評価します。
-
-既存のファイルに次のコンテンツを追加します。
-
-```yaml
-Conditions:
- IsProduction: !Equals
- - !Ref EnvType
- - prod
-```
-次に、`IsProduction` 条件に基づいて条件付きでプロビジョニングするリソースに条件を関連付けます。次の例では、`Volume` リソースと `MountPoint` リソースを `IsProduction` に関連付けます。`Volume` および `MountPoint` リソースが作成されるのは、`IsProduction` 条件が満たされた場合、つまり、`EnvType` パラメータ値が `prod` と等しい場合だけです。それ以外の場合は、EC2 インスタンスリソースのみがプロビジョニングされます。
-
-以下のコンテンツをコピーし、`condition-resource.yaml` ファイルに貼り付けます。
-
-```yaml
-Resources:
- EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
-
- MountPoint:
- Type: AWS::EC2::VolumeAttachment
- Properties:
- InstanceId: !Ref EC2Instance
- VolumeId: !Ref Volume
- Device: /dev/sdh
- Condition: IsProduction
-
- Volume:
- Type: AWS::EC2::Volume
- Properties:
- Size: 2
- AvailabilityZone: !GetAtt EC2Instance.AvailabilityZone
- Encrypted: true
- Condition: IsProduction
-```
-
-ソリューションをデプロイしましょう!
-
-スタックを作成する時に、`test` を `EnvType` の値として渡すと、CloudFormation によって EC2 インスタンスリソースのみがプロビジョニングされることがわかります。更新したテンプレートを保存します。次に、AWS CloudFormation [コンソール](https://console.aws.amazon.com/cloudformation) に移動し、スタックを作成します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/conditions` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/conditions
-:::
-1. AWS CLI を使用してスタックを作成します。必要なパラメータはあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-condition-test \
---template-body file://condition-resource.yaml \
---parameters ParameterKey="EnvType",ParameterValue="test"
-:::
-1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-condition-test/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. CloudFormation コンソールで、 **スタックの作成** 、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートの準備** セクションで、 **テンプレートの準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. `condition-resource.yaml` テンプレートを選択します。
-1. **スタックの名前** を入力します。例えば、`cfn-workshop-condition-test` と入力します。
-1. `EnvType` パラメータの値として `test` を選択します。 **次へ** をクリックします。
-1. **スタックオプションの設定** ページはデフォルト値のまま **次へ** をクリックします。
-1. レビューページで、 **送信** をクリックします。CloudFormation コンソールで作成中のスタックの進行状況を確認できます。
-1. スタックの作成が完了するまでお待ちください。スタックのステータスが `CREATE_COMPLETE` になるまで、コンソールのビューを更新します。
-::::
-:::::
-
-スタックが `CREATE_COMPLETE` ステータスになったら、スタックの **リソース** タブに移動します。`EnvType` に渡した `test` 値と、テンプレート内の他の 2 つのリソースに追加して関連付けた条件に基づき作成したロジックをベースに、プロビジョニングされているリソースが EC2 インスタンスだけであることを確認します。
-
-
-
-次のステップでは、同じテンプレートを使用して新しいスタックを作成します。今回は、`envType` パラメータの値として `prod` を渡し、`Volume` と `MountPoint` リソースもプロビジョニングされることを確認します。AWS CloudFormation [コンソール](https://console.aws.amazon.com/cloudformation)に移動し、既存のテンプレートを使用してスタックを作成します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/conditions` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/conditions
-:::
-1. AWS CLI を使用してスタックを作成します。必要なパラメータはあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-condition-prod \
---template-body file://condition-resource.yaml \
---parameters ParameterKey="EnvType",ParameterValue="prod"
-:::
-1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-condition-prod/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. CloudFormation コンソールで、 **スタックの作成** 、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートの準備** セクションで、 **テンプレートの準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. `condition-resource.yaml` テンプレートを選択します。
-1. **スタックの名前** を入力します。例えば、`cfn-workshop-condition-prod` と入力します。
-1. `EnvType` パラメータの値として `prod` を選択します。 **次へ** をクリックします。
-1. **スタックオプションの設定** ページはデフォルト値のまま **次へ** をクリックします。
-1. レビューページで、 **送信** をクリックします。CloudFormation コンソールで作成中のスタックの進行状況を確認できます。
-1. スタックの作成が完了するまでお待ちください。スタックのステータスが `CREATE_COMPLETE` になるまで、コンソールのビューを更新します。
-::::
-:::::
-
-今回は `IsProduction` 条件が満たされます。スタックの **リソース** タブに移動し、EC2 インスタンスリソースと共に、`Volume` および `MountPoint` リソースもプロビジョニングされていることを確認します。
-
-
-
-おめでとうございます!条件付きでリソースを作成する方法を学びました!
-
-
-#### **プロパティレベルでの条件の定義**
-
-リソースプロパティ値を条件付きで定義するユースケースの例を見てみましょう。例えば、`test` 環境用に `t2.micro` タイプの EC2 インスタンスを作成し、`prod` 環境用に `t2.small` タイプの EC2 インスタンスを作成するとします。`InstanceType` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-instancetype)として、リソースプロパティレベルで関連付ける条件を定義します。
-
-まず、条件を設計します。例えば、`EnvType` パラメータの入力パラメータとして `prod` を指定した場合、条件は満たされます。次に、条件を EC2 インスタンスに関連付け、希望する動作を次のように記述します。条件が当てはまる場合、インスタンスはインスタンスタイプとして `t2.small` を使用し、それ以外の場合は `t2.micro` を使用します。次の例で、これがどのように機能するか見てみましょう。
-
-1. `code/workspace/conditions` ディレクトリにいることを確認します。
-1. `condition-resource-property.yaml` ファイルを開きます。
-1. ラボの手順に従ってテンプレートの内容を更新します。
-
-それでは、始めましょう!この例では、前の例と同様に、`EnvType` パラメータと `IsProduction` 条件を定義して、渡したパラメータ値に基づいてリソースを作成します。以下に示すコンテンツをコピーし、`condition-resource-property.yaml` ファイルに貼り付けます。
-
-```yaml
-Parameters:
- LatestAmiId:
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-
- EnvType:
- Description: Specify the Environment type of the stack.
- Type: String
- AllowedValues:
- - test
- - prod
- Default: test
- ConstraintDescription: Specify either test or prod.
-
-Conditions:
- IsProduction: !Equals
- - !Ref EnvType
- - prod
-```
-
-次に、`IsProduction` 条件により、条件付きでプロパティ値を指定します。この例では、`Fn::If` [条件関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if)を使用して、`IsProduction` 条件が満たされるかどうかを評価します。条件が満たされる場合、`t2.small` プロパティの値が `InstanceType` に使用されます。条件を満たさない場合は `t2.micro` が使用されます。次のコードをコピーしてテンプレートに追加します。
-
-```yaml
-Resources:
- EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: !If [IsProduction, t2.small, t2.micro]
-```
-
-リソースをデプロイしましょう!
-
-このセクションでは、`EnvType` パラメータの値として `test` を指定、EC2 インスタンスのタイプが `t2.micro` であることを確認します。AWS CloudFormation [コンソール](https://console.aws.amazon.com/cloudformation)に移動し、次のテンプレートを使用してスタックを作成します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/conditions` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/conditions
-:::
-1. AWS CLI を使用してスタックを作成します。必須パラメータはあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-condition-property-test \
---template-body file://condition-resource-property.yaml \
---parameters ParameterKey="EnvType",ParameterValue="test"
-:::
-1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-condition-property-test/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. CloudFormation コンソールで、 **スタックの作成** 、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレートの準備** セクションで、 **テンプレートの準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. `condition-resource-property.yaml` テンプレートを選択します。
-1. **スタックの名前** を入力します。例えば、`cfn-workshop-condition-property-test` と入力します。
-1. `EnvType` パラメータの値として `test` を渡します。 **次へ** をクリックします。
-1. **スタックオプションの設定** ページはデフォルト値のまま **次へ** をクリックします。
-1. レビューページで、 **送信** をクリックします。CloudFormation コンソールで作成中のスタックの進行状況を確認できます。
-1. スタックの作成が完了するまでお待ちください。スタックのステータスが `CREATE_COMPLETE` になるまで、コンソールのビューを更新します。
-::::
-:::::
-
-スタックのステータスが `CREATE_COMPLETE` になったら、スタックの **リソース** タブに移動し、スタックで作成した EC2 インスタンスを探します。
-
-次に、インスタンスタイプが想定通りであることを確認します。インスタンスの物理 ID のリンクをクリックして、Amazon EC2 コンソールでインスタンスを表示します。
-
-
-次の例のように、インスタンスタイプが `t2.micro` であることを示すビューが表示されます。
-
-
-同じテンプレートで新しいスタックを作成し、`EnvType` の値として `prod` を指定すると、インスタンスのタイプは代わりに `t2.small` になります。
-
-おめでとうございます!これで、リソースプロパティ値を条件付きで指定する方法がわかりました。
-
-### **チャレンジ**
-
-ここまで、CloudFormation テンプレート内のリソースとプロパティ値で条件を使用する方法を学んできました。このチャレンジでは、`condition-resource.yaml` CloudFormation テンプレートの [Outputs](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) セクションに条件付きで出力を作成します。
-
-**タスク** `condition-resource.yaml` テンプレートに [Outputs](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) セクションを記述してください。出力の論理 ID として `VolumeId` を指定し、`Ref` 組み込み関数を使用して [VolumeID を返します](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#aws-resource-ec2-volume-return-values)。このチャレンジのゴールは、`IsProduction` 条件が満たされた場合にのみ出力を作成することです。チャレンジのゴールに向けて、どのようにテンプレートに反映させますか?準備ができたら、更新したテンプレートで既存の `cfn-workshop-condition-prod` スタックを更新し、変更によって期待どおりの出力が作成されたことを確認します。
-
-:::expand{header="ヒントが必要ですか?"}
-* [スタック出力](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html#outputs-section-structure-examples)のドキュメントを参照し、テンプレートで `VolumeId` 出力を定義してください。
-* [条件](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html)と[条件の関連付け](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html#associating-a-condition)のドキュメントを確認してください。どのように条件付きで出力を作成しますか?
-:::
-
-::::::expand{header="解決策を確認しますか?"}
-`condition-resource.yaml` ファイルに次の内容を追加します。
-
-```yaml
-Outputs:
- VolumeId:
- Value: !Ref Volume
- Condition: IsProduction
-```
-
-次に、AWS CloudFormation [コンソール](https://console.aws.amazon.com/cloudformation)に移動して、`cfn-workshop-condition-prod` スタックの更新を選択します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/conditions` ディレクトリに移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/conditions
- :::
-1. AWS CLI を使用してスタックを更新します。必要なパラメータはあらかじめ入力されています。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-condition-prod \
---template-body file://condition-resource.yaml \
---parameters ParameterKey="EnvType",ParameterValue="prod"
- :::
-1. `update-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-condition-prod/739fafa0-e4d7-11ed-a000-12d9009553ff"
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **UPDATE_COMPLETE** になっているかどうかを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. CloudFormation コンソールで、 **更新** をクリックします。
-1. **テンプレートの準備** セクションで、 **既存のテンプレート置き換える** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. `condition-resource.yaml` テンプレートを選択します。
-1. `EnvType` は既に `prod` に設定されているはずです。 **次へ** をクリックします。
-1. **スタックオプションの設定** ページはデフォルト値のまま **次へ** をクリックします。
-1. レビューページで、 **送信** をクリックします。CloudFormation コンソールで作成中のスタックの進行状況を確認できます。
-1. スタックの作成が完了するまでお待ちください。スタックのステータスが `UPDATE_COMPLETE` になるまで、コンソールのビューを更新します。
-::::
-:::::
-
-スタックの`出力`セクションに移動し、`VolumeId` の出力が存在することを確認します。
-
-::::::
-
-解決策は、`code/solutions/conditions/condition-output.yaml` テンプレートファイルでも入手できます。
-
-### クリーンアップ
-
-次に示す手順に従って、このラボで作成したリソースをクリーンアップしてください。
-
-* CloudFormation コンソールで、このラボで作成した `cfn-workshop-condition-test` スタックを選択します。
-* このラボで作成したスタックの **削除** を選択した後、 **スタックの削除** をクリックして確定します。
-
-
-このラボで作成した他のスタック `cfn-workshop-condition-prod`、`cfn-workshop-condition-property-test` に対して、上記と同じクリーンアップ手順を実行します。
-
----
-### まとめ
-
-おめでとうございます!リソースを条件付きで作成する方法と、リソースプロパティ値を条件付きで指定する方法を学習しました。詳細については、[条件](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html)と[条件関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html)をご参照ください。
diff --git a/content/intermediate/templates/conditions/index.md b/content/intermediate/templates/conditions/index.md
deleted file mode 100644
index c1659f599..000000000
--- a/content/intermediate/templates/conditions/index.md
+++ /dev/null
@@ -1,348 +0,0 @@
----
-title: "Conditions"
-weight: 100
----
-
-_Lab Duration: ~20 minutes_
-
----
-
-### Overview
-
-When you describe your infrastructure with [AWS CloudFormation](https://aws.amazon.com/cloudformation/), you declare resources and resource properties in your CloudFormation templates. You might have use cases where you want to create resources, or specify resource property values, based on conditions.
-
-As part of best practices, you want to maximize reuse of templates you write for your application's infrastructure across your life cycle environments, such as `test` and `production`. Let’s say you choose to run resources at a reduced capacity in your `test` environment, for cost savings: for example, you choose a `t2.small` [Amazon Elastic Compute Cloud](https://aws.amazon.com/ec2/) (Amazon EC2) [instance type](https://aws.amazon.com/ec2/instance-types/) for your `production` environment, and a `t2.micro` instance type for your `test` environment. Another example: you choose to create a 2 GiB [Amazon Elastic Block Store](https://aws.amazon.com/ebs/) (Amazon EBS) [volume](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-volumes.html) to use with your `production` instance, and a 1 GiB volume to use with your `test` instance. You might also have use cases where you only want to create a resource when a condition is true.
-
-To conditionally create resources, you add the optional [Conditions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) section to your template. Once you define conditions and relevant criteria, you use your conditions in [Resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) and [Outputs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) template sections. For example, you associate a condition to a resource, or to an output you describe in your template, so you can conditionally create the given resource or the given output if your condition is true. To conditionally specify resource property values - such as, for example, the instance type of your EC2 instance - you use [Condition Functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html).
-
-To use conditions in your template, you include statements in following template sections:
-* **Parameters**: specify template input parameter(s) you want your conditions to evaluate.
-* **Conditions**: define your conditions by using [intrinsic condition functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html).
-* **Resource and Outputs**:
- * associate conditions with resources, or outputs, that you want to conditionally create.
- * Use the `Fn::If` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if) to conditionally specify resource property values based on a condition you define.
-
-
-CloudFormation evaluates all conditions in your template before creating any resources at stack creation or stack update. Resources that are associated with a true condition are only created during stack creation or stack update.
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* Identify sample use cases for leveraging Condition functions.
-* Provision resources based on Condition evaluation.
-* Specify resource property values using Condition functions.
-
-Let’s walk through examples of how to use Condition functions!
-
-### Start Lab
-
-#### **Defining Conditions at the resource level**
-
-* Change directory to: `code/workspace/conditions`.
-* Open the `condition-resource.yaml` template.
-* Update the content of the template as you follow along steps on this lab.
-
-Let’s get started!
-
-Let’s first focus on making your template more reusable. Choose to add a `Parameters` section in your template, with an input parameter for your life cycle environments; call the parameter `EnvType`, and describe two example environment names, `test` and `prod`, as input values you allow. Define an input parameter for the [Amazon Machine Image](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) (AMI) you will use: in this example, you use an example parameter called `LatestAmiId` to refer, in its value, to the latest available Amazon Linux AMI by using [AWS Systems Manager](https://aws.amazon.com/systems-manager/) [Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html).
-
-::alert[For more information, see [Query for the latest Amazon Linux AMI IDs using AWS Systems Manager Parameter Store](https://aws.amazon.com/blogs/compute/query-for-the-latest-amazon-linux-ami-ids-using-aws-systems-manager-parameter-store/).]{type="info"}
-
-Copy the content shown below, and paste it in the `condition-resource.yaml` file, by appending it to the existing file content:
-
-```yaml
-Parameters:
- LatestAmiId:
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-
- EnvType:
- Description: Specify the Environment type of the stack.
- Type: String
- AllowedValues:
- - test
- - prod
- Default: test
- ConstraintDescription: Specify either test or prod.
-```
-Next, describe `IsProduction`, an example condition in the `Conditions` section of your [template.](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html) In this condition, you evaluate if the `EnvType` parameter value equals to `prod`.
-
-Append the following content to the existing file content:
-
-```yaml
-Conditions:
- IsProduction: !Equals
- - !Ref EnvType
- - prod
-```
-Next, associate conditions to resources you want to conditionally provision based on the `IsProduction` condition. In the following example, you associate the `Volume` and `MountPoint` resources with `IsProduction`. Therefore, these resources are created only when the `IsProduction` condition is true: that is, if the `EnvType` parameter value is equal to `prod`. Otherwise, only the EC2 instance resource will be provisioned.
-
-Copy the content below, and paste it in the `condition-resource.yaml` file by appending it to the existing file content:
-
-```yaml
-Resources:
- EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
-
- MountPoint:
- Type: AWS::EC2::VolumeAttachment
- Properties:
- InstanceId: !Ref EC2Instance
- VolumeId: !Ref Volume
- Device: /dev/sdh
- Condition: IsProduction
-
- Volume:
- Type: AWS::EC2::Volume
- Properties:
- Size: 2
- AvailabilityZone: !GetAtt EC2Instance.AvailabilityZone
- Encrypted: true
- Condition: IsProduction
-```
-
-Let’s deploy the solution!
-
-When you create the stack, you will pass `test` as the value for `EnvType`, and you will observe only an EC2 instance resource will be provisioned by CloudFormation. Save the template you have updated with content above; next, navigate to the AWS CloudFormation [console](https://console.aws.amazon.com/cloudformation), and choose to create a stack using this template:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/conditions`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/conditions
-:::
-1. Use the AWS CLI to create the stack. The required parameters have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-condition-test \
---template-body file://condition-resource.yaml \
---parameters ParameterKey="EnvType",ParameterValue="test"
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-condition-test/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. In the CloudFormation console, select **Create stack**, **With new resources (standard)**.
-1. In **Prepare template**, select **Template is ready**.
-1. In **Template source**, select **Upload a template file**.
-1. Choose the `condition-resource.yaml` template.
-1. Enter a **Stack name**. For example, choose to specify `cfn-workshop-condition-test`.
-1. Pass `test` as the value for the `EnvType` parameter. Choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page. Choose **Next**.
-1. Choose **Submit**. You can view the progress of the stack being created in the CloudFormation console.
-1. Wait until the stack creation is complete. Refresh the view in the console until you see your stack to be in the `CREATE_COMPLETE` status.
-::::
-:::::
-Once the stack is in the `CREATE_COMPLETE` status, navigate to the **Resources** tab for your stack: verify the only resource provisioned is your EC2 instance, based on the logic you created driven by the `test` value you passed to the `EnvType` parameter, and to the condition you added and associated to the other two resources in the template:
-
-
-
-In the next step, you will create a new stack with the same template. This time, you will pass `prod` as the value for the `EnvType` parameter, and verify that you will provision, with CloudFormation, your `Volume` and `MountPoint` resources as well. Navigate to the AWS CloudFormation [console](https://console.aws.amazon.com/cloudformation), and choose to create a stack using your existing template:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/conditions`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/conditions
-:::
-1. Use the AWS CLI to create the stack. The required parameters have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-condition-prod \
---template-body file://condition-resource.yaml \
---parameters ParameterKey="EnvType",ParameterValue="prod"
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-condition-prod/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. In the CloudFormation console, select **Create stack**, **With new resources (standard)**.
-1. In **Prepare template**, select **Template is ready**.
-1. In **Template source**, select **Upload a template file**.
-1. Choose the `condition-resource.yaml` template.
-1. Enter a **Stack name**. For example, choose to specify `cfn-workshop-condition-prod`.
-1. Pass `prod` as the value for the `EnvType` parameter. Choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page. Choose **Next**.
-1. Choose **Submit**. You can view the progress of the stack being created in the CloudFormation console.
-1. Wait until the stack creation is complete. Refresh the view in the console until you see your stack to be in the `CREATE_COMPLETE` status.
-::::
-:::::
-
-This time, the `IsProduction` condition is true. Navigate to the **Resources** tab for your stack, and verify that along with your EC2 instance resource, your other `Volume` and `MountPoint` resources are also provisioned:
-
-
-
-Congratulations! You learned how to conditionally create resources!
-
-
-#### **Defining Conditions at the property level**
-
-Let’s evaluate an example use case where you conditionally define resource property values. For example, let's say you want to create an EC2 instance of the `t2.micro` type for your `test` environment, and an EC2 instance of type `t2.small` for your `production` environment. You choose to define a condition that you associate at the resource property level for the `InstanceType` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-instancetype).
-
-First, you design your condition such as, for example, if you specify `prod` as the input parameter for the `EnvType` parameter, your condition is true. Next, you associate the condition to your EC2 instance, and describe your desired behavior as such: if your condition is true, your instance will use `t2.small` as the instance type, or `t2.micro` otherwise. Let’s take a look at how this works in the example following next.
-
-1. Make sure you are in the following directory: `code/workspace/conditions`.
-2. Open the `condition-resource-property.yaml` file.
-3. Update the content of the template as you follow along steps on this lab.
-
-Let’s get started! In this example, that is similar to the previous one, you define the `EnvType` parameter and the `IsProduction` condition to create resource based on parameter value you passed. Copy the content shown below, and paste it in the `condition-resource-property.yaml` file, by appending it to the existing file content:
-
-```yaml
-Parameters:
- LatestAmiId:
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-
- EnvType:
- Description: Specify the Environment type of the stack.
- Type: String
- AllowedValues:
- - test
- - prod
- Default: test
- ConstraintDescription: Specify either test or prod.
-
-Conditions:
- IsProduction: !Equals
- - !Ref EnvType
- - prod
-```
-
-Next, let’s wire up the `IsProduction` condition to conditionally specify a property values. In this example, you use the `Fn::if` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if), in its YAML short form, to evaluate if the `IsProduction` condition is true: if that is the case, the `t2.small` property value will be used for `InstanceType`; otherwise, `t2.micro` will be used if the condition is false. Copy and append the following code to the template:
-
-```yaml
-Resources:
- EC2Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: !If [IsProduction, t2.small, t2.micro]
-```
-
-Time to deploy your resources!
-
-In this section, you will pass `test` as the value for the `EnvType` parameter, and verify the type of your EC2 instance will be `t2.micro`. Navigate to the AWS CloudFormation [console](https://console.aws.amazon.com/cloudformation), and choose to create a stack using this template:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/conditions`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/conditions
-:::
-1. Use the AWS CLI to create the stack. The required parameters have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-condition-property-test \
---template-body file://condition-resource-property.yaml \
---parameters ParameterKey="EnvType",ParameterValue="test"
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-condition-property-test/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. In the CloudFormation console, select **Create stack**, **With new resources (standard)**.
-1. In **Prepare template**, select **Template is ready**.
-1. In **Template source**, select **Upload a template file**.
-1. Choose the `condition-resource-property.yaml` template.
-1. Enter a **Stack name**. For example, choose to specify `cfn-workshop-condition-property-test`.
-1. Pass `test` as the value for the `EnvType` parameter. Choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page. Choose **Next**.
-1. Choose **Submit**. You can view the progress of the stack being created in the CloudFormation console.
-1. Wait until the stack creation is complete. Refresh the view in the console until you see your stack to be in the `CREATE_COMPLETE` status.
-::::
-:::::
-
-Once the Stack is in the `CREATE_COMPLETE` status, navigate to the **Resources** tab for your stack, and locate the EC2 instance you created with your stack.
-
-Next, verify the instance type is the one you expect: follow the link for the Physical ID of your instance, to view your instance in the Amazon EC2 Console:
-
-
-You should see a view, as in the example shown next, showing that your instance type is `t2.micro`:
-
-
-If you create a new stack with the same template, and specify `prod` as the value for `EnvType`, the type of your instance will be `t2.small` instead.
-
-Congratulations! You have learned how to conditionally specify resource property values!
-
-### **Challenge**
-
-So far, you’ve learned how to use conditions with resources and property values in your CloudFormation templates. In this challenge, you will conditionally create an output in the [Outputs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) section of your `condition-resource.yaml` CloudFormation template.
-
-**Task:** Describe an [Outputs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) section in your `condition-resource.yaml` template. Specify `VolumeId` for the Logical ID of your output, and use the `Ref` intrinsic function to [return the ID of your volume](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#aws-properties-ec2-instance-return-values). Your goal, in this challenge, is to create your output only if the `IsProduction` condition is true: how can you reflect this intent in your template? Once ready, update your existing `cfn-workshop-condition-prod` stack with the template you updated, and verify your changes led to creating the output as you expected.
-
-:::expand{header="Need a hint?"}
-* See the documentation for [Stack Output](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html#outputs-section-structure-examples), and define a `VolumeId` output in your template.
-* Review the documentation on [Conditions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) and [Associating a condition](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html#associating-a-condition). How do you conditionally create an output?
-:::
-
-::::::expand{header="Want to see the solution?"}
-Append the following content to the `condition-resource.yaml` file:
-
-```yaml
-Outputs:
- VolumeId:
- Value: !Ref Volume
- Condition: IsProduction
-```
-
-Next, navigate to the AWS CloudFormation [console](https://console.aws.amazon.com/cloudformation), and choose to update your `cfn-workshop-condition-prod` stack:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/conditions`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/conditions
- :::
-1. Use the AWS CLI to update the stack. The required parameter `--template-body` have been pre-filled for you.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-condition-prod \
---template-body file://condition-resource.yaml \
---parameters ParameterKey="EnvType",ParameterValue="prod"
- :::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-condition-prod/739fafa0-e4d7-11ed-a000-12d9009553ff"
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. In the CloudFormation console, select **Update stack**.
-1. In **Prepare template**, select **Replace current template**.
-1. In **Template source**, select **Upload a template file**.
-1. Choose the `condition-resource.yaml` template.
-1. `EnvType` should already be set to `prod`. Choose **Next**.
-1. Choose to accept default values in the **Configure stack options** page. Choose **Next**.
-1. Choose **Submit**. You can view the progress of the stack being created in the CloudFormation console.
-1. Wait until the stack creation is complete. Refresh the view in the console until you see your stack to be in the `UPDATE_COMPLETE` status.
-::::
-:::::
-
-Navigate to the `Outputs` section of your stack, and validate the `VolumeId` output is present.
-
-::::::
-
-The full solution is also available in the `code/solutions/conditions/condition-output.yaml` template file.
-
-### Cleanup
-
-Follow steps shown next to clean up resources you created in this lab:
-
-* In the CloudFormation console, choose the `cfn-workshop-condition-test` stack you created in this lab.
-* Choose **Delete** to delete the stack you created in this lab, and then choose **Delete stack** to confirm.
-
-
-Perform the same cleanup steps above for your other stacks you created in this lab: `cfn-workshop-condition-prod`, and `cfn-workshop-condition-property-test`.
-
----
-### Conclusion
-
-Congratulations! You have learned how to conditionally create resources, and how to conditionally specify resource property values. For more information, see [Conditions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) and [Condition functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html).
diff --git a/content/intermediate/templates/cross-stacks/index.ja.md b/content/intermediate/templates/cross-stacks/index.ja.md
deleted file mode 100644
index ab48fba7d..000000000
--- a/content/intermediate/templates/cross-stacks/index.ja.md
+++ /dev/null
@@ -1,291 +0,0 @@
----
-title: "クロススタック参照"
-weight: 500
----
-
-_ラボ実施時間 : 25分程度_
-
----
-
-### 概要
-前のラボでは、`Outputs` セクションと `Fn::GetAtt` 関数を使って子スタックから親スタックへ値を渡す方法について学びました。そして、再利用可能なテンプレートを作成することができるようになりました。例えば、ネストされたスタックを利用すると、VPC と IAM ロール専用のテンプレートを用意することができます。
-しかし、 **スタック** を再利用したい場合はどうでしょうか?
-
-例えば、多数のテンプレートを使用して多数のワークロードをデプロイする計画があったとします。すべての EC2 インスタンスが Systems Manager Session Manager によるすべての EC2 インスタンスへのアクセスを有効にする必要があります。
-同様に、1 つのスタックで VPC をデプロイし、それを将来、複数のスタックやワークロードで使用したい場合があります。
-このような一対多の関係は、ネストされたスタックのシナリオでは実現できません。
-ここでクロススタック参照の出番です。
-
-
-私たちは [Export](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) を使用し、同じ AWS アカウントと同じリージョンの任意の CloudFormation スタックに [Import](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) できるグローバル変数を作成します。
-
-### 取り上げるトピック
-このラボでは、以下を作成します。
-
-1. **VPC スタック** : 前のラボで使用したものと同じシンプルな VPC テンプレートが含まれていますが、出力に Export が追加されています。
-1. **IAM インスタンスロールスタック** : 前のラボで使用したのと同じ IAM インスタンスロールが含まれていますが、出力に Export が追加されています。
-1. **EC2 スタック** : 前のラボで定義した EC2 インスタンスが含まれていますが、ここでは Fn::ImportValue 関数を使用します。
-
-> クロススタック参照の関係を示す図
-
-
-
-> 導入されるインフラストラクチャの概要
-
-
-
-### ラボを開始
-
-作業ファイルは `code/workspace/cross-stacks` にあります。このラボの残りの部分では、テンプレートにコードを追加する必要があります。なお、解決策は `code/solutions/cross-stacks` フォルダにありますので、こちらを参照することも可能です。
-
-#### VPC スタックの作成
-VPC テンプレートは既に作成されており、タイトルは `vpc.yaml` です。このテンプレートは、2 つのパブリックサブネット、1 つのインターネットゲートウェイ、および、ルートテーブルを含む VPC スタックを作成することができます。
-
-##### 1. VPC テンプレートの準備
-
-::alert[このラボで参照されているファイルはすべて `code/workspace/cross-stacks` 内にあります。]{type="info"}
-
-`vpc.yaml` ファイルを見ると、テンプレートの **Outputs** セクションにいくつかの出力があることがわかります。次に、Export を追加して、他の CloudFormation スタックから使用できるようにします。
-
-以下の [4-5、9-10、14-15] 行目をテンプレートファイルに追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=4-5,9-10,14-15}
-Outputs:
- VpcId:
- Value: !Ref VPC
- Export:
- Name: cfn-workshop-VpcId
-
- PublicSubnet1:
- Value: !Ref VPCPublicSubnet1
- Export:
- Name: cfn-workshop-PublicSubnet1
-
- PublicSubnet2:
- Value: !Ref VPCPublicSubnet2
- Export:
- Name: cfn-workshop-PublicSubnet2
-:::
-
-##### 2. VPC スタックのデプロイ
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `cfn101-workshop/code/workspace/cross-stacks` ディレクトリに移動します。
-1. **スタックを作成** は、次の AWS CLI コマンドを使用して行います。このテンプレートでは、 `AvailabilityZones` パラメータの値を指定する必要があります。たとえば、 `us-east-1a` と `us-east-1b` は以下で使用されます。利用しているリージョンの 2 つのアベイラビリティーゾーンを選択してください。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-cross-stacks-vpc \
---template-body file://vpc.yaml \
---parameters ParameterKey=AvailabilityZones,ParameterValue=us-east-1a\\,us-east-1b
-:::
-1. 次の AWS CLI コマンドを実行して、スタックの作成が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-cross-stacks-vpc
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. コンソールで CloudFormation に移動し、 **新しいリソースを使用 (標準)** をクリックします。
-1. **テンプレートの準備** セクションで、 **テンプレート準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. `vpc.yaml` ファイルを選択します。
-1. **スタック名** を入力します。例えば、`cfn-workshop-cross-stacks-vpc` と入力します。
-1. **AvailabilityZone** パラメータには、 **2 つの AZ** を選択します。
-1. 残りのパラメータは **デフォルト** のままとします。
-1. すべてデフォルトのままウィザード内を移動します。
-1. レビューページで一番下までスクロールし、 **送信** をクリックします。
-::::
-:::::
-#### IAM スタックの作成
-
-##### 1. IAM ロールテンプレートの準備
-
-1. `iam.yaml` ファイルを開きます。
-1. 以下の [4 ~ 5] 行目をテンプレートの **Outputs** セクションにコピーします。
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=4-5}
- Outputs:
- WebServerInstanceProfile:
- Value: !Ref WebServerInstanceProfile
- Export:
- Name: cfn-workshop-WebServerInstanceProfile
-:::
-
-##### 2. IAM スタックのデプロイ
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次の AWS CLI コマンドを使用して、 **スタックを作成** してみましょう。このテンプレートでは、IAM リソースを作成するための `CAPABILITY_IAM` 機能を指定する必要があります。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-cross-stacks-iam \
---template-body file://iam.yaml \
---capabilities CAPABILITY_IAM
-:::
-1. 次の AWS CLI コマンドを実行して、スタックの作成が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-cross-stacks-iam
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. コンソールで CloudFormation に移動し、 **新しいリソースを使用 (標準)** をクリックします。
-1. **テンプレートの準備** セクションで、 **テンプレート準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. `iam.yaml` ファイルを選択します。
-1. **スタック名** を入力します。例えば、`cfn-workshop-cross-stacks-iam` と入力します。
-1. **次へ** をクリックします。
-1. すべてデフォルトのままウィザード内を移動します。
-1. **Acknowledge IAM capabilities** をクリックし、 **送信** をクリックします。
-::::
-:::::
-
-#### EC2 クロススタックの作成
-
-##### 1. EC2 テンプレートの準備
-**クロススタック** のコンセプトは、 **Parameters** を使用する代わりに、組み込み関数を使用して、以前にエクスポートされた値をインポートすることです。
-従って、`ec2.yaml` に最初に加えるべき変更は、今後使用されなくなる `SubnetId`、`VpcID`、`WebServerInstanceProfile` のパラメータを削除することです。
-
-
-##### 2. Parameters セクションの更新
-
-次の例のような形で、 **Parameters** セクションを更新します。
-つまり、 **Parameters** セクションから、`VpcId`、`SubnetId`、`WebServerInstanceProfile` の項目を削除します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-Parameters:
- EnvironmentType:
- Description: 'Specify the Environment type of the stack.'
- Type: String
- Default: Test
- AllowedValues:
- - Dev
- - Test
- - Prod
- ConstraintDescription: 'Specify either Dev, Test or Prod.'
-
- AmiID:
- Type: AWS::SSM::Parameter::Value
- Description: 'The ID of the AMI.'
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-:::
-
-##### 3. WebServerInstance リソースの更新
-
-次に、テンプレートの `Ref` を更新して、以前に作成した VPC と IAM スタックからエクスポートされた値をインポートする必要があります。
-このインポートは [Fn::ImportValue](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) 組み込み関数を使用して実行します。
-
-`ec2.yaml` テンプレートのリソースセクションにある WebServerInstance リソースを更新します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=5-8}
-WebServerInstance:
- Type: AWS::EC2::Instance
- {...}
- Properties:
- SubnetId: !ImportValue cfn-workshop-PublicSubnet1
- IamInstanceProfile: !ImportValue cfn-workshop-WebServerInstanceProfile
- ImageId: !Ref AmiID
- InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref EnvironmentType, InstanceType]
- {...}
-:::
-
-##### 4. セキュリティグループの更新
-最後に、セキュリティグループリソースを更新します。`ec2.yaml` テンプレートの **Resources** セクション `WebServerSecurityGroup` リソース [19] 行目を更新します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=19}
-WebServerSecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Enable HTTP and HTTPS access
- SecurityGroupIngress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
- SecurityGroupEgress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
- - IpProtocol: tcp
- FromPort: 443
- ToPort: 443
- CidrIp: 0.0.0.0/0
- VpcId: !ImportValue cfn-workshop-VpcId
-:::
-
-##### 5. EC2 スタックのデプロイ
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次の AWS CLI コマンドを使用して、 **スタックを作成** してみましょう。このテンプレートでは、IAM リソースを作成するための `CAPABILITY_IAM` 機能を指定する必要があります。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-cross-stacks-ec2 \
---template-body file://ec2.yaml
-:::
-1. 次の AWS CLI コマンドを実行して、スタックの作成が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-cross-stacks-ec2
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. コンソールで CloudFormation に移動し、 **新しいリソースを使用 (標準)** をクリックします。
-1. **テンプレートの準備** セクションで、 **テンプレート準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. `ec2.yaml` ファイルを選択します。
-1. **スタック名** を入力します。例えば、`cfn-workshop-cross-stacks-ec2`と入力します。
-1. 残りのパラメータは **デフォルト** のままとします。
-1. すべてデフォルトのままウィザード内を移動します。
-1. **レビュー** ページで一番下までスクロールし、 **送信** をクリックします。
-::::
-:::::
-
-#### 7. デプロイメントのテスト
-
-##### 1.アプリケーションが正常にデプロイされたことを確認
-
-プライベートモードで新しいブラウザウィンドウを開き、`websiteURL` を入力します (WebsiteURL は CloudFormation コンソールの EC2 スタックの **出力** タブから取得できます)。
-下の図のような、いくつかのインスタンスメタデータが表示されます。
-
-
-
-##### 2.SSM Session Manager を使用してインスタンスにログイン
-
-Session Manager を使用してインスタンスにログインできることを確認します。
-
-やり方がわからない場合は、[Session Manager](/basics/operations/session-manager#challenge) ラボをご参照ください。
-
-### クリーンアップ
-
-::alert[スタックが出力値をインポートした後は、出力値をエクスポートしているスタックを削除したり、エクスポートされた出力値を変更したりすることはできません。エクスポートするスタックを削除したり、出力値を変更したりする前に、すべてのインポートを削除する必要があります。]{type="info"}
-
-例えば、 **EC2 スタック** を削除する前に **VPC スタック** を削除することはできません。次のエラーメッセージが表示されます。
-
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **スタックを削除** するために次の AWS CLI コマンドを実行してください
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-cross-stacks-ec2
-:::
-1. 次の AWS CLI コマンドを使用して、スタックが削除されるまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---stack-name cfn-workshop-cross-stacks-ec2
-:::
-1. `cfn-workshop-cross-stacks-iam` と `cfn-workshop-cross-stacks-vpc` スタックについて、上記のステップ (1-2) を繰り返します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [CloudFormation コンソール](https://console.aws.amazon.com/cloudformation) で、 **EC2 スタック** を選択します (例: `cfn-workshop-cross-stacks-ec2`)。
-1. 右上の **削除** をクリックします。
-1. ポップアップウィンドウで、 **スタックの削除** をクリックします。
-1. **DELETE_COMPLETE** のステータスが表示されるまで、 **更新** ボタンを数回クリックします。
-1. 依存関係がなくなったため、 **IAM** と **VPC** スタックが削除できます。
-::::
-:::::
-
----
-### まとめ
-**クロススタック参照** では、複数のスタックで繰り返し使用できるリソースを作成できます。利用する全てのスタックで、 **Export** で指定した名前を知る必要があります。この機能を利用することで、役割と責任を分けることができます。例えば、ネットワークチームは、承認された VPC デザインをテンプレートとして作成して提供できます。必要に応じて、VPC スタックの Export を参照すれば良いです。同様に、セキュリティチームは IAM ロールや EC2 セキュリティグループについても同じ操作を行うことができます。
diff --git a/content/intermediate/templates/cross-stacks/index.md b/content/intermediate/templates/cross-stacks/index.md
deleted file mode 100644
index b27f36454..000000000
--- a/content/intermediate/templates/cross-stacks/index.md
+++ /dev/null
@@ -1,293 +0,0 @@
----
-title: "Cross-stack references"
-weight: 500
----
-
-_Lab Duration: ~25 minutes_
-
----
-
-### Overview
-In the previous lab, we saw how we use the `Outputs` section and the `Fn::GetAtt` function to pass values from a child
-stack to parent stack. This enabled us to have dedicated templates for a VPC and an IAM role. As we mentioned previously,
-this gives us the ability to create templates that can be re-used. However, what about if we want to re-use **stacks**?
-
-For example, you may have plans for many workloads deployed with many templates but every EC2 instance is expected to
-enable Systems Manager Session Manager access to every EC2 Instance. Similarly, you may wish to deploy a VPC via one
-stack and then use it with multiple future stacks and workloads. Achieving this one-many relationship is not possible
-in a Nested Stack scenario. This is where cross-stack references come in.
-
-We use **[Exports](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html)** to create variables that can be **[Imported](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html)** into any CloudFormation stack in the same AWS account and region.
-
-### Topics Covered
-In this lab, you will build:
-
-1. **The VPC stack.** This contains the same simple VPC template used in the previous lab but with Export added to the Outputs.
-1. **The IAM instance** role stack. This contains the same IAM instance role used in the previous lab but with Export added to the Outputs.
-1. **The EC2 stack.** This contains the EC2 instance you have defined in previous labs but will make use of the Fn::ImportValue function.
-
-Here is a diagram showing the hierarchy of cross-stack references.
-
-
-
-This diagram represents the high-level overview of the infrastructure that will be deployed:
-
-
-
-### Start Lab
-
-You will find the working files in `code/workspace/cross-stacks`. In the rest of this lab, you should add your code to the templates here. The solution can be found in the `code/solutions/cross-stacks` folder. You can reference these against your code.
-
-#### Create VPC Stack
-The VPC template has been created for you. It is titled `vpc.yaml`. This template will create VPC stack with 2 Public Subnets, an Internet Gateway, and Route tables.
-
-##### 1. Prepare the VPC template
-
-::alert[All the files referenced in this lab can be found within `code/workspace/cross-stacks`]{type="info"}
-
-If you look in the file `vpc.yaml` file, you will notice that there are some outputs in the **Outputs** section of the template. You will now add exports to each of these so that we can consume them from other CloudFormation stacks.
-
-Add the lines [4-5, 9-10 and 14-15] to your template file:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=4-5,9-10,14-15}
-Outputs:
- VpcId:
- Value: !Ref VPC
- Export:
- Name: cfn-workshop-VpcId
-
- PublicSubnet1:
- Value: !Ref VPCPublicSubnet1
- Export:
- Name: cfn-workshop-PublicSubnet1
-
- PublicSubnet2:
- Value: !Ref VPCPublicSubnet2
- Export:
- Name: cfn-workshop-PublicSubnet2
-:::
-
-##### 2. Deploy the VPC Stack
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `cfn101-workshop/code/workspace/cross-stacks`.
-1. **Create Stack** by using the following AWS CLI command. The template requires you provide the values for `AvailabilityZones` parameter, For example `us-east-1a` and `us-east-1b` are used below. Please select 2 Availability Zone based on your region.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-cross-stacks-vpc \
---template-body file://vpc.yaml \
---parameters ParameterKey=AvailabilityZones,ParameterValue=us-east-1a\\,us-east-1b
-:::
-1. Wait until the stack creation is completed by running the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-cross-stacks-vpc
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to CloudFormation in the console and click **Create stack With new resources (standard)**.
-1. In **Prepare template** select **Template is ready**.
-1. In **Template source** select **Upload a template file**.
-1. Choose a file `vpc.yaml`.
-1. Enter a **stack name**. For example, `cfn-workshop-cross-stacks-vpc`.
-1. For the **AvailabilityZones** parameter, select **2 AZs**.
-1. You can leave the rest of the parameters **default**.
-1. Navigate through the wizard leaving everything default.
-1. On the Review page, scroll down to the bottom and click on **Submit**.
-::::
-:::::
-
-#### Create IAM Stack
-
-##### 1. Prepare the IAM role template
-
-1. Open `iam.yaml` file.
-1. Copy the lines [4-5] to the **Outputs** section of the template:
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=4-5}
- Outputs:
- WebServerInstanceProfile:
- Value: !Ref WebServerInstanceProfile
- Export:
- Name: cfn-workshop-WebServerInstanceProfile
-:::
-
-##### 2. Deploy the IAM Stack
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Let's **Create Stack** by using the following AWS CLI command. The template requires you to specify `CAPABILITY_IAM` capability for creating IAM resources.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-cross-stacks-iam \
---template-body file://iam.yaml \
---capabilities CAPABILITY_IAM
-:::
-1. Wait until the stack creation is completed by running the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-cross-stacks-iam
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to CloudFormation in the console and click **Create stack With new resources (standard)**.
-1. In **Prepare template** select **Template is ready**.
-1. In **Template source** select **Upload a template file**.
-1. Choose a file `iam.yaml`.
-1. Enter a **stack name**. For example, `cfn-workshop-cross-stacks-iam`.
-1. Click **Next**.
-1. Navigate through the wizard leaving everything default.
-1. **Acknowledge IAM capabilities** and click on **Submit**.
-::::
-:::::
-
-#### Create EC2 Cross-stack
-
-##### 1. Prepare the EC2 template
-The concept of the **Cross Stack** is to use intrinsic functions to import previously exported values instead of using
-**Parameters**. Therefore, the first change to make to the `ec2.yaml` is to remove the parameters that will no longer be used;
-`SubnetId`, `VpcId`, and `WebServerInstanceProfile`.
-
-##### 2. Update the Parameters section
-
-Update the **Parameters** section to look as follows:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-Parameters:
- EnvironmentType:
- Description: 'Specify the Environment type of the stack.'
- Type: String
- Default: Test
- AllowedValues:
- - Dev
- - Test
- - Prod
- ConstraintDescription: 'Specify either Dev, Test or Prod.'
-
- AmiID:
- Type: AWS::SSM::Parameter::Value
- Description: 'The ID of the AMI.'
- Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-:::
-
-##### 3. Update WebServerInstance resource
-
-Next, we need to update the `Ref` in the template to import the exported values from the vpc and iam stacks created earlier.
-We perform this import by using the [Fn::ImportValue](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) intrinsic function.
-
-Update WebServerInstance resource in the Resources section of the `ec2.yaml` template:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=5-8}
-WebServerInstance:
- Type: AWS::EC2::Instance
- {...}
- Properties:
- SubnetId: !ImportValue cfn-workshop-PublicSubnet1
- IamInstanceProfile: !ImportValue cfn-workshop-WebServerInstanceProfile
- ImageId: !Ref AmiID
- InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref EnvironmentType, InstanceType]
- {...}
-:::
-
-##### 4. Update the security group
-Finally, update the security group resource similarly. Update `WebServerSecurityGroup` resource in the **Resources** section of the `ec2.yaml` template, line [19].
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=19}
-WebServerSecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Enable HTTP and HTTPS access
- SecurityGroupIngress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
- SecurityGroupEgress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
- - IpProtocol: tcp
- FromPort: 443
- ToPort: 443
- CidrIp: 0.0.0.0/0
- VpcId: !ImportValue cfn-workshop-VpcId
-:::
-
-##### 5. Deploy the EC2 Stack
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Let's **Create Stack** by using the following AWS CLI command. The template requires you to specify `CAPABILITY_IAM` capability for creating IAM resources.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-cross-stacks-ec2 \
---template-body file://ec2.yaml
-:::
-1. Wait until the stack creation is completed by running the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-cross-stacks-ec2
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to CloudFormation in the console and click **Create stack With new resources (standard)**.
-1. In **Prepare template** select **Template is ready**.
-1. In **Template source** select **Upload a template file**.
-1. Choose a file `ec2.yaml`.
-1. Enter a **stack name**. For example, `cfn-workshop-cross-stacks-ec2`.
-1. You can leave the rest of the parameters **default**.
-1. Navigate through the wizard leaving everything default.
-1. On the **Review page**, scroll down to the bottom and click on **Submit**.
-::::
-:::::
-
-#### 7. Test the deployment
-
-##### 1. Verify that application was deployed successfully
-
-Open a new browser window in private mode and enter the `WebsiteURL` (you can get the WebsiteURL from the **Outputs** tab of the EC2 stack in the CloudFormation console).
-You should see some instance metadata, similar to the picture below.
-
-
-
-##### 2. Log in to the instance using SSM Session Manager
-
-Verify that you can log in to the instance via Session Manager.
-
-If you not sure how to do that, follow the instructions from the [Session Manager](/basics/operations/session-manager#challenge) lab.
-
-### Clean up
-
-::alert[After the stack imports an output value, you can't delete the stack that is exporting the output value or modify the exported output value. All the imports must be removed before you can delete the exporting stack or modify the output value.]{type="info"}
-
-For example, you can not delete the **VPC stack** before you delete **EC2 stack**. You get following error message:
-
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Delete Stack** by running the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-cross-stacks-ec2
-:::
-1. Wait until the stack is deleted by using the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---stack-name cfn-workshop-cross-stacks-ec2
-:::
-1. Repeat steps (1-2) above for stacks: `cfn-workshop-cross-stacks-iam` and `cfn-workshop-cross-stacks-vpc`.
-::::
-::::tab{id="local" label="Local development"}
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the **EC2 stack**, for example `cfn-workshop-cross-stacks-ec2`.
-1. In the top right corner, click on **Delete**.
-1. In the pop-up window click on **Delete**.
-1. Hit the **refresh** button a few times until you see in the status **DELETE_COMPLETE**.
-1. Now you can delete **IAM** and **VPC** stack in any order as there are no more dependencies.
-::::
-:::::
-
----
-
-### Conclusion
-**Cross-stack references** allow you to create resources that can be used again and again in multiple stacks. All the stack needs
-to know is the **Export** name used. They allow the separation of roles and responsibilities. For example, a network team
-could create and supply an approved VPC design as a template. You deploy it as a stack and then just reference the Exports
-as needed. Similarly, a security team could do the same for IAM roles or EC2 security groups.
diff --git a/content/intermediate/templates/dynamic-references/index.ja.md b/content/intermediate/templates/dynamic-references/index.ja.md
deleted file mode 100644
index 976fe1a9e..000000000
--- a/content/intermediate/templates/dynamic-references/index.ja.md
+++ /dev/null
@@ -1,337 +0,0 @@
----
-title: "動的参照"
-weight: 300
----
-
-_ラボ実施時間 : 30分程度_
-
----
-
-### 概要
-このモジュールでは、CloudFormation テンプレートの[動的な参照](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html)を使用して、[AWS Systems Manager](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/what-is-systems-manager.html) (SSM)、[Parameter Store](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html)、[AWS Secrets Manager](https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/intro.html) を含む AWS サービスに保存されている外部値を参照する方法を学びます。
-
- 前のセクションで説明したように、CloudFormation テンプレートでは、AWS リソースの[ライフサイクルと所有権](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/best-practices.html) の基準とベストプラクティスを考慮し、一元化された場所に保存されている設定値を参照することもできます。Parameter Store は、構成データ管理のための安全な階層型ストレージを提供します。
-
-また、AWS CloudFormation テンプレートから機密情報を参照する必要がある場合もあります。[AWS Secrets Manager](https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/intro.html) を使用すると、データベースやその他のサービスの認証情報をプログラムで安全に暗号化、保存、取得できます。SSM [Secure String パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm-secure-strings)を使用して機密データを保存および参照することもできます。
-
-動的参照を使用すると、CloudFormation はスタックおよび [変更セット](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html)操作中に、必要に応じて指定された参照値を取得します。ただし、CloudFormation が実際の参照値を保存することはありません。
-
-### 取り上げるトピック
-このラボを修了すると、次のことができるようになります。
-
-* CloudFormation テンプレートの外部値にアクセスするための*動的参照文字列*を作成
-* 特定のバージョン、または*最新*バージョンの Parameter Store パラメータを取得
-* Secrets Manager シークレットの特定のバージョンを取得
-* JSON データ形式を使用するシークレットから特定のキーの値を抽出
-
-### ラボを開始
-
-#### Parameter Store の動的リファレンス
-開発チームにライフサイクル環境を提供する必要があるシナリオを考えてみましょう。このプラクティスには、多くの場合、最新のオペレーティングシステムアップデート、セキュリティの強化要件、必要なサードパーティのソフトウェアエージェントを含むカスタム [Amazon Machine Images](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/AMIs.html) (AMI) の構築と配布が含まれます。
-
-あなた (または組織のチーム) がカスタム AMI を作成したら、Parameter Store を使用して AMI の識別子を保存することができます。これにより、EC2 インスタンスを起動するときに使用する AMI をプログラムで指定しやすくなり、設定ミスの可能性が低くなります。
-
-このラボでは、AMI ID を永続化する Parameter Store パラメータを作成します。カスタム AMI の代わりに、選択したリージョンで利用できる最新の _Amazon Linux 2023 AMI, 64-bit x86_ を使用します。次に、テンプレートに記述した EC2 インスタンスの `ImageId` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-imageid)でパラメータを参照します。
-
-それでは、始めましょう!
-
-:::alert{type="info"}
-ワークショップの _AWS リージョン_ には **us-east-1 (バージニア北部)** を使用することをお勧めします。
-:::
-
-1. Amazon EC2 [コンソール](https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#LaunchInstances:)の _インスタンスを起動_ に移動し、使用する[リージョンを選択](https://docs.aws.amazon.com/ja_jp/awsconsolehelpdocs/latest/gsg/select-region.html)します。次に、最新の *Amazon Linux 2023 AMI (64 ビット x86)* を探し、AMI ID (例:`ami-abcd1234`) を書き留めます。この値は次のステップで使用します。
-
-
-
-2. [AWS Command Line Interface](https://aws.amazon.com/jp/cli/) (CLI) を使用してパラメータを作成します。以下に示すコマンドを実行するときは、必ず `YOUR_AMI_ID` と `YOUR_REGION` のプレースホルダーを必要な値に置き換えてください。必要値の入力時には、特定の AWS リージョンを指定します。リージョンの詳細については、[リージョンエンドポイント](https://docs.aws.amazon.com/ja_jp/general/latest/gr/rande.html#regional-endpoints) の表の **コード** をご参照ください。また、必ず、前のステップで AMI を選択したときのリージョンと同一のリージョンを使用してください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ssm put-parameter \
- --name "/golden-images/amazon-linux-2" \
- --value YOUR_AMI_ID \
- --type "String" \
- --region YOUR_REGION
-:::
-
-::alert[CloudFormation を使用して、`String` または `StringList` タイプの Parameter Store パラメータを作成可能です。詳細については、[AWS::SSM::Parameter](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html) のドキュメントをご覧ください。]{type="info"}
-
-3. `put-parameter` コマンドが成功すると、SSM は `Version` と `Tier` を返します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"Version": 1,
-"Tier": "Standard"
-:::
-
-4. 次の手順に従って、テンプレートに記述した EC2 インスタンスのパラメータへの動的参照を作成します。
-
- 1. `code/workspace/dynamic-references` ディレクトリに移動します。
- 1. お好みのテキストエディタで `ec2-instance.yaml` CloudFormation テンプレートを開きます。
- 1. テンプレート内の `AWS::EC2::Instance` リソースタイプブロックを探し、`Properties` セクションのプロパティに `ImageId` プロパティとパラメータへの動的参照を追加してテンプレートを更新します。
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- ImageId: '{{resolve:ssm:/golden-images/amazon-linux-2}}'
- :::
-
-上記の動的参照を使って、スタックの実行時に `/golden-images/amazon-linux-2` パラメータの `LATEST` バージョンの値を解決します。
-
-::alert[CloudFormation は、[動的参照](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm)による[パブリックパラメータ](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/parameter-store-finding-public-parameters.html)をサポートしていません。[SSM パラメータタイプ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-ssm-parameter-types)を使用してパブリックパラメータの値を取得することができます。]{type="info"}
-
-5. いよいよスタックを作成しましょう! 以下の手順に従ってください。
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **Code Editor ターミナル** で `code/workspace/dynamic-references` ディレクトリに移動します
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/dynamic-references
- :::
- 2. AWS CLI を使用してスタックを作成します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
- --stack-name cfn-workshop-dynamic-references-ec2 \
- --template-body file://ec2-instance.yaml
- :::
- 1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-dynamic-references-ec2/3fabc340-e74e-11ed-9b33-0a550dedb7a1"
- :::
- 1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移 し **新しいリソースを使用 (標準)** を選択します。
- 1. **テンプレートの準備** セクションで、 **テンプレート準備完了** を選択します。
- 1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
- 1. ファイル `ec2-instance.yaml` を選択します。
- 1. スタック名を入力します。例えば、`cfn-workshop-dynamic-references-ec2` を入力します。
- 1. **スタックオプションの設定** ページはデフォルト値のまま、 **次へ** をクリックします。
- 1. スタックの **レビュー <スタック名>** ページで、一番下までスクロールし、 **送信** をクリックします。
- 1. スタックの **CREATE_COMPLETE** ステータスが表示されるまでページを更新してください。
- ::::
- :::::
-
- ::alert[SSM パラメータへの動的参照を使用して、特定のパラメータバージョンを指すこともできます。例えば、CloudFormation にパラメータのバージョン `1` を解決させるには、`ImageId: '{{resolve:ssm:/golden-images/amazon-linux-2:1}}'` を使用します。特定のバージョンへの動的参照をロックすると、スタックの更新時にリソースが意図せず更新されることを防止するのに役立ちます。]{type="info"}
-
-6. EC2 インスタンスに使用したイメージの ID が、Parameter Store パラメータに保存したイメージ ID と一致することを確認します。まず、CloudFormation コンソールの _リソース_ タブに移動して EC2 インスタンス ID を確認します。EC2 インスタンスの物理 ID を探し、その値を書き留めます。次に、以下のコマンドを実行します (コマンドを実行する前に、`YOUR_INSTANCE_ID` と `YOUR_REGION` プレースホルダーを置き換えてください)。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ec2 describe-instances \
---instance-ids YOUR_INSTANCE_ID \
---region YOUR_REGION \
---query 'Reservations[0].Instances[0].ImageId'
-:::
-7. `describe-instances` コマンドが正常に送信された場合、EC2 は `ImageID` を返します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"ami-02396cdd13e9a1257"
-:::
-
-おめでとうございます!Parameter Store を使用して、動的参照の利用方法の例を学習しました。
-
-#### AWS Secrets Manager の動的参照
-[AWS Secrets Manager](https://aws.amazon.com/jp/secrets-manager/) は、データベース認証情報などの認証情報を保護するのに役立ちます。AWS Secrets Manager を用いると、コードにシークレットをハードコーディングしなくても、後でプログラムで利用できるようになります。例えば、[AWS Lambda](https://aws.amazon.com/jp/lambda/) 関数を作成して、[Amazon Relational Database Service (RDS)](https://aws.amazon.com/jp/rds/) データベースインスタンスのデータベース接続情報 (ホスト名やポートなど) を使用します。
-
-このラボでは、Secrets Manager を使用してデータベースの*ホスト名*、*ポート*、*ユーザー名*、および*パスワード*を保存します。次に、動的参照を使用して、テンプレートに記述する `AWS::Lambda::Function` リソースから*ホスト名*と*ポート*情報を読み取ります。
-
-それでは、始めましょう!次に示す手順に従って実行します。
-
-1. Amazon RDS データベースを作成し、接続情報を AWS Secrets Manager にシークレットとして保存します。
- 1. `code/workspace/dynamic-references` ディレクトリにいることを確認します。
- 1. お好みのテキストエディタで `database.yaml` CloudFormation テンプレートを開きます。
- 1. テンプレート内の次のリソースに注意してください。
- 1. `AWS::RDS::DBInstance` タイプのリソース。本リソースを使用して Amazon RDS インスタンスを記述します。
- :::alert{type="info"}
- `AWS::RDS::DBInstance`タイプのリソースで (このラボの例のように) `DBClusterIdentifier` プロパティを指定していない場合、[削除ポリシー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html)が明示的に定義されていない場合、削除ポリシーはデフォルトで `Snapshot` になり、CloudFormation はリソースを削除する前にリソースのスナップショットを作成します。このラボでは、リソースの `DeletionPolicy` を `Delete` に設定して、削除時にスナップショットの作成をスキップします。
- :::
- 1. `AWS::SecretsManager::Secret` タイプのリソース。データベース接続パラメータを JSON キーと値のペアとして、`DatabaseConnParams` という名前のシークレットに保存します。
- :::code{language=json showLineNumbers=true showCopyAction=false lineNumberStart=47}
- {
- "RDS_HOSTNAME": "${Database.Endpoint.Address}",
- "RDS_PORT": "${Database.Endpoint.Port}",
- "RDS_USERNAME": "${DBUsername}",
- "RDS_PASSWORD": "${DBPassword}"
- }
- :::
-2. データベーススタックをデプロイするには、以下の手順に従います。
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **Code Editor ターミナル** で `code/workspace/dynamic-references` ディレクトリに移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/dynamic-references
- :::
- 1. AWS CLI を使用してスタックを作成します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。`DBUsername` パラメータと `DBPassword` パラメータの値を入力します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
- --stack-name cfn-workshop-dynamic-references-database \
- --template-body file://database.yaml \
- --parameters ParameterKey=DBUsername,ParameterValue='admin' \
- ParameterKey=DBPassword,ParameterValue='wjznf74irj831o9'
- :::
- 1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-dynamic-references-database/5b6b44f0-e750-11ed-af8c-12a600715c03"
- :::
- 1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。最新のスタックステータスを確認するには、定期的に更新を選択する必要があります。
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移し、 **新しいリソースを使用 (標準)** を選択します。
- 1. **テンプレートの準備** セクションで、 **テンプレートの準備完了** を選択します。
- 1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
- 1. ファイル `database.yaml` を選択します。
- 1. スタック名を入力します。例えば、`cfn-workshop-database-stack` と入力します。
- 1. `DBUserName` には、DB インスタンスのプライマリユーザー名を指定します。
- 1. `DBPassword` には、プライマリユーザーのパスワードを指定します。
- :::alert{type="info"}
- 入力したユーザー名またはパスワードが無効な場合は、テンプレートのパラメーターの詳細を確認してください。
- :::
- 1. **スタックオプションの設定** ページはデフォルト値のまま、 **次へ** をクリックします。
- 1. スタックの **レビュー <スタック名>** ページで、一番下までスクロールして、 **送信** をクリックします。
- 1. スタックの `CREATE_COMPLETE` ステータスが表示されるまでページを更新してください。
- ::::
- :::::
-
-1. 次に、AWS Lambda 関数を作成し、以前に作成した Secrets Manager シークレットへの動的参照を使用して、いくつかのデータベース接続パラメータを[環境変数](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html)として Lambda 関数に読み取ります。
- 1. `code/workspace/dynamic-references` ディレクトリにいることを確認します。
- 1. お好みのテキストエディタで `lambda-function.yaml` CloudFormation テンプレートを開きます。
- 1. テンプレートには `AWS::Lambda::Function` リソースタイプが記述されています。`Properties` セクションに `Environment` プロパティを追加し、先ほど作成した AWS Secret Manager シークレットへの動的参照を使用する変数を追加してテンプレートを更新します。
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- Environment:
- Variables:
- RDS_HOSTNAME: '{{resolve:secretsmanager:DatabaseConnParams:SecretString:RDS_HOSTNAME}}'
- RDS_PORT: '{{resolve:secretsmanager:DatabaseConnParams:SecretString:RDS_PORT}}'
- :::
-1. Lambda スタックをデプロイするには、以下の手順に従います。
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. **Code Editor ターミナル** で `code/workspace/dynamic-references` ディレクトリに移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/dynamic-references
- :::
- 1. AWS CLI を使用してスタックを作成します。必須パラメータ `--stack-name` と `--template-body` と `--capabilities` はあらかじめ入力されています。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
- --stack-name cfn-workshop-dynamic-references-lambda \
- --template-body file://lambda-function.yaml \
- --capabilities CAPABILITY_IAM
- :::
- 1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-dynamic-references-lambda/7e465860-e751-11ed-aa31-0a674dce3c49"
- :::
- 1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。最新のスタックステータスを確認するには、定期的に更新を選択する必要があります。
- ::::
- ::::tab{id="local" label="ローカル開発"}
- 1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動し **新しいリソースを使用 (標準)** を選択します。
- 1. **テンプレートの準備** セクションで、 **テンプレートの準備完了** を選択します。
- 1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** をクリックします。
- 1. ファイル `lambda_function.yaml` を選択します。
- 1. スタック名を入力します。例えば、`cfn-workshop-lambda-stack` と入力し、 **次へ** をクリックします。
- 1. **スタックオプションの設定** ページはデフォルト値のまま、 **次へ** をクリックします。
- 1. **レビュー <スタック名>** ページで、一番下までスクロールし、 **AWS CloudFormation が IAM リソースを作成する可能性があることを認識しています** チェックボックスをチェックし、 **送信** をクリックします。
- 1. スタックのステータスが `CREATE_COMPLETE` になるまでページを更新します。
- ::::
- :::::
-
-先ほど使用したテンプレートでは、データベース接続パラメーターはスタックの実行時に動的文字列を使用して取得されます。`RDS_HOSTNAME` などの特定のキーの値を、`'{{resolve:secretsmanager:DatabaseConnParams:SecretString:RDS_HOSTNAME}}'` で取得しました。なお、`DatabaseConnParams` はシークレット ID を示しています。
-
-::alert[AWS Secrets Manager のシークレットには、暗号化されたシークレット値のコピーを保持する [*versions*](https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/getting-started.html#term_version) があります。シークレットの値を変更すると、Secrets Manager は新しいバージョンを作成します。シークレットには常に、現在のシークレット値であるステージングラベル `AWSCURRENT` のバージョンがあります。必要に応じて、*バージョンステージ*または*バージョン ID* を指定して、この文字列を次のように変更できます: `'{{resolve:secretsmanager:prod-DatabaseConnParams:SecretString:RDS_HOSTNAME::}}'`。バージョンを指定しない場合、CloudFormation はステージ `AWSCURRENT` に関連するシークレットをデフォルトで解決します。]{type="info"}
-
-5. 作成したサンプルの Lambda 関数を呼び出すと、関数は `RDS_HOSTNAME` と `RDS_PORT` 環境変数をフェッチし、それらの値を出力します。まず、CloudFormation コンソールの _リソース_ タブに移動し、Lambda 関数名を見つけます。Lambda 関数の物理 ID を探し、その値を書き留めます。次に、次のコマンドを使用し、データベース接続パラメーターを Lambda 関数に渡していることを確認します (`YOUR_FUNCTION_NAME` を Lambda 関数名に、`YOUR_REGION` を必要な値に置き換えてください)。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws lambda invoke \
- --function-name YOUR_FUNCTION_NAME \
- --region YOUR_REGION \
- output.json
-:::
-
-次のコマンドを使用して、上記コマンドの出力を表示します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cat output.json
-:::
-
-output.json の内容が出力されます。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"Database: cfn-workshop-dynamic-references-database-database-rrxa105iggu0.csxwxntvtkdn.us-east-1.rds.amazonaws.com:3306"
-:::
-
-おめでとうございます! AWS Secrets Manager で動的参照を使用する方法を学びました。
-
-### チャレンジ
-この演習では、*動的参照*についての理解を深めます。
-
-AWS Lambda では、`MemorySize` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-memorysize)で、[関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)のメモリ構成をサポートします。ここでのタスクは、AWS CLI で Parameter Store パラメータを作成することです。ここで、`Lambda_memory_size.yaml` テンプレートに記述する Lambda 関数に使用するメモリサイズを設定します。次に、作成したパラメーターのバージョン `1` への動的参照を作成し、テンプレートを使用してスタックを作成してビルドした内容が機能することを確認します。`cfn-workshop-dynamic-references-lambda-memory` スタックを呼び出します。Parameter Store パラメータは、スタックの作成時に選択したものと同じ AWS リージョンに作成します。
-
-:::expand{header= "ヒントが必要ですか?"}
-1. CloudFormation [ユーザーガイド](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-memorysize) を参照し、Lambda 関数の `MemorySize` 設定を指定する方法を理解してください。
-1. 特定のバージョンの Parameter Store パラメータへの動的参照文字列を作成する方法については、CloudFormation [ユーザーガイド](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm-pattern)をご参照ください。
-:::
-
-::::expand{header="解決策を確認しますか?"}
-1. 以下のコマンドを使用して、必要なメモリ設定を指定する Parameter Store パラメータを作成します (`YOUR_REGION`を必要な値に置き換えてください)。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ssm put-parameter \
---name "/lambda/memory-size" \
---value "256" \
---type "String" \
---region YOUR_REGION
-:::
-1. お好みのテキストエディタで `code/workspace/dynamic-references/lambda-memory-size.yaml` テンプレートを開きます。パラメータへの動的参照を使用して `MemorySize` プロパティを含む以下の例を `Resources` セクションに追加して、テンプレートを更新します。
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-HelloWorldFunction:
- Type: AWS::Lambda::Function
- Properties:
- Role: !GetAtt FunctionExecutionRole.Arn
- Handler: index.handler
- Runtime: python3.9
- MemorySize: '{{resolve:ssm:/lambda/memory-size:1}}'
- Code:
- ZipFile: |
- import os
- def handler(event, context):
- return "Hello World!"
-:::
-1. 以前の Lambda 関数と同様に、`cfn-workshop-dynamic-references-lambda-memory` CloudFormation スタックを作成して、テンプレートに記述して更新したリソースをプロビジョニングします。
-1. [AWS コマンドラインインターフェイス](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/gettingstarted-awscli.html)(CLI) を実行して、MemorySize の SSM パラメータ値を使用して Lambda 関数が作成されたことを確認します。`--query` パラメータはすでに入力されています (`YOUR_REGION` を必要な値に置き換えてください)。
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-aws lambda list-functions --query 'Functions[*].[FunctionName,MemorySize,Environment]' --region YOUR_REGION
-:::
-1. 成功すると、`aws lambda list-functions` には少なくとも 2 つの関数の詳細が表示されるはずです。1 つは RDS 環境変数を使用して作成したもので、もう 1 つは `MemorySize` を 256 に設定したものです。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[
- [
- "cfn-workshop-dynamic-references-HelloWorldFunction-xhsdJOc49hhX",
- 256,
- null
- ],
- [
- "cfn-workshop-dynamic-references-l-DatabaseFunction-XO1tBoIQL3xT",
- 128,
- {
- "Variables": {
- "RDS_HOSTNAME": "cfn-workshop-dynamic-references-database-database-eyffmthgvwih.csxwxntvtkdn.us-east-1.rds.amazonaws.com",
- "RDS_PORT": "3306"
- }
- }
- ]
-]
-:::
-
-解決策は、`code/solutions/dynamic-references/lambda-memory-size.yaml` サンプルテンプレートにあります。
-::::
-
-### クリーンアップ
-1. `cfn-workshop-dynamic-references-lambda` と `cfn-workshop-dynamic-references-lambda-memory` で作成した Lambda 関数に関連付けられた CloudWatch ロググループを削除します (チャレンジセクションの Lambda 関数を呼び出した場合は、関連するロググループが存在しているはずです)。
-
- スタックごとに、CloudFormation コンソールの **リソース** タブに移動して Lambda 関数名を検索し、Lambda 関数の物理 ID を探して、その値を書き留めます。次に、作成した各 Lambda 関数に対して以下のコマンドを使用します (`YOUR_FUNCTION_NAME` を Lambda 関数名に置き換え、`YOUR_REGION` を必要な値に置き換えてください)。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws logs delete-log-group \
---log-group-name /aws/lambda/YOUR_FUNCTION_NAME \
---region YOUR_REGION
-:::
-1. 次のコマンドを使用して、AMI ID と `MemorySize` 設定を保存するために作成した 2 つの Parameter Store パラメータを削除します (`YOUR_REGION` は必要な値に置き換えてください)。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ssm delete-parameters \
---names "/golden-images/amazon-linux-2" "/lambda/memory-size" \
---region YOUR_REGION
-:::
-1. 次に、CloudFormation コンソールで、最後に作成したスタック (例: `cfn-workshop-dynamic-references-lambda-memory`) を選択します。
-1. **削除** を選択した後、 **スタックの削除** をクリックして確定します。
-1. このラボで作成した他のスタックについても上記の手順を繰り返します。具体的には、`cfn-workshop-dynamic-references-lambda`、`cfn-workshop-dynamic-references-database`、`cfn-workshop-dynamic-references-ec2` スタックです。
-
----
-### まとめ
-動的参照を使用して、AWS Systems Manager Parameter Store や AWS Secrets Manager などのサービスで保存および管理する外部値を指定する方法がわかりました。詳しい情報については、[動的な参照を使用してテンプレート値を指定する](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html)をご参照ください。
diff --git a/content/intermediate/templates/dynamic-references/index.md b/content/intermediate/templates/dynamic-references/index.md
deleted file mode 100644
index 74ac37651..000000000
--- a/content/intermediate/templates/dynamic-references/index.md
+++ /dev/null
@@ -1,332 +0,0 @@
----
-title: "Dynamic References"
-weight: 300
----
-
-_Lab Duration: ~30 minutes_
-
----
-
-### Overview
-In this module, you will learn how to use [dynamic references](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html) in your CloudFormation template to reference external values stored in AWS services that include [AWS Systems Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/what-is-systems-manager.html) (formerly known as SSM) [Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html), and [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html).
-
-As you describe, in your CloudFormation templates, AWS resources by taking into account [lifecycle and ownership](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html) criteria and best practices, you might also want to reference configuration values stored in a centralized place. Parameter Store provides secure, hierarchical storage for configuration data management.
-
-In other cases, you might be required to reference sensitive information in your AWS CloudFormation templates. [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) helps you to securely encrypt, store, and retrieve credentials for your databases and other services programmatically. You can also choose to use Parameter Store [secure string parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm-secure-strings) to store and reference sensitive data.
-
-When you use a dynamic reference, CloudFormation retrieves the value of the specified reference when necessary during stack and [change set](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html) operations. However, CloudFormation never stores the actual reference value.
-
-### Topics Covered
-By the end of this lab, you will be able to:
-
-* Compose a *dynamic reference string* to access an external value in your CloudFormation template.
-* Retrieve a specific version, or the *latest* version of a Parameter Store parameter.
-* Retrieve a specific version of a Secrets Manager secret.
-* Extract a value for a specific key, from a secret that uses a JSON data format.
-
-### Start Lab
-
-#### Dynamic References for Parameter Store
-Consider a scenario where you are required to provide life cycle environments for your development teams. This practice often involves practices that include building and distributing custom [Amazon Machine Images](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) (AMIs) with the latest operating system updates, hardening requirements, and third-party software agents you require.
-
-After you (or a team in your organization) builds a custom AMI, you can choose to use Parameter Store to store the identifier of the AMI. This makes it easier for you to programmatically point to an AMI you wish to use when you launch EC2 instances, thus reducing the likelihood of configuration mistakes.
-
-In this lab, you will create a Parameter Store parameter to persist an AMI ID: instead of a custom AMI, you will use the latest _Amazon Linux 2023 AMI, 64-bit x86_ available in a region of your choice. You will then reference your parameter in the `ImageId` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-imageid) of an EC2 instance that you describe in a template.
-
-Let’s get started!
-
-:::alert{type="info"}
-We recommend using **us-east-1 (N. Virginia)** as the _AWS Region_ for the workshop.
-:::
-
-1. Navigate to the _Launch an Instance_ Amazon EC2 [Console](https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#LaunchInstances:), and [choose the Region](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/select-region.html) you wish to use. Next, locate the latest *Amazon Linux 2023 AMI, (64-bit x86)*, and note the AMI ID (e.g., `ami-abcd1234`). You will use this value in the next step.
-
-
-
-2. Create your parameter using the [AWS Command Line Interface](https://aws.amazon.com/cli/) (CLI). When you run the command shown next, please make sure to replace `YOUR_AMI_ID` and `YOUR_REGION` placeholders with values you need. For values, you can specify for the AWS region, see **Code** in the [Regional endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints) table; make sure to use the same region you chose when you selected the AMI to use in the previous step:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ssm put-parameter \
---name "/golden-images/amazon-linux-2" \
---value YOUR_AMI_ID \
---type "String" \
---region YOUR_REGION
-:::
-
-::alert[You can choose to create Parameter Store parameters of the type `String` or `StringList` using CloudFormation. For more details, check the documentation for [AWS::SSM::Parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html).]{type="info"}
-
-3. If the `put-parameter` command was successful, SSM will return `Version` and `Tier`.
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"Version": 1,
-"Tier": "Standard"
-:::
-
-4. Follow steps shown next to create a dynamic reference to your parameter in an EC2 instance you describe in a template:
-
- 1. Change directory to `code/workspace/dynamic-references`.
- 2. Open the `ec2-instance.yaml` CloudFormation template in your favorite text editor.
- 3. Locate the `AWS::EC2::Instance` resource type block in the template; update the template by appending, to properties in the `Properties` section, the `ImageId` property and a dynamic reference to your parameter:
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- ImageId: '{{resolve:ssm:/golden-images/amazon-linux-2}}'
- :::
-
-With the dynamic reference above, you describe the intent of resolving the `LATEST` version of your `/golden-images/amazon-linux-2` parameter during stack runtime.
-
-::alert[CloudFormation does not support [public parameters](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-finding-public-parameters.html) [in dynamic references](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm). You can choose to use [SSM Parameter Types](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-ssm-parameter-types) to retrieve the value for a public parameter.]{type="info"}
-
-5. It’s now time to create your stack! Follow steps below:
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. In the **Code Editor terminal** navigate to `code/workspace/dynamic-references`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/dynamic-references
- :::
- 1. Use the AWS CLI to create the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
- --stack-name cfn-workshop-dynamic-references-ec2 \
- --template-body file://ec2-instance.yaml
- :::
- 1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-dynamic-references-ec2/3fabc340-e74e-11ed-9b33-0a550dedb7a1"
- :::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and wait for stack status to reach the **CREATE_COMPLETE** status. You need to periodically select Refresh to see the latest stack status.
- ::::
- ::::tab{id="local" label="Local development"}
- 1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/), and choose **Create stack With new resources (standard)**.
- 1. In **Prepare template**, select **Template is ready**.
- 1. In **Template source**, select **Upload a template file**.
- 1. Choose the file `ec2-instance.yaml`.
- 1. Enter a Stack name. For example, `cfn-workshop-dynamic-references-ec2`.
- 1. Choose to use default values for **Configure stack options**, and choose **Next**.
- 1. On the **Review ** page for your stack, scroll down to the bottom, and choose **Submit**.
- 1. Wait for stack status to reach the **CREATE_COMPLETE**. You need to periodically select Refresh to see the latest stack status.
- ::::
- :::::
- ::alert[You can also use dynamic references to an SSM parameter to point a specific parameter version. For example, to have CloudFormation resolve version `1` of your parameter, you use: `ImageId: '{{resolve\:ssm:/golden-images/amazon-linux-2:1}}'`. When you lock a dynamic reference to a specific version, this helps to prevent unintentional updates to your resource when you update your stack.]{type="info"}
-
-6. Verify that the ID of the image you used for your EC2 instance matches the image ID you stored in your Parameter Store parameter. First, locate the EC2 Instance ID by navigating to the _Resources_ tab in the CloudFormation Console: look for the Physical ID of your EC2 Instance, and note its value. Next, run the following command (replace the `YOUR_INSTANCE_ID` and `YOUR_REGION` placeholder before you run the command):
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ec2 describe-instances \
---instance-ids YOUR_INSTANCE_ID \
---region YOUR_REGION \
---query 'Reservations[0].Instances[0].ImageId'
-:::
-7. If the `describe-instances` command was successfully sent, EC2 will return `ImageId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"ami-02396cdd13e9a1257"
-:::
-
-Congratulations! You learned how to use dynamic references with an example using Parameter Store.
-
-#### Dynamic References for AWS Secrets Manager
-[AWS Secrets Manager](https://aws.amazon.com/secrets-manager) helps you secure your credentials, such as database credentials for example, so that you can consume them later programmatically without hard-coding secrets in your code. For example, you create an [AWS Lambda](https://aws.amazon.com/lambda/) function to consume your database connection information, such as hostname and port, for your [Amazon Relational Database Service (RDS)](https://aws.amazon.com/rds/) database instance.
-
-In this lab, you will use Secrets Manager to store database *hostname*, *port*, *username*, and *password*. Next, you will use dynamic references to read *hostname* and *port* information from an `AWS::Lambda::Function` resource you will describe in a template.
-
-Let’s get started! Choose to follow steps shown next:
-
-1. First, you will create an Amazon RDS database, and store connection information as a secret in AWS Secrets Manager:
- 1. Make sure you are in the `code/workspace/dynamic-references` directory.
- 2. Open the `database.yaml` CloudFormation template in your favorite text editor.
- 3. Note the following resources in the template:
- 1. The resource of type `AWS::RDS::DBInstance`, with which you describe your Amazon RDS instance.
- :::alert{type="info"}
- For resources of the type `AWS::RDS::DBInstance` that don't specify the `DBClusterIdentifier` property (as in the example for this lab), if a [deletion policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) is not explicitly defined, the deletion policy defaults to `Snapshot`, and CloudFormation creates a snapshot for the resource before deleting it. In this lab, `DeletionPolicy` for the resource is set to `Delete` to skip snapshot creation on delete.
- :::
- 1. The resource of type `AWS::SecretsManager::Secret`, where you will store database connection parameters, as JSON key-value pairs, in a secret named `DatabaseConnParams`:
- :::code{language=json showLineNumbers=true showCopyAction=false lineNumberStart=47}
- {
- "RDS_HOSTNAME": "${Database.Endpoint.Address}",
- "RDS_PORT": "${Database.Endpoint.Port}",
- "RDS_USERNAME": "${DBUsername}",
- "RDS_PASSWORD": "${DBPassword}"
- }
- :::
-2. To deploy the Database stack, follow the steps below:
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. In the **Code Editor terminal** navigate to `code/workspace/dynamic-references`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/dynamic-references
- :::
- 1. Use the AWS CLI to create the stack. The required parameters `--stack-name` and `--template-body` have been pre-filled for you. Enter the `DBUsername` and `DBPassword` from the CloudFormation template file into the command parameters.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
- --stack-name cfn-workshop-dynamic-references-database \
- --template-body file://database.yaml \
- --parameters ParameterKey=DBUsername,ParameterValue='admin' \
- ParameterKey=DBPassword,ParameterValue='wjznf74irj831o9'
- :::
- 1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-dynamic-references-database/5b6b44f0-e750-11ed-af8c-12a600715c03"
- :::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and wait for stack status to reach the **CREATE_COMPLETE** status. You need to periodically select Refresh to see the latest stack status.
- ::::
- ::::tab{id="local" label="Local development"}
- 1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/), and choose **Create stack With new resources (standard)**.
- 1. In **Prepare template**, select **Template is ready**.
- 1. In **Template source**, select **Upload a template file**.
- 1. Choose the file `database.yaml`.
- 1. Enter a Stack name. For example, `cfn-workshop-dynamic-references-database`.
- 1. For `DBUsername`, specify the primary username for the DB instance.
- 1. For `DBPassword`, specify the password for the primary user.
- :::alert{type="info"}
- Check the parameter details in the template if the username or password you enter is invalid.
- :::
- 1. Choose to use default values for **Configure stack options**, and choose **Next**.
- 1. On the **Review ** page for your stack, scroll down to the bottom, and choose **Submit**.
- 1. Wait for stack status to reach the **CREATE_COMPLETE**. You need to periodically select Refresh to see the latest stack status.
- ::::
- :::::
-
-3. Next, you will create an AWS Lambda Function, and read a number of database connection parameters as [Environment Variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) to your Lambda function, by using dynamic references to the Secrets Manager secret you created earlier.
- 1. Make sure you are in the `code/workspace/dynamic-references` directory.
- 2. Open the `lambda-function.yaml` CloudFormation template in your favorite text editor.
- 3. The template describes an `AWS::Lambda::Function` resource type; update the template by appending the `Properties` section with the `Environment` property, with variables using dynamic references to the AWS Secret Manager secret you created earlier:
- :::code{language=yaml showLineNumbers=false showCopyAction=true}
- Environment:
- Variables:
- RDS_HOSTNAME: '{{resolve:secretsmanager:DatabaseConnParams:SecretString:RDS_HOSTNAME}}'
- RDS_PORT: '{{resolve:secretsmanager:DatabaseConnParams:SecretString:RDS_PORT}}'
- :::
-4. To Deploy the Lambda stack, follow the steps below:
- :::::tabs{variant="container"}
- ::::tab{id="code-editor" label="Code Editor"}
- 1. In the **Code Editor terminal** navigate to `code/workspace/dynamic-references`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/dynamic-references
- :::
- 1. Use the AWS CLI to create the stack. The required parameters `--stack-name`, `--template-body` and `--capabilities` have been pre-filled for you.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack \
- --stack-name cfn-workshop-dynamic-references-lambda \
- --template-body file://lambda-function.yaml \
- --capabilities CAPABILITY_IAM
- :::
- 1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-dynamic-references-lambda/7e465860-e751-11ed-aa31-0a674dce3c49"
- :::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and wait for stack status to reach the **CREATE_COMPLETE** status. You need to periodically select Refresh to see the latest stack status.
- ::::
- ::::tab{id="local" label="Local development"}
- 1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/), and choose **Create stack With new resources (standard)**.
- 1. In **Prepare template**, select **Template is ready**.
- 1. In **Template source**, select **Upload a template file**.
- 1. Choose the file `lambda-function.yaml`.
- 1. Enter a Stack name. For example, `cfn-workshop-dynamic-references-lambda`, and choose **Next**.
- 1. Choose to use default values for **Configure stack options**, and choose **Next**.
- 1. On the **Review ** page, scroll down to the bottom and tick **I acknowledge that AWS CloudFormation might create IAM resources** check box, then click on **Submit**.
- 1. Wait for stack status to reach the **CREATE_COMPLETE**. You need to periodically select Refresh to see the latest stack status.
- ::::
- :::::
-
-In the template you just used, database connection parameters are retrieved during stack runtime using a dynamic string. You retrieved the value for a given key, such as `RDS_HOSTNAME`, with: `'{{resolve:secretsmanager:DatabaseConnParams:SecretString:RDS_HOSTNAME}}'`, where `DatabaseConnParams` is the secret ID.
-
-::alert[A secret in AWS Secrets Manager has [*versions*](https://docs.aws.amazon.com/secretsmanager/latest/userguide/getting-started.html#term_version) holding copies of the encrypted secret value. When you change the secret value, Secrets Manager creates a new version. A secret always has a version with the staging label `AWSCURRENT`, which is the current secret value. If required, you can modify this string specifying a *version-stage* or *version-id* as such: `'{{resolve:secretsmanager:prod-DatabaseConnParams:SecretString:RDS_HOSTNAME::}}'`. When you do not specify a version, CloudFormation defaults to resolving the secret associated with the stage `AWSCURRENT`.]{type="info"}
-
-5. When you invoke the example Lambda function you created, the function fetches `RDS_HOSTNAME` and `RDS_PORT` environment variables, and prints out their values. First, locate the Lambda function name by navigating to the _Resources_ tab in the CloudFormation Console: look for the Physical ID of your Lambda function, and note its value. Next, verify you are passing database connection parameters to your Lambda function by invoking it with the following command (replace `YOUR_FUNCTION_NAME` with your Lambda function name and `YOUR_REGION` with the value you need):
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws lambda invoke \
---function-name YOUR_FUNCTION_NAME \
---region YOUR_REGION \
-output.json
-:::
-
-Print the output for the above command using the following command:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cat output.json
-:::
-
-The contents of output.json will be displayed
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"Database: cfn-workshop-dynamic-references-database-database-rrxa105iggu0.csxwxntvtkdn.us-east-1.rds.amazonaws.com:3306"
-:::
-
-Congratulations! You learned how to use dynamic references with AWS Secrets Manager.
-
-### Challenge
-In this exercise, you will reinforce your understanding of *dynamic references.*
-
-AWS Lambda supports specifying memory configuration for a [function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html) with the `MemorySize` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-memorysize). Your task is to create a Parameter Store parameter with the AWS CLI, where you set the memory size to use for a Lambda function that you will describe in the `lambda_memory_size.yaml` template. You will then create a dynamic reference to version `1` of the parameter you created, and verify what you built works by creating a stack with your template: call the stack `cfn-workshop-dynamic-references-lambda-memory`. Make sure you create your Parameter Store parameter in the same AWS region you choose to create your stack.
-
-:::expand{header="Need a hint?"}
-1. Review the CloudFormation [User Guide](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-memorysize) to understand how to specify the `MemorySize` configuration for a Lambda Function.
-1. Review the CloudFormation [User Guide](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm-pattern) for help with constructing a dynamic reference string to a specific version of a Parameter Store parameter.
-:::
-::::expand{header="Want to see the solution?"}
-1. Create a Parameter Store parameter specifying your required memory configuration using the following command (replace `YOUR_REGION` with the value you need):
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ssm put-parameter \
---name "/lambda/memory-size" \
---value "256" \
---type "String" \
---region YOUR_REGION
-:::
-1. Open the `code/workspace/dynamic-references/lambda-memory-size.yaml` template in your favorite text editor. Update the template by appending, to the `Resources` section, the example below that include the `MemorySize` property using a dynamic reference to the parameter:
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-HelloWorldFunction:
- Type: AWS::Lambda::Function
- Properties:
- Role: !GetAtt FunctionExecutionRole.Arn
- Handler: index.handler
- Runtime: python3.9
- MemorySize: '{{resolve:ssm:/lambda/memory-size:1}}'
- Code:
- ZipFile: |
- import os
- def handler(event, context):
- return "Hello World!"
-:::
-1. As for the previous Lambda function, create a `cfn-workshop-dynamic-references-lambda-memory` CloudFormation stack to provision resources you described and updated in the template.
-1. Verify the Lambda function was created using the SSM Parameter value for MemorySize by executing the [AWS Command Line Interface](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-awscli.html) (CLI). The `--query` parameter is already filled for you (replace `YOUR_REGION` with the value you need).
-:::code{language=yaml showLineNumbers=false showCopyAction=true}
-aws lambda list-functions --query 'Functions[*].[FunctionName,MemorySize,Environment]' --region YOUR_REGION
-:::
-1. If successful, `aws lambda list-functions` should displayed the details of at least two functions, one you created with RDS Environment Variables and the other with `MemorySize` set to 256.
-:::code{language=json showLineNumbers=false showCopyAction=false}
-[
- [
- "cfn-workshop-dynamic-references-HelloWorldFunction-xhsdJOc49hhX",
- 256,
- null
- ],
- [
- "cfn-workshop-dynamic-references-l-DatabaseFunction-XO1tBoIQL3xT",
- 128,
- {
- "Variables": {
- "RDS_HOSTNAME": "cfn-workshop-dynamic-references-database-database-eyffmthgvwih.csxwxntvtkdn.us-east-1.rds.amazonaws.com",
- "RDS_PORT": "3306"
- }
- }
- ]
-]
-:::
-You can find the full solution in the `code/solutions/dynamic-references/lambda-memory-size.yaml` example template.
-::::
-
-### Cleanup
-1. Delete CloudWatch Log Groups associated with Lambda functions you created with `cfn-workshop-dynamic-references-lambda`, and with `cfn-workshop-dynamic-references-lambda-memory` (if you invoked the Lambda function for the challenge section, you should have a relevant Log Group present).
-
- For each of the stacks, locate the Lambda function name by navigating to the **Resources** tab in the CloudFormation Console; look for the Physical ID of your Lambda function, and note its value. Then, use the following command for each of the Lambda functions you have created (replace `YOUR_FUNCTION_NAME` with your Lambda function name, and `YOUR_REGION` with the value you need):
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws logs delete-log-group \
---log-group-name /aws/lambda/YOUR_FUNCTION_NAME \
---region YOUR_REGION
-:::
-2. Delete the two Parameter Store parameters you created to store the AMI ID and `MemorySize` configuration using the following command (replace `YOUR_REGION` with the value you need):
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws ssm delete-parameters \
---names "/golden-images/amazon-linux-2" "/lambda/memory-size" \
---region YOUR_REGION
-:::
-3. Next, in the CloudFormation console, select the stack you created last, for example: `cfn-workshop-dynamic-references-lambda-memory`.
-4. Choose **Delete** to delete the stack, and then choose **Delete stack** to confirm.
-5. Repeat steps above for other stacks you created with this lab, for example: `cfn-workshop-dynamic-references-lambda`, then `cfn-workshop-dynamic-references-database`, and `cfn-workshop-dynamic-references-ec2`.
-
----
-### Conclusion
-Great job! Now you know how to use dynamic references to specify external values you store and manage in services such as AWS Systems Manager Parameter Store, and AWS Secrets Manager. For more information, see [Using dynamic references to specify template values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html).
diff --git a/content/intermediate/templates/index.ja.md b/content/intermediate/templates/index.ja.md
deleted file mode 100644
index 816e89497..000000000
--- a/content/intermediate/templates/index.ja.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "テンプレート"
-weight: 10
----
-
-
diff --git a/content/intermediate/templates/index.md b/content/intermediate/templates/index.md
deleted file mode 100644
index 4c6babf3b..000000000
--- a/content/intermediate/templates/index.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Templates"
-weight: 10
----
-
-
diff --git a/content/intermediate/templates/language-extensions/index.ja.md b/content/intermediate/templates/language-extensions/index.ja.md
deleted file mode 100644
index 92968b426..000000000
--- a/content/intermediate/templates/language-extensions/index.ja.md
+++ /dev/null
@@ -1,286 +0,0 @@
----
-title: "言語拡張"
-weight: 640
----
-
-_ラボ実施時間 : 30分程度_
-
----
-
-### 概要
-
-AWS CloudFormation 言語を拡張することを目指して、CloudFormation チームは [RFC](https://github.com/aws-cloudformation/cfn-language-discussion) を通じてして CloudFormation コミュニティとオープンな議論を交わしてきました。これらの議論の結果、CloudFormation のための新しい言語拡張がリリースされました。リリースされた新しい言語拡張は変換機能で CloudFormation によって実行されるマクロです。2022 年の初期リリースでは、3 つの新しい言語拡張が追加されました。
-
-1. JSON 文字列変換([Fn::ToJsonString](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ToJsonString.html)): オブジェクトまたは配列を対応する JSON 文字列に変化します。
-2. Length([Fn::Length](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-length.html)): 配列内の要素数を返却します。
-3. [組み込み関数と擬似パラメータのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/function-refs-in-policy-attributes.html): ユーザが定義した `DeletionPolicy` と `UpdateReplacePolicy` [リソース属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-product-attribute-reference.html) の値をパラメータなどから取得できるようにします。
-
-
-詳細については、[Introducing new language extensions in AWS CloudFormation](https://aws.amazon.com/blogs/mt/introducing-new-language-extensions-in-aws-cloudformation/) をご参照ください。
-
-このラボでは、 これらの言語拡張を活用してどのように開発者体験を向上させるのかを探り、学習します。
-
-
-### 取り上げるトピック
-
-このラボを修了すると、次のことができるようになります。
-
-* `AWS::LanguageExtensions` トランスフォームを CloudFormation テンプレートに組み込む方法の理解
-* CloudFormation テンプレートでの言語拡張の使用
-
-### ラボを開始
-
-### 事前準備
-
-AWS アカウントに付属するデフォルト VPC を使用できる状態にあります。
-
-
-### ラボパート 1
-
-このラボのパート 1 では、サンプルの CloudFormation テンプレート `language-extentions.yaml` を使用して、`us-east-1` リージョンにスタックを作成します。開始するには、以下に示すステップに進んでください。
-
-1. `code/workspace/language-extensions` のディレクトリに移動します。
-2. ご自身のエディターで `language-extensions.yaml` の CloudFormation テンプレートを開きます。
-3. テンプレート内のリソースの設定を確認します。このテンプレートは `Dev` 環境リソースとしてタグづけされた [Amazon Elastic Compute Cloud (Amazon EC2)](https://aws.amazon.com/ec2/) インスタンスを作成します。この時点のテンプレートでは EC2 インスタンスの `DeletionPolicy` [属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) が指定されていないことに注目してください。
-
-デフォルトでは、CloudFormation はリソースの `DeletionPolicy` 属性のデフォルト値として `Delete` を使用します。ただし、 `AWS::RDS::DBCluster` リソースと、`DBClusterIdentifier` プロパティを指定しない `AWS::RDS::DBInstance` リソースは例外です。上記のテンプレートを使用してスタックを作成した場合、スタック自体を削除すると EC2 インスタンスは終了します。一般的な使用例の 1 つは、本番環境で作成されたリソースを保持しながら、必要に応じてテストリソースを柔軟に破棄して開発アクティビティ用に再作成することです。テンプレートの `AWS::LanguageExtensions` トランスフォームを使用すると、必要な `DeletionPolicy` の値をパラメータから参照できます。`DeletionPolicy` や `UpdateReplacePolicy` のようなリソース属性は通常は文字列の指定が必要ですが、言語拡張を使用すると値をパラメータから参照する機能が追加されます。
-
-この例では、`DEV` 環境のインスタンスの `DeletionPolicy` を `Delete` として指定することを意図しています。次の手順に進んでください。
-
-1. `code/workspace/language-extensions` ディレクトリに移動します。
-1. `language-extensions.yaml` テンプレートを開きます。`AWS::LanguageExtensions` のトランスフォーマ行を追加するには、`AWSTemlateFormatVersion: "2010-09-09"` の行の下に、以下のコンテンツをコピーして貼り付けます。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=3}
-Transform: AWS::LanguageExtensions
-:::
-1. 既存の `Parameters` セクションの配下に、例えば `DeletionPolicyParameter` という名前のパラメータを次のコードのように追加します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=13}
-DeletionPolicyParameter:
- Type: String
- AllowedValues: [Delete, Retain]
- Default: Delete
-:::
-1. `Resource` セクションの配下にある EC2 インスタンスのリソース設定を変更します。`Type` プロパティと同じレベルに `DeletionPolicy` を追加し、先ほど設定した `DeletionPolicyParameter` を参照させます。
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=18 highlightLines=20}
-Resources:
- EC2Instance:
- DeletionPolicy: !Ref DeletionPolicyParameter
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- Tags:
- - Key: Environment
- Value: DEV
-:::
-
-テンプレートファイルを保存し、次の手順に進みます。
-
-次に、変更したテンプレートを使用して `us-east-1` リージョンに新しいスタックを作成します。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次の AWS CLI コマンドを実行してスタックを作成します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-language-extensions \
---template-body file://language-extensions.yaml \
---capabilities CAPABILITY_AUTO_EXPAND
-1. CloudFormation は次のアウトプットを返却します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-language-extensions/466df9e0-0dff-08e3-8e2f-5088487c4896"
-:::
-1. [wait stack-create-complete] (https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) AWS CLI コマンドを使用して、`CREATE` 操作が完了するまでお待ちください。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-language-extensions
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール] (https://console.aws.amazon.com/cloudformation/) に移動します。
-1. 左側のナビゲーションパネルから **スタック** を選択します。ページの右側から **スタックの作成** を選択し、**新しいリソースを使用 (標準)** を選択します。
-1. **前提条件 - テンプレートの準備** から **テンプレートの準備完了** を選択します。
-1. **テンプレートの指定** セクションで、**テンプレートソース** で **テンプレートファイルのアップロード** を選択します。**ファイルの選択** を選択し、更新した `language-extentions.yaml` テンプレートを指定して、**次へ** を選択します。
-1. **スタック詳細を指定** のページで
- 1. **スタック名** を指定します。例えば `cfn-workshop-language-extensions` を入力します。
- 1. **パラメータ** で、テンプレートのデフォルト値として設定されている `DeletionPolicyParameter` の値に `Delete` を選択し、`LatestAmiId` の値をそのままにしておきます。**次へ** を選択します。
-1. **スタックオプションの設定** では、設定をそのままにしておきます。**次へ** を選択します。
-1. **レビュー** ページで、設定内容を確認します。ページの下部に **機能と変換** セクションに表示されている機能をすべて承認するように選択してください。**送信** を選択します。
-1. スタックが `CREATE_COMPLETE` ステータスになるまで、スタック作成ページを更新します。
-::::
-:::::
-
-おめでとうございます!これで `DeletionPolicy` 属性用の組み込み関数リファレンスを使用する方法を学びました。`UpdateReplacePolicy` 属性と一緒に使用することもできます。次のパートでは、`Fn::ToJsonString` という別の言語拡張の使い方を学びます。
-
-### ラボパート 2
-
-EC2 インスタンスを実行できたので、AWS リソースのメトリクスとアラームをカスタマイズして表示する [Amazon CloudWatch ダッシュボード](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html) を作成してモニタリングすることとします。`CPUUtilization` や `DiskReadOps` などのメトリクスを [ウィジェット](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/create-and-work-with-widgets.html) としてダッシュボードに追加できます。
-
-ダッシュボード本文は JSON 形式の文字列です。詳細については、[ダッシュボード本体の構造と構文](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/APIReference/CloudWatch-Dashboard-Body-Structure.html)を参照してください。CloudFormation を使用して CloudWatch ダッシュボードを記述する時は、次のようなキーとバリューを含む JSON 文字列を指定します。
-
-:::code{language=json showLineNumbers=true showCopyAction=false}
-{
- "start":"-PT6H",
- "periodOverride":"inherit",
- [...]
-}
-:::
-
-
-ダッシュボード作成と利用をより簡単にするため (例えば、`\"` のような内部引用符のエスケープを避けるため)、また一行の文字列を保持しないようにするには、`Fn::ToJsonString` 言語拡張を使用して JSON オブジェクトを指定できます。これにより作成と管理が容易になります。この言語拡張機能を使用すると、代わりに CloudWatch ダッシュボードの構造を JSON オブジェクトとして指定できるためタスクが簡単になります。
-
-`Fn::ToJsonString` を使用すると、開発者はオブジェクトまたは配列形式のテンプレートブロックをエスケープされた JSON 文字列に変換できます。その後、新たに変換された JSON 文字列を CloudWatch ダッシュボードリソースタイプを含むリソースの文字列型プロパティへの入力値として使用できます。これにより、テンプレート内のコードが簡略化され、読みやすくなります。
-
-ラボのこのパート 2 では、前に作成した `language-extensions` スタックを更新し、 EC2 インスタンスの `CPUUtilization` メトリクスを含む CloudWatch ダッシュボードを追加します。
-
-作業をシンプルにするため、この演習ではダッシュボードを既存のテンプレートに追加して、使用する言語拡張機能に焦点を当てれるようにします。通常、[ライフサイクルと所有権](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/best-practices.html#organizingstacks)によるスタックの整理を含むベストプラクティスを考慮して、ダッシュボード用に別のテンプレートを作成します。例えば、CloudWatch ダッシュボードのライフサイクルを EC2 インスタンスのライフサイクルから切り離すために、別のテンプレートを作成したいと考えることがあると思います。
-
-`language-extensions.yaml` テンプレートを更新して、パート 1 で作成した EC2 インスタンスの CPU 使用率データを含む CloudWatch ダッシュボードを追加します。そのためには以下のステップに沿って実施します。
-
-1. `language-extensions.yaml` テンプレートを開きます。`Resources` セクション配下に `Dashboard` を追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=29}
-Dashboard:
- Type: AWS::CloudWatch::Dashboard
- Properties:
- DashboardBody:
- Fn::ToJsonString:
- start: -PT6H
- periodOverride: inherit
- widgets:
- - type: metric
- x: 0
- "y": 7
- width: 3
- height: 3
- properties:
- metrics: [[AWS/EC2, CPUUtilization, InstanceId, !Ref EC2Instance]]
- period: 300
- stat: Average
- region: !Ref AWS::Region
- title: EC2 Instance CPU
-:::
-
-上記のスニペットでは、`CPUUtilization` メトリックが `properties` セクション配下に `metrics` フィールドを介して反映されていることを注目してください。EC2 インスタンスの参照のための `!Ref` を利用し、インスタンス ID を取得しています。また、現在のリージョンを参照するには `!Ref AWS::Region` を使用しています。`AWS::Region` CloudFormation 擬似パラメータを使用して、スタックと EC2 インスタンスを作成するリージョンの名前で取得します。(このラボでは `us-east-1`)
-
-テンプレートファイルを保存し、次の手順に進みます。
-
-パート 1 で作成した既存のスタックを更新します。そのためには、以下に示す手順を実施します。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次の AWS CLI コマンドを実行して、スタック `cfn-workshop-language-extensions` を更新します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-language-extensions \
---template-body file://language-extensions.yaml \
---capabilities CAPABILITY_AUTO_EXPAND
-1. CloudFormation は次の出力を返却します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-language-extensions/466df9e0-0dff-08e3-8e2f-5088487c4896"
-:::
-1. [wait stack-update-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-update-complete.html) AWS CLI コマンドを使用して `UPDATE` 操作が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-language-extensions
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. 左側のナビゲーションパネルから、**スタック** を選択します。前に作成した `cfn-workshop-language-extensions` スタックを選択します。
-1. 右上のメニューから **更新** を選択します。
-1. **前提条件 - テンプレートの準備**で、**既存テンプレートを置き換える** を選択し、**テンプレートファイルのアップロード**を選択します。**ファイルの選択** を選択し、更新した `language-extensions.yaml` テンプレートを指定して **次へ** を選択します。
-1. **スタックの詳細を指定** ページでは、設定をそのままにしておきます。 **次へ** を選択します。
-1. **スタックオプションの設定** では、設定をデフォルトのままにしておきます。**次へ** を選択します。
-1. **レビュー** ページで、ページの内容を確認します。ページの下部で、**機能と変換** セクションに表示されている機能をすべて承認するように選択してください。
-1. **送信** を選択します。スタックのステータスが `UPDATE_COMPLETE` になるまでスタック作成ページを更新します。
-::::
-:::::
-
-* [CloudWatch コンソール](https://console.aws.amazon.com/cloudwatch/)に移動します。左側のナビゲーションパネルから、**ダッシュボード** を選択します。
-* 作成した **ダッシュボード** を選択し、右上から **アクション** を選択します。
-* **ソースを表示 / 編集** を選択すると、`language-extensions.yaml` の `YAML` と同等の `JSON` がダッシュボードに表示されるはずです。
-
-おめでとうございます!`Fn::ToJsonString` を使用して JSON オブジェクトをリソースプロパティへの入力としてエスケープされた JSON 文字列に変換する方法を学習しました。
-
-### チャレンジ
-
-この演習では、このラボで得た知識を使用します。あなたのタスクは、削除ポリシーを `Delete` というパラメータ値に設定した [Amazon Simple Storage Service (Amazon S3)](https://aws.amazon.com/s3/) バケットを作成し、バケット内のオブジェクト数を反映する CloudWatch ダッシュボードを作成することです。`language-extensions-challenge.yaml` テンプレートを使用して、コンテンツを追加してください。
-
-CloudFormation テンプレートでダッシュボードを記述する時には、ラボのパート 2 で記述した [CloudWatch ダッシュボード構造](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/APIReference/CloudWatch-Dashboard-Body-Structure.html)を参照してください。`properties` 配下の `metrics` フィールドには、`[[AWS/S3, NumberOfObjects, StorageType, AllStorageTypes, BucketName, !Ref S3Bucket]]` を使用してください。[S3 ストレージメトリクスは 1 日に 1 回報告されます](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/cloudwatch-monitoring.html)。追加料金は発生しないため、ラボを実行しているときには表示されない場合があることにご注意ください。
-
-
-:::expand{header="ヒントが必要ですか?"}
-* ラボのパート 1 で説明した言語拡張を使用して、削除ポリシーのパラメータを使用したことを思い返してください。
-* S3 バケットリソースの削除ポリシーパラメータを参照することを忘れないでください。
-* さらに、以前 CloudWatch ダッシュボードを追加した方法を思い出してください。関連フィールドに `NumberOfObjects` メトリクスを使用することを追加してください。
-:::
-
-::::::expand{header="解決策を確認しますか?"}
-* ラボのパート 1 で行ったように、テンプレートの `Transform: AWS::LanguageExtensions` の行を追加します。
-* ラボのパート 1 で行ったように、`Parameters` セクションを編集して `DeletionPolicyParameter` を追加します。
-* `S3Bucket` リソースの `Resources` セクション配下に、パラメータへの参照を含む `DeletionPolicy` 属性を追加します。
-* `Resource` セクション配下に、`Dashboard` リソースを追加します。
-* チャレンジソリューションの全文は、`code/solutions/language-extensions` ディレクトリにある `language-extensions-solutions.yaml` というテンプレートにあります。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次の AWS CLI コマンドを実行してスタックを作成しましょう。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-language-extensions-solution \
---template-body file://language-extensions-challenge.yaml \
---capabilities CAPABILITY_AUTO_EXPAND
-1. CloudFormation は次の出力を返却します。
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-language-extensions-solution/466df9e0-0dff-08e3-8e2f-5088487c4896"
-:::
-1. [wait stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) AWS CLI コマンドを使用して、`CREATE` 操作が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-language-extensions-solution
-:::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-2. 左側のナビゲーションパネルから、**スタック** を選択します。ページの右側から、**スタックの作成** を選択し、**新しいリソースを使用 (標準)** を選択します。
-3. **前提条件 - テンプレートの準備** から、**テンプレートの準備完了** を選択します。
-4. **テンプレートの指定** セクションで、**テンプレートソース** で **テンプレートファイルのアップロード** を選択します。**ファイルの選択** を選択し、先ほど更新した `language-extensions-challenge.yaml` テンプレートを指定して、**次へ** を選択します。
-5. **スタックの詳細を指定**ページで
- 1. **スタック**名を指定します。例えば、`cfn-workshop-language-extensions-solution` を選択します。
- 2. **パラメータ** で、テンプレートのデフォルト値として設定されている `DeletionPolicyParameter` の値が `Delete` であることを確認し、**次へ** を選択します。
-6. **スタックオプションの設定** では、設定をそのままにしておきます。**次へ** を選択します。
-7. **レビュー** ページで、ページの内容を確認します。ページの下部で、**機能と変換** セクションに表示されている機能をすべて承認するように設定してください。**送信** を選択します。
-8. スタックが `CREATE_COMPLETE` ステータスになるまで、スタック作成ページを更新します。
-::::
-:::::
-::::::
-
-### クリーンアップ
-
-このラボで作成したリソースを削除します。以下の手順を実行してください。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次の AWS CLI コマンドを実行して、スタック `cfn-workshop-language-extensions` を削除します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-language-extensions
-:::
-1. [wait stack-delete-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-delete-complete.html) AWS CLI コマンドを使用して、`DELETE` 操作が完了するまで待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---stack-name cfn-workshop-language-extensions
-:::
-1. 上記のステップ (1-2) を繰り返して、スタック `cfn-workshop-language-extensions-solution` を削除します。
-::::
-::::tab{id="LocalDevelopment" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. CloudFormation コンソールの **スタック** ページで、パート 1 で作成した `cfn-workshop-language-extensions` スタックを選択します。
-1. スタックの詳細ペインで、**削除** を選択します。プロンプトが表示されたら、**削除** を選択します。
-1. CloudFormation コンソールの **スタック** ページで、チャレンジセクションで作成した `cfn-workshop-language-extensions-solution` スタックを選択します。
-1. スタックの詳細ペインで、**削除** を選択します。プロンプトが表示されたら、**削除** を選択します。
-::::
-:::::
-
----
-
-### まとめ
-
-`AWS::LanguageExtensions` を CloudFormation テンプレートに組み込む方法を学びました。 RFC に関するフィードバックは [Language Discussion GitHub repository](https://github.com/aws-cloudformation/cfn-language-discussion) にお気軽にお寄せください。皆さんのコントリビューションをお待ちしています!
diff --git a/content/intermediate/templates/language-extensions/index.md b/content/intermediate/templates/language-extensions/index.md
deleted file mode 100644
index 078ac456c..000000000
--- a/content/intermediate/templates/language-extensions/index.md
+++ /dev/null
@@ -1,286 +0,0 @@
----
-title: "Language extensions"
-weight: 640
----
-
-_Lab Duration: ~30 minutes_
-
----
-
-### Overview
-
-With the goal of extending the AWS CloudFormation language, the CloudFormation team has been having open discussions with the CloudFormation community, by using an [RFC mechanism](https://github.com/aws-cloudformation/cfn-language-discussion). These discussions have led to the launch of new language extensions for CloudFormation. A language extension is a transform, which is a macro hosted by CloudFormation. In its first release in 2022, three new language extensions were added:
-
-1. JSON string conversion ([Fn::ToJsonString](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ToJsonString.html)): converts an object or array to its corresponding JSON string.
-2. Length ([Fn::Length](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-length.html)): returns the number of elements within an array.
-3. [Intrinsic functions and pseudo-parameter references](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/function-refs-in-policy-attributes.html): allow the user to define the `DeletionPolicy` and `UpdateReplacePolicy` [resource attributes](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-product-attribute-reference.html) whose values can be referenced by parameters, for example.
-
-
-For more information, see [Introducing new language extensions in AWS CloudFormation](https://aws.amazon.com/blogs/mt/introducing-new-language-extensions-in-aws-cloudformation/).
-
-In this lab, you'll explore and learn how you can leverage these language extensions to augment your developer experience.
-
-
-### Topics Covered
-
-By the end of this lab, you'll be able to:
-
-* Understand how to incorporate the `AWS::LanguageExtensions` transform in your CloudFormation templates.
-* Use language extensions in your CloudFormation template.
-
-### Start Lab
-
-### Prerequisites
-
-You can use the default VPC that comes with your AWS account.
-
-
-### Part 1
-
-In part 1 of this lab, you'll use an example CloudFormation template, `language-extensions.yaml`, to create a stack in the `us-east-1` region. To get started, follow steps shown next:
-
-1. Navigate to `code/workspace/language-extensions` directory.
-1. Open the `language-extensions.yaml` CloudFormation template in your own text editor.
-1. Familiarize with the configuration of resources in the template. This template creates an [Amazon Elastic Compute Cloud (Amazon EC2)](https://aws.amazon.com/ec2/) instance tagged as a `DEV` environment resource. Note that, up to this point, the template does not specify a `DeletionPolicy` [attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) for the EC2 instance.
-
-By default, CloudFormation uses `Delete` as the default value for the `DeletionPolicy` attribute for resources; exceptions to this are `AWS::RDS::DBCluster` resources, and `AWS::RDS::DBInstance` resources that don't specify the `DBClusterIdentifier` property. If you use the template above for the creation of a stack, upon deletion of the stack itself the EC2 instance will be terminated. One of the common use cases is to retain the resources that are created in production, whilst having the flexibility to discard and recreate test resources, as needed, for development activities: with the `AWS::LanguageExtensions` transform in your template, you can reference the `DeletionPolicy` value you need from a parameter. The language extension you'll use adds the functionality of referencing a value for resource attributes like `DeletionPolicy` and `UpdateReplacePolicy` that natively accept a string value and not a parameter reference.
-
-In this example, your intent is to specify `DeletionPolicy` as `Delete` for your instance in the `DEV` environment; follow steps shown next:
-
-1. Navigate to the `code/workspace/language-extensions` directory.
-1. Open the `language-extensions.yaml` template. Add the `AWS::LanguageExtensions` transform line by copying and pasting the content below _underneath_ the `AWSTemplateFormatVersion: "2010-09-09"` line:
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=3}
-Transform: AWS::LanguageExtensions
-:::
-1. Add a parameter, called for example `DeletionPolicyParameter`, by copying and pasting the content below _underneath_ the existing `Parameters` section:
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=13}
-DeletionPolicyParameter:
- Type: String
- AllowedValues: [Delete, Retain]
- Default: Delete
-:::
-1. Underneath the `Resources` section, modify the EC2 instance resource configuration: add `DeletionPolicy` at the same level as `Type`, and reference the `DeletionPolicyParameter` you added earlier, as shown next:
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=18 highlightLines=20}
-Resources:
- EC2Instance:
- DeletionPolicy: !Ref DeletionPolicyParameter
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- Tags:
- - Key: Environment
- Value: DEV
-:::
-
-Save the template file, and proceed to the next steps.
-
-You'll now create a new stack, using the template you modified, in the `us-east-1` region.
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Let's create a stack by running the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-language-extensions \
---template-body file://language-extensions.yaml \
---capabilities CAPABILITY_AUTO_EXPAND
-1. CloudFormation returns the following output.
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-language-extensions/466df9e0-0dff-08e3-8e2f-5088487c4896"
-:::
-1. Wait until the `CREATE` operation is complete, by using the [wait stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---stack-name cfn-workshop-language-extensions
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From the left navigation panel, select the **Stacks** tab. From the right side of the page, choose **Create Stack**, and then choose **With new resources (standard).**
-1. From **Prerequisite - Prepare template**, choose **Template is ready**.
-1. Under **Specify template**, select **Template source**, and choose **Upload a template file**. Select **Choose file**, and supply the `language-extensions.yaml` template you updated earlier, and then choose **Next**.
-1. In the **Specify Stack details** page:
- 1. Specify a **Stack** name. For example, choose `cfn-workshop-language-extensions`.
- 1. Under **Parameters**, choose to accept the value for `DeletionPolicyParameter` as `Delete`, which is set as the default value in the template; keep the value for `LatestAmiId` as it is. Choose **Next**.
-1. On **Configure Stack options**, leave the configuration as it is. Choose **Next**.
-1. On the **Review** page, review the contents of the page. At the bottom of the page, choose to acknowledge all the capabilities shown in the **Capabilities and transforms** section. Choose **Submit**.
-1. Refresh the stack creation page until you see the stack to be in the `CREATE_COMPLETE` status.
-::::
-:::::
-
-Congratulations! You have learned how to use intrinsic function references for the `DeletionPolicy` attribute; you can also use them with the `UpdateReplacePolicy` attribute as well. In the next part, you'll learn how to use another language extension: `Fn::ToJsonString`.
-
-### Part 2
-
-Now that you have your EC2 instance running, you choose to monitor it by creating an [Amazon CloudWatch dashboard](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html) that provides customized views of the metrics and alarms for your AWS resources. You can add metrics such as `CPUUtilization`, `DiskReadOps`, etc. to a dashboard as a [widget](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/create-and-work-with-widgets.html).
-
-A dashboard body is a string in JSON format: for more information, see [Dashboard Body Structure and Syntax](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/CloudWatch-Dashboard-Body-Structure.html). When you describe a CloudWatch dashboard with CloudFormation, you specify a JSON string that contains keys and values, such as:
-
-:::code{language=json showLineNumbers=true showCopyAction=false}
-{
- "start":"-PT6H",
- "periodOverride":"inherit",
- [...]
-}
-:::
-
-
-To make it easier to write and consume a dashboard (for example, to avoid escaping inner quotes like `\"`), and to avoid maintaining a single-line string you can use the `Fn::ToJsonString` language extension to specify a JSON object, which is easier to compose and to maintain. With this language extension, you can specify the structure of a CloudWatch dashboard as a JSON object instead, thus simplifying the task.
-
-`Fn::ToJsonString` allows developers to convert a template block in the form of an object or array into an escaped JSON string. You can then use a newly-converted JSON string as a set of input values to string-type properties for resources that include the CloudWatch dashboard resource type. This simplifies the code in your template, and enhances its readability.
-
-In this part 2 of the lab, you'll update the `language-extensions` stack you created earlier, and add a CloudWatch dashboard with the `CPUUtilization` metric for your EC2 instance.
-
-For simplicity, in this exercise you'll add the dashboard to your existing template, so you can focus on the language extension you'll use. Normally, you would create a separate template for your dashboards, for considerations on best practices that also include organizing your stacks by [lifecycle and ownership](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html#organizingstacks): you would want to, for example, create a separate template to decouple the lifecycle of your CloudWatch dashboard from the lifecycle of your EC2 instance.
-
-You'll now update the `language-extensions.yaml` template to add a CloudWatch dashboard with CPU utilization data of the EC2 instance you created in part 1. To do so, follow steps shown next:
-
-1. Open the `language-extensions.yaml` template. Underneath `Resources` section, add `Dashboard`:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=29}
-Dashboard:
- Type: AWS::CloudWatch::Dashboard
- Properties:
- DashboardBody:
- Fn::ToJsonString:
- start: -PT6H
- periodOverride: inherit
- widgets:
- - type: metric
- x: 0
- "y": 7
- width: 3
- height: 3
- properties:
- metrics: [[AWS/EC2, CPUUtilization, InstanceId, !Ref EC2Instance]]
- period: 300
- stat: Average
- region: !Ref AWS::Region
- title: EC2 Instance CPU
-:::
-
-In the above snippet, note that the `CPUUtilization` metric is reflected underneath the `properties` section through the `metrics` field. Note also the references to your EC2 instance with `!Ref`, that in this case will return the instance ID, and the reference to the current region with `!Ref AWS::Region`, where you'll use the `AWS::Region` CloudFormation pseudo parameter to resolve the name of the region where you are creating the stack and the EC2 instance (in this lab, `us-east-1`).
-
-Save the template file, and proceed to the next steps.
-
-You'll now update your existing stack that you created in Part 1. To do so, follow steps shown next:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Update the stack `cfn-workshop-language-extensions` by running the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name cfn-workshop-language-extensions \
---template-body file://language-extensions.yaml \
---capabilities CAPABILITY_AUTO_EXPAND
-1. CloudFormation returns the following output.
-:::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-language-extensions/466df9e0-0dff-08e3-8e2f-5088487c4896"
-:::
-1. Wait until the `UPDATE` operation is complete, by using the [wait stack-update-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-update-complete.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-language-extensions
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From the left navigation panel, select the **Stacks** tab. Select the `cfn-workshop-language-extensions` stack you created earlier.
-1. From the top-right menu, choose **Update**.
-1. Under **Prerequisite - Prepare template,** select **Replace current template** and choose **Upload a template file**. Select **Choose file**, and supply the `language-extensions.yaml` template you updated earlier, and then choose **Next**.
-1. On **Specify Stack details** page, leave the configuration as it is. Choose **Next**.
-1. On **Configure Stack options**, leave the configuration as it is. Choose **Next**.
-1. On **Review** page, review the contents of the page. At the bottom of the page, choose to acknowledge all the capabilities shown in the **Capabilities and transforms** section.
-1. Choose **Submit**. Refresh the stack creation page until you see the stack in the `UPDATE_COMPLETE` status.
-::::
-:::::
-
-* Navigate to the [CloudWatch console](https://console.aws.amazon.com/cloudwatch/). From the left navigation panel, choose **Dashboards**.
-* Select the **Dashboard** that you have created, From the top-right, choose **Actions**.
-* Select **View/edit source**, you should see `JSON` for the dashboard that matches `YAML` from `language-extensions.yaml`
-
-Congratulations! You have learned how to use `Fn::ToJsonString` to transform JSON objects into escaped JSON strings as inputs to resource properties.
-
-### Challenge
-
-In this exercise, you'll use the knowledge gained from earlier parts of this lab. Your task is to create an [Amazon Simple Storage Service (Amazon S3)](https://aws.amazon.com/s3/) bucket with its deletion policy set to a parameterized value of `Delete`, and create a CloudWatch dashboard that reflects the number of objects in the bucket. Use the `language-extensions-challenge.yaml` template, and add content to it.
-
-Refer to the [CloudWatch Dashboard structure](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/CloudWatch-Dashboard-Body-Structure.html) mentioned in Part 2 of the lab as you describe the dashboard in your CloudFormation template. For the `metrics` field underneath `properties`, use `[[AWS/S3, NumberOfObjects, StorageType, AllStorageTypes, BucketName, !Ref S3Bucket]]` to denote the `NumberOfObjects` metrics in an S3 bucket for your CloudWatch widget. Please note that [S3 storage metrics are reported once per day](https://docs.aws.amazon.com/AmazonS3/latest/userguide/cloudwatch-monitoring.html) at no additional cost, so you may not see them when you are running the lab.
-
-
-:::expand{header="Need a hint?"}
-* Recall using the language extension in Part 1 of the lab to use a parameter for the deletion policy.
-* Don’t forget to reference the deletion policy parameter in your S3 bucket resource.
-* Additionally, recall how you added a CloudWatch dashboard earlier, add use the `NumberOfObjects` metrics for the relevant field.
-:::
-
-::::::expand{header="Want to see the solution?"}
-* Add the `Transform: AWS::LanguageExtensions` line to the template like you did in Part 1 of the lab.
-* Edit the `Parameters` section to add the `DeletionPolicyParameter` like you did in Part 1 of the lab.
-* Underneath the `Resources` section for the `S3Bucket` resource, add the `DeletionPolicy` attribute with a reference to the parameter.
-* Underneath the `Resources` section, add the `Dashboard` resource.
-* You can find the full challenge solution in the template called `language-extensions-solution.yaml`, that is in the `code/solutions/language-extensions` directory.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Let's create the stack by running the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name cfn-workshop-language-extensions-solution \
---template-body file://language-extensions-challenge.yaml \
---capabilities CAPABILITY_AUTO_EXPAND
-1. CloudFormation returns the following output.
-:::code{language=json showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-language-extensions-solution/466df9e0-0dff-08e3-8e2f-5088487c4896"
-:::
-1. Wait until the `CREATE` operation is complete, by using the [wait stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-update-complete \
---stack-name cfn-workshop-language-extensions-solution
-:::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From the left navigation panel, select the **Stacks** tab. From the right side of the page, choose **Create Stack**, and then choose **With new resources (standard).**
-1. From **Prerequisite - Prepare template**, choose **Template is ready**.
-1. Under **Specify template**, select **Template source**, and choose **Upload a template file**. Select **Choose file**, and supply the `language-extensions-challenge.yaml` template you updated earlier, and then choose **Next**.
-1. In the **Specify Stack details** page:
- 1. Specify a **Stack** name. For example, choose `cfn-workshop-language-extensions-solution`.
- 1. Under **Parameters**, choose to accept the value for `DeletionPolicyParameter` as `Delete`, which is set as the default value in the template, Choose **Next**.
-1. On **Configure Stack options**, leave the configuration as it is. Choose **Next**.
-1. On the **Review** page, review the contents of the page. At the bottom of the page, choose to acknowledge all the capabilities shown in the **Capabilities and transforms** section. Choose **Submit**.
-1. Refresh the stack creation page until you see the stack to be in the `CREATE_COMPLETE` status.
-::::
-:::::
-::::::
-
-### Clean up
-
-You'll now tear down the resources you created in this lab. Use following steps:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Delete the stack `cfn-workshop-language-extensions` by running the following AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---stack-name cfn-workshop-language-extensions
-:::
-1. Wait until the `DELETE` operation is complete, by using the [wait stack-delete-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-delete-complete.html) AWS CLI command.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---stack-name cfn-workshop-language-extensions
-:::
-1. Repeat steps (1-2) above to delete the stack `cfn-workshop-language-extensions-solution`.
-::::
-::::tab{id="LocalDevelopment" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. On the **Stacks** page in the CloudFormation console, select the stack you created in Part 1: `cfn-workshop-language-extensions`.
-1. In the stack details pane, choose **Delete**. Select **Delete** when prompted.
-1. On the **Stacks** page in the CloudFormation console, select the stack you created in Challenge section: `cfn-workshop-language-extensions-solution`.
-1. In the stack details pane, choose **Delete**. Select **Delete** when prompted.
-::::
-:::::
-
----
-
-### Conclusion
-
-Great work! You learned how to incorporate `AWS::LanguageExtensions` in your CloudFormation templates. Please feel free to provide feedback for RFCs in the [Language Discussion GitHub repository](https://github.com/aws-cloudformation/cfn-language-discussion). We welcome your contributions!
diff --git a/content/intermediate/templates/looping-over-collections/index.ja.md b/content/intermediate/templates/looping-over-collections/index.ja.md
deleted file mode 100644
index 138fb4e59..000000000
--- a/content/intermediate/templates/looping-over-collections/index.ja.md
+++ /dev/null
@@ -1,524 +0,0 @@
----
-title: "Fn::ForEach を使用してコレクションをループオーバする"
-weight: 641
----
-
-_ラボ実施時間 : 45分程度_
-
----
-
-### 概要
-
-インフラストラクチャをコードで記述する場合、記述するコードが同じ構成を共有するリソースや、変数などのメカニズムで管理できるいくつかの相違点を含むリソースを記述するケースがあります。このようなリソースや関連するプロパティの数が増えるにつれて、記述するコードも増えるため、長期にわたる保守が容易ではなくヒューマンエラーも発生しやすくなります。
-
-[言語拡張](../language-extensions) ラボでは、`AWS::LanguageExtensions` [変換](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/transform-aws-languageextensions.html) を使用して [AWS CloudFormation](https://aws.amazon.com/cloudformation/) 言語を拡張するいくつかの関数を活用しました。このような関数は、CloudFormation チームが [RFC](https://github.com/aws-cloudformation/cfn-language-discussion) によって推進されるオープンディスカッションを通じてコミュニティから受け取ったフィードバックから生まれています。これらの関数の 1 つは、`Fn::ForEach` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-foreach.html)であり、このラボではその使用方法を学習します。この組み込み関数を使用すると、リソース構成をループ状の構造にマッピングするために使用する動的な反復処理を使用して、同じもしくは類似した構成を共有するリソースを記述できます。
-
-### 取り上げるトピック
-
-このラボを修了すると、次のことができるようになります。
-
-* 同じもしくは類似した設定を共有するリソースについて、`Fn::ForEach` を使用して、静的に記述されたコードを簡略化および削除できるユースケースの例を特定できるようになります。
-* `Fn::ForEach` を使用してコレクションをループさせて、リソースの状態をコードで記述できるようになります。
-* 該当するユースケースについて、`Fn::ForEach` を使用してコードの行数を減らし、保守が容易でヒューマンエラーを起こしにくいコードを作成することができます。
-
-### ラボを開始
-
-### ラボパート 1: S3 バケットのコレクションの基本的なループ処理
-
-ユースケースの例から始めましょう。多くの共通の設定プロパティを持つ 3 つの[Amazon Simple Storage Service (Amazon S3)](https://aws.amazon.com/s3/) バケットを定義する必要があります。例えば、[バケットの暗号化](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-bucketencryption.html)が[AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/)、[ライフサイクル設定](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-lifecycleconfig.html)は 30 日後に `GLACIER` [ストレージクラス](https://aws.amazon.com/jp/s3/storage-classes/)に移行し、1 年後にオブジェクトの有効期限が切れるように設定し、`PublicAccessBlockConfiguration` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html) を `true` に設定し、タグは `Name` タグキーの値として `aws-cloudformation-workshop` を使用するように設定します。
-
-コードに記述する必要がある S3 バケットは、このユースケースでは同じプロパティを共有します。これら全てを 3 つの個別のコードブロックで記述することもできますが、このラボでは、`Fn::ForEach` を使用してコードサイズと相対的な複雑さを軽減し、3 つのバケット全てを 1 つの反復構造で一度に記述できます。よって、保守が容易なコードになるという利点もあり、ヒューマンエラーを減らすのにも有効です。
-
-上記の 3 つのバケットを `Fn::ForEach` なしで記述すると、結果として下記のようなテンプレートとなります。例として次に示します。
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-AWSTemplateFormatVersion: "2010-09-09"
-
-Description: AWS CloudFormation workshop lab - sample S3 buckets with the same configuration settings.
-
-Resources:
- S3Bucket1:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: aws:kms
- LifecycleConfiguration:
- Rules:
- - ExpirationInDays: 365
- Id: Example Glacier Rule
- Status: Enabled
- Transitions:
- - StorageClass: GLACIER
- TransitionInDays: 30
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
-
- S3Bucket2:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: aws:kms
- LifecycleConfiguration:
- Rules:
- - ExpirationInDays: 365
- Id: Example Glacier Rule
- Status: Enabled
- Transitions:
- - StorageClass: GLACIER
- TransitionInDays: 30
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
-
- S3Bucket3:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: aws:kms
- LifecycleConfiguration:
- Rules:
- - ExpirationInDays: 365
- Id: Example Glacier Rule
- Status: Enabled
- Transitions:
- - StorageClass: GLACIER
- TransitionInDays: 30
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
-:::
-
-このラボでは、`Fn::ForEach` を使用してバケットのコレクションをループすることで S3 バケットの設定プロパティを一度だけ記述することになります。つまりこの場合、最初に使用するテンプレートのコード行数が少なくなるため、保守が容易になります。
-`AWS::LanguageExtensions` トランスフォームによってテンプレートが処理され、その結果には `S3Bucket1`、`S3Bucket2`、`S3Bucket3` など、プロパティは同じで [論理 ID](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) が異なる 3 つのバケットリソースを含む上記のようなテンプレートが作成されます。
-
-それでは、始めましょう! `code/workspace/looping-over-collections` ディレクトリに移動し、お好みのテキストエディタで `s3-buckets.yaml` ファイルを開きます。
-
-::alert[先ほど開いた `s3-buckets.yaml` テンプレートですでに存在する `Transform::AWS::LanguageExtensions` 行を削除しないように注意してください。このトランスフォームは [言語拡張](../language-extensions) ラボで既に使用しています。この行は言語拡張 [変換](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/transform-aws-languageextensions.html) を有効にします。`Fn::ForEach` 組み込み関数を使うために *必須* です。]{type="warning"}
-
-テキストエディタで `s3-buckets.yaml` ファイルを開いた状態で、コメントアウトされている TODO リマインダー行を削除し、以下のソースコードを `Resources` セクションに追加します。インデントは重要です。`Fn::ForEach::S3Buckets` 行の先頭の文字がエディターの列番号 `2` から始まることを確認してください。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=8}
- Fn::ForEach::S3Buckets:
- - S3BucketLogicalId
- - [S3Bucket1, S3Bucket2, S3Bucket3]
- - ${S3BucketLogicalId}:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: aws:kms
- LifecycleConfiguration:
- Rules:
- - Id: Example Glacier Rule
- ExpirationInDays: 365
- Status: Enabled
- Transitions:
- - TransitionInDays: 30
- StorageClass: GLACIER
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
-:::
-
-更新したファイルを保存します。貼り付けたコードを見ると、このラボの最初の例で見た `Type: AWS::S3::Bucket` 行から始める内容は、3 つの S3 バケット全てに共通するプロパティのセットであることがわかります。`Fn::ForEach` の仕組みを理解するために、`Type: AWS::S3::Bucket` の上にある行を見てみましょう!
-
-この例では、3 つの S3 バケットで構成される 3 つの要素のコレクションを繰り返し処理する必要があります。このコレクションを `[S3Buckets1, S3Bucket2, S3Bucket3]` として作成し、コレクション自体の上に記述した `S3BucketLogicalId` 識別子で示される各要素を使用することを選択します。この例では、コレクションを配列として記述しましたが、`CommaDelimitedList` 型のテンプレート[パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)への参照を使用することもできます。
-
-貼り付けたコードの一番上にある`Fn::ForEach::S3Buckets` 行に注目してください。この行には、`Fn::ForEach` を使用してコレクションを反復処理する旨が記述されています。行の右端の `S3Buckets` は、ループに選択する名前を示しています。ループを作成するときは、必ずテンプレート内で一位の名前を指定してください。テンプレート内の別のループに使用している名前や、同じテンプレート内のリソースの論理 ID に使用した、または使用する予定の名前は選択しないでください。
-
-`Type: AWS::S3::Bucket` のすぐ上の行、つまり `${S3BucketLogicalId}` は、変換されるテンプレートにある `OutputKey` コンテンツを示しています。この場合、`OutputKey` の値は 3 つの S3 バケットそれぞれの論理 ID になります。最初の反復ループでは `S3Bucket1`、2 番目の反復ループでは`S3Bucket2`、3 番目の反復ループでは `S3Bucket3` になります。
-
-この例では、`Type: AWS::S3::Bucket` で始まる行とそれ以下の行は、処理されたテンプレート内の `OutputKey` ごとに複製される `OutputValue` を構成します。これらの行には、前の段落で記述した論理 ID を持つ 3 つの S3 バケットリソースに適用される共通の設定が含まれています。
-
-::alert[CloudFormation では、処理されたテンプレートにサービスクォータを適用しす。CloudFormation サービスクォータの詳細については、CloudFormation ユーザガイドの [AWS CloudFormation のクォータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html) を参照してください。]{type="warning"}
-
-これで新しい CloudFormation スタックを作成し、上で記述したコレクションをループして 3 つの S3 バケットがどのようにプロビジョニングされるかを確認します。`us-east-1` リージョンに新しいスタックを作成します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-次の AWS CLI コマンドを実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name looping-over-collections-s3-buckets \
---template-body file://s3-buckets.yaml \
---region us-east-1 \
---capabilities CAPABILITY_AUTO_EXPAND
-:::
-
-上記のコマンドは、作成しているスタック ID を返すはずです。[wait stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) AWS CLI コマンドを作成して、スタックが `CREATE_COMPLETE` ステータスになるまで待ちます。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---region us-east-1 \
---stack-name looping-over-collections-s3-buckets
-:::
-
-::::
-::::tab{id="local" label="ローカル開発"}
-手順
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-2. **米国東部 (バージニア北部)** リージョンにいることを確認してください。
-3. 左のナビゲーションパネルから、**スタック** を選択します。
-4. ページの右側から、**スタックの作成** を選択し、**新しいリソースを使用 (標準)** を選択します。
-5. **前提条件 - テンプレートの準備** から、**テンプレートの準備完了** を選択します。
-6. **テンプレートの指定** セクションで、**テンプレートソース** で、**テンプレートファイルのアップロード** を選択します。
-7. **ファイルの選択** を選択し、更新した `s3-buckets.yaml` テンプレートを指定します。**次へ** を選択します。
-8. **スタックの詳細を指定** ページで、**スタック名** に `looping-over-collections-s3-buckets` と入力します。**次へ** を選択します。
-9. **スタックオプションの設定** では、設定をそのままにしておきます。**次へ** を選択します。
-10. **レビュー** ページで、ページの内容を確認します。ページの下部で、**機能と変換** セクションに表示されている機能をすべて承認するように選択してください。**送信** を選択します。
-11. スタックが `CREATE_COMPLETE` ステータスになるまで、スタック作成ページを更新します。
-::::
-:::::
-
-スタックの作成が完了したら、[AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動し、`looping-over-collections-s3-buckets` スタックを探します。スタックを選択し、次に **テンプレート** タブを選択します。次の点に確認してください。
-
-* 指定した最初のテンプレートが表示されます。記述したバケットのコレクションに対してループを使用するものです。
-* **処理されたテンプレートの表示** を選択します。展開されたテンプレートが表示され、処理の結果として、ループ構造の代わりに静的に記述された 3 つの S3 バケットが表示されます。処理された設定は JSON 形式で表示されることにご注意ください。
-* **リソース** タブに移動し、論理 ID が `S3Bucket1`、`S3Bucket2`、`S3Bucket3` であるはずの 3 つの新しく作成された S3 バケットを確認できます。
-
-おめでとうございます!このラボの最初の部分を終了し、`Fn::ForEach` の基本を学習しました。次のパートでは可動部分を増やした新しい例を見ていきます。
-
-### ラボパート 2: VPC 関連リソースの内部ループ
-
-ラボのこのパートでは、`Fn::ForEach` ループ構造をネストする方法を学びます。前回の `Fn::ForEach` の使い方を思い出してください。ユニークループの定義のすぐ下にある組み込み関数に以下のパラメータを渡します。
-
-* `Identifier`
-* `Collection`
-* `OutputKey`
-
-前の例では、作成したい各バケットの論理 ID の `OutputKey` として `${S3BucketLogicalID}:` を使用しました。今回の例では、`OutputKey` の代わりに別の `Fn::ForEach` ループを使用して、[Amazon Virtual Private Cloud (Amazon VPC)](https://aws.amazon.com/jp/vpc/) リソースに関連するリソースの作成のための内部ループロジックを駆動します。
-
-それでは、始めましょう!`code/workspace/looping-over-collections` ディレクトリにいることを確認し、お好みのテキストエディタで `vpc.yaml` ファイルを開きます。コード内の `Transform: AWS::LanguageExtensions` 行に注意してください。この行は次に使用する `Fn::ForEach` 組み込み関数に *必須* です。テンプレートには既に `VPC` [リソース](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html)、`InternetGateway` [リソース](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html)、および `VpcGatewayAttachment` [リソース](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html) が記述されていますが、`Fn::ForEach` は使用していません。なぜなら、このようなリソースはテンプレート内で一度しか定義していないからです。テンプレートには、次に使用する VPC と VPC 関連リソースの様々な設定が含まれている `Mappings` [セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html) もあります。
-
-開いたファイルの TODO リマインダー行を削除し、次のコードを追加して、パブリックサブネットとプライベートサブネットの記述を開始します。インデントのレベルが `VpcGatewayAttachment` リソース宣言と同じ(つまり、列 `2` から始まる) ことに注意してください。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=63}
- Fn::ForEach::SubnetTypes:
- - SubnetType
- - [Public, Private]
- - Fn::ForEach::SubnetNumbers:
- - SubnetNumber
- - ["1", "2"]
- - ${SubnetType}Subnet${SubnetNumber}:
- Type: AWS::EC2::Subnet
- Properties:
- AvailabilityZone: !Select
- - !FindInMap
- - SubnetAzIndexes
- - !Ref SubnetType
- - !Ref SubnetNumber
- - !GetAZs ""
- CidrBlock: !FindInMap
- - SubnetCidrs
- - !Ref SubnetType
- - !Ref SubnetNumber
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
- VpcId: !Ref Vpc
-:::
-
-上で追加したコードは、合計 4 つの `AWS::EC2::Subnet` リソースについて、2 つのパブリックサブネットと 2 つのプライベートサブネットを記述する意図を示しています。
-
-最初の `Fn::ForEach::SubnetTypes` ループでは、サブネットタイプ (Public と Private) のコレクションを反復処理し、2 番目の内部ループ (ここでは `OutputKey` として使用している) では、特定のタイプの各サブネット (サブネット 1 とサブネット 2、コレクション内の文字列 `["1", "2"]`) を反復処理します。
-
-::alert[`["1", "2"]` サンプルコレクションの要素である数値 `1` と `2` は、引用符で囲んで表現しています。コレクションは文字列のリストでなければならないからです。]{type="warning"}
-
-内部ループ `${SubnetType}Subnet${SubnetNumber}` の `OutputKey` セクションで、各リソースの論理 ID の名前を作成します。各リソースの論理 ID の名前は、外部ループと内部ループの両方がコレクションを反復処理するため、それぞれのループで定義したコレクション (`[Public, Private]` と `["1", "2"]`) を繰り返し、リソースの論理 ID が `PublicSubnet1`、`PublicSubnet2`、`PrivateSubnet1`、`PrivateSubnet2` になります。
-
-内部ループの各反復では、上記の 4 つの論理 ID の他に、`Fn::FindInMap` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html) を使って各リソースのプロパティが設定されます。`SubnetCIDRS` マッピングから CIDR アドレス情報を取得し、`Fn::GetAZs` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getavailabilityzones.html) でサブネットのアベイラビリティーゾーンを選択するためのインデックスを取得します。`SubnetAZIndexes` マッピングのインデックスに使用される目的は、同じアベイラビリティゾーンに ID 1 のパブリックサブネットとプライベートサブネットを作成し、ID 2 のパブリックサブネットとプライベートサブネットを別のアベイラビリティゾーンに作成することです。この選択の理由は、アベイラビリティーゾーン内のトラフィックを最適化し、プライベートサブネットのリソースを NAT ゲートウェイと同じアベイラビリティーゾーンに配置し、関連するパブリックサブネットに合わせます。(例えば、`PrivateSubnet1` に `PublicSubnet1` に関連付けられた NAT ゲートウェイターゲットを使用させる場合などです。) 詳細については、Amazon VPC ユーザガイドの [NAT ゲートウェイ](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-nat-gateway.html) を参照してください。
-
-内部ループの繰り返しで複製されるサブネットのその他のプロパティには、`Tags` と `VpcId` があります。
-
-他に必要なリソースを定義していきましょう。今回は、2 つのパブリックルートテーブルと 2 つのプライベートルートテーブルを定義し、そのルートテーブルを上記で定義したサブネットに関連付けます。既存の内部ループに次のコードを追加します。(インデントが正しいことに注意してください。`${SubnetType}routeTable${SubnetNumber}` の列は、上記の `${SubnetType}Subnet${SubnetNumber}` の列と同じく、`10` 列目とでなければなりません。)
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=86}
- ${SubnetType}RouteTable${SubnetNumber}:
- Type: AWS::EC2::RouteTable
- Properties:
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
- VpcId: !Ref Vpc
- ${SubnetType}SubnetRouteTableAssociation${SubnetNumber}:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref
- Fn::Sub: ${SubnetType}RouteTable${SubnetNumber}
- SubnetId: !Ref
- Fn::Sub: ${SubnetType}Subnet${SubnetNumber}
-:::
-
-上記では、最初のブロックで 4 つのルートテーブル (2 つはパブリック、2 つはプライベート) を作成し、2 番目のブロックでは、同じ反復ループ内で定義しているサブネットに関連付けます。
-
-これで、このラボのサンプルユースケースに必要なサブネットが用意され、各サブネットにルートテーブルが関連付けられました。次は、このサンプルユースケースの要件であると想定されるすべての IPv4 宛先 (`0.0.0.0/0`) へのデフォルトルートを追加します。これで、`0.0.0.0/0` CIDR はパブリックサブネットとプライベートサブネットの両方に割り当てるルートは同じですが、パブリックサブネットのルートには先に作成した `InternetGateway` がターゲットになり、プライベートサブネットのルートには代わりにネットワークアドレス変換 (NAT) の仕組みが必要になります。次に、パブリックルートとプライベートルートの 2 つの別々の新しいループイテレーションで記述し、それぞれのタイプに特化したビジネスロジックでパブリックルートとプライベートルートを分けます。
-
-まずは、パブリックサブネット用のルートを作成し、先ほど定義したパブリックルートテーブルに追加します。ここでは、右に 2 列 (つまり、列番号 `2`) をインデントする新しいループを作成し、以下の内容を `vpc.yaml` ファイルに追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=101}
- Fn::ForEach::DefaultRoutesForPublicSubnets:
- - SubnetNumber
- - ["1", "2"]
- - DefaultRouteForPublicSubnet${SubnetNumber}:
- DependsOn: VpcGatewayAttachment
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref
- Fn::Sub: PublicRouteTable${SubnetNumber}
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-:::
-
-上記の新しいループでは、パブリックサブネット用の 2 つの `AWS::EC2::Route` リソースについて記述しました。つまり、それぞれが `InternetGateway` (このラボで使用しているテンプレートですでに定義されています) をターゲットとするデフォルトルートとして設定されています。
-
-::alert[上記の `AWS::EC2::Route` リソースは `dependsOn` 属性を使用して VPC ゲートウェイアタッチメントへの明示的な依存関係を追加します。次に定義する `AWS::EC2::EIP` リソースについても同じです。現在のコンテキストでこれらのリソースに `DependsOn` が必要な理由について詳しくは、[DependsOn 属性が必須の場合](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html#gatewayattachment) を参照してください]{type="warning"}
-
-次に、プライベートサブネットのルートを設定する必要があります。そのためには、2 つの `AWS::EC2::EIP` [リソース](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-eip.html) を記述する新しいループを作成します。このループは、後でこの新しいループで定義する 2 つの `AWS::EC2::NATGateway` リソースに使用します。また、各 NAT ゲートウェイをそれぞれターゲットとするプライベートサブネットの 2 つのルートについても記述します。新しいループの次のコードをテンプレートに追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=113}
- Fn::ForEach::NatGateways:
- - SubnetNumber
- - ["1", "2"]
- - Eip${SubnetNumber}:
- DependsOn: VpcGatewayAttachment
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
- NatGateway${SubnetNumber}:
- Type: AWS::EC2::NatGateway
- Properties:
- AllocationId: !GetAtt
- - !Sub Eip${SubnetNumber}
- - AllocationId
- SubnetId: !Ref
- Fn::Sub: PublicSubnet${SubnetNumber}
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
- DefaultRouteForPrivateSubnet${SubnetNumber}:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref
- Fn::Sub: PrivateRouteTable${SubnetNumber}
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref
- Fn::Sub: NatGateway${SubnetNumber}
-:::
-
-上記のコードでは、作成している 2 つの elastic IP リソースの論理 ID (`Eip${SubnetNumber}`)、2 つの NAT ゲートウェイの論理 ID (`NATGateway${SubnetNumber}`)、およびプライベートサブネットの 2 つのルートの論理 ID (`defaultRouteForPrivateSubnet${SubnetNumber}`) をご確認ください。
-
-さらに、NAT ゲートウェイリソースの `allocationId` [property](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html#cfn-ec2-natgateway-allocationid) にも注目してください。このプロパティを記述するときは、`Fn::GetAtt` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html) を使用して、elastic IP リソースの論理 ID も渡すことにより、関連する elastic IP リソースの割り当て ID を使用します。上の例では、最初に `Fn::Sub` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) を使用して、各 elastic IP リソース (`!Sub Eip${SubnetNumber}`) の論理 ID を作成します。次に `Ref` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) を使用して、形成された論理 ID をテンプレートに記述されている関連リソースへの参照として渡します (この場合は、反復ループの一部として記述されます)。`AWS::EC2::Route` リソースの `RouteTableId` プロパティは、ルートテーブルの論理 ID を形成する際に同様のロジック (`Fn::Sub::PrivateRouteTable${SubnetNumber}`) を使用します。`AWS::EC2::NATGateway` リソースの `SubnetId` プロパティも同じです。
-
-さて、コードで記述した VPC 関連リソースのインフラストラクチャをプロビジョニングしましょう!ラボのこの部分で行ってきたすべての変更を含む `vpc.yaml` ファイルを保存し、以下の手順に沿って `vpc.yaml` ファイルを使用して `looping-over-collections-vpc` という名前の新しいスタックを作成します。新しいスタックは `us-east-1` リージョンに作成します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-次の AWS CLI コマンドを実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name looping-over-collections-vpc \
---template-body file://vpc.yaml \
---region us-east-1 \
---capabilities CAPABILITY_AUTO_EXPAND
-:::
-
-上記のコマンドは、作成しているスタックの ID を返すはずです。[wait stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) AWS CLI コマンドを使用して、スタックが `CREATE_COMPLETE` ステータスになるまで待ちます。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---region us-east-1 \
---stack-name looping-over-collections-vpc
-:::
-
-::::
-::::tab{id="local" label="ローカル開発"}
-手順
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-2. **米国東部 (バージニア北部)** リージョンにいることを確認してください。
-3. 左側のナビゲーションパネルから、**スタック** を選択します。
-4. ページの右側から、**スタックの作成** を選択し、**新しいリソースを使用 (標準)** を選択します。
-5. **前提条件 - テンプレートの準備** から、**テンプレートの準備完了** を選択します。
-6. **テンプレートの指定** セクションで、**テンプレートソース** で **テンプレートファイルのアップロード** を選択します。
-7. **ファイルの選択** を選択し、前に更新した `vpc.yaml` テンプレートを指定します。**次へ** を選択します。
-8. **スタックの詳細を指定** ページで、**スタック名** を `looping-over-collections-vpc` と指定します。**次へ** を選択します。
-9. **スタックオプションの設定** では、設定をそのままにしておきます。**次へ** を選択します。
-10. **レビュー** ページで、ページの内容を確認します。ページの下部で、**機能と変換** セクションに表示されている機能をすべて承認するように選択してください。**送信** を選択します。
-11. スタックが `CREATE_COMPLETE` ステータスになるまで、スタック作成ページを更新します。
-::::
-:::::
-
-上記のどちらかの方法で新しいスタックを作成したら、引き続きラボのパート 1 で説明したと同様に、`looping-over-collections-vpc` スタックの **テンプレート** タブと **リソース** タブに移動します。送信したテンプレートを処理済みのテンプレートを比較し、コレクションをループする方法によってコードの保守性がどのように向上したかを確認します。
-
-おめでとうございます!ラボのパート 2 を終了し、より複雑なユースケースが必要な時にインナーループを使用する方法を学びました。
-
-### チャレンジ
-
-このチャレンジでは、`Fn::ForEach` を使用して `vpc.yaml` ファイルの `Outputs` [セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) にパブリックサブネットとプライベートサブネットの ID を追加する必要があります。出力の要件は以下のとおりです。
-
-* `vpc.yaml` テンプレートに `Outputs` セクションを追加してください。
-* 出力をわかりやすくするために、各出力のコメントに以下のような説明を入れてください。
- * `The ID of PublicSubnet1.`
- * `The ID of PublicSubnet2.`
- * `The ID of PrivateSubnet1.`
- * `The ID of PrivateSubnet2.`
-* 関連するサブネット ID への参照として、各出力に `Value` を追加します。
-* 出力ごとに `Export` と [Name](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) を追加して、将来的に他のスタックから [インポート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) できるようにします。`YOUR_AWS_ACCOUNT_ID-SUBNET_TYPESubnetSUBNET_NUMBERId` のように各エクスポートの名前を作成します。例えば最初のサブネットが `111122223333-PublicSubnet1ID` のようになります。
-
-:::expand{header="ヒントが必要ですか?"}
-* 同じ外部 + 内部ループロジックを使用して 2 つのパブリックサブネットと 2 つのプライベートサブネットを作成したように、`Outputs` セクションに記述するコンテンツに再利用します。
-* 出力のループロジックを構築するときは、出力の [構造](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) の記述方法を思い出してください。
-* 各出力の `Value` を記述するときは、サブネットの論理 ID を参照する必要がありますが、まず `Fn::Sub` を使用してサブネットの論理 ID を作成する必要があります。`AWS::EC2::Route` リソースの記述に使用した内部ループで `RouteTableId` の参照値を作成するために使用したサンプルパターン、または `AWS::EC2::NatGateway` リソースの `SubnetId` プロパティをご確認ください。
-* 現在使用している AWS アカウントの ID を返すのに使用できる [擬似パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html) はありそうですか?
-:::
-
-::::::expand{header="解決策を確認しますか?"}
-ソリューションの一式はこのファイルは `code/solutions/looping-over-collections` ディレクトリにある `vpc.yaml` ファイルにあります。
-
-次の内容を `vpc.yaml` ファイルに追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=141}
-Outputs:
- Fn::ForEach::SubnetIdsOutputs:
- - SubnetType
- - [Public, Private]
- - Fn::ForEach::SubnetNumbers:
- - SubnetNumber
- - ["1", "2"]
- - ${SubnetType}Subnet${SubnetNumber}:
- Description: !Sub 'The ID of ${SubnetType}Subnet${SubnetNumber}.'
- Export:
- Name: !Sub ${AWS::AccountId}-${SubnetType}Subnet${SubnetNumber}Id
- Value: !Ref
- Fn::Sub: ${SubnetType}Subnet${SubnetNumber}
-:::
-
-次に、既存の `looping-over-collections-vpc` スタックを以下の `Outputs` 情報を含むテンプレートで更新します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-次の AWS CLI コマンドを実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name looping-over-collections-vpc \
---template-body file://vpc.yaml \
---region us-east-1 \
---capabilities CAPABILITY_AUTO_EXPAND
-:::
-
-[wait stack-update-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-update-complete.html) AWS CLI コマンドを使用して、スタックが `UPDATE_COMPLETE` ステータスになるまで待ちます。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-update-complete \
---region us-east-1 \
---stack-name looping-over-collections-vpc
-:::
-
-::::
-::::tab{id="local" label="ローカル開発"}
-手順
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/) に移動します。
-2. **米国東部 (バージニア北部)** リージョンにいることを確認してください。
-3. 左側のナビゲーションパネルから、**スタック** を選択します。
-4. スタックのリストから既存の `looping-over-collections-vpc` スタックを選択します。
-5. ページの右側から、**更新** を選択します。
-6. **前提条件 - テンプレートの準備** から、**既存テンプレートを置き換える** を選択します。
-7. **テンプレートの指定** セクションで、**テンプレートソース** で、**テンプレートファイルのアップロード** を選択します。
-8. **ファイルの選択** を選択し、更新した `vpc.yaml` テンプレートを指定します。**次へ** を選択します。
-9. **スタックの詳細を指定** ページで、**次へ** を選択します。
-10. **スタックオプションの設定** では、設定をそのままにしておきます。**次へ** を選択します。
-11. **レビュー** ページで、ページの内容を確認します。ページの下部で、**機能と変換** セクションに表示されている機能をすべて承認するように選択してください。**送信** を選択します。
-12. スタックが `UPDATE_COMPLETE` ステータスになるまで、スタック作成ページを更新します。
-::::
-:::::
-
-スタックの更新が完了すると、CloudFormation コンソールのスタックの `出力` タブに出力が表示されるはずです。
-::::::
-
-### クリーンアップ
-
-次に、このラボで作成したリソースを削除します。以下の手順を実行してください。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-次の AWS CLI コマンドを実行して、`looping-over-collections-s3-buckets` スタックを削除します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---region us-east-1 \
---stack-name looping-over-collections-s3-buckets
-:::
-
-[wait stack-delete-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-delete-complete.html) AWS CLI コマンドを使用して、`DELETE` 操作が完了するまでお待ちください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---region us-east-1 \
---stack-name looping-over-collections-s3-buckets
-:::
-
-完了したら、上記の手順を繰り返して `looping-over-collections-vpc` スタックを削除します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---region us-east-1 \
---stack-name looping-over-collections-vpc
-:::
-
-[wait stack-delete-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-delete-complete.html) AWS CLI コマンドを使用して、`DELETE` 操作が完了するまでお待ちください。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---region us-east-1 \
---stack-name looping-over-collections-vpc
-:::
-
-::::
-::::tab{id="local" label="ローカル"}
-手順
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-2. **米国東部 (バージニア北部)** リージョンにいることを確認してください。
-3. **スタック** ページから、`looping-over-collections-s3-buckets` スタックを選択します。
-4. スタックの詳細ペインで、**削除** を選択します。プロンプトが表示されたら、**削除** を選択します。
-5. **スタック** ページから `looping-over-collections-vpc` スタックを選択します。
-6. スタックの詳細ペインで、**削除** を選択します。プロンプトが表示されたら、**削除** を選択します
-::::
-:::::
-
-### まとめ
-
-`Fn::ForEach` 組み込み関数と `AWS::LanguageExtensions` トランスフォームを使ってコレクションをループさせる方法を学びました。詳細については、AWS CloudFormation ユーザガイドの [Fn::ForEach](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-foreach.html) と、[Exploring Fn::ForEach and Fn::FindInMap enhancements in AWS CloudFormation](https://aws.amazon.com/jp/blogs/devops/exploring-fnforeach-and-fnfindinmap-enhancements-in-aws-cloudformation/) を参照してください。[cfn-language-discussion](https://github.com/aws-cloudformation/cfn-language-discussion) GitHub リポジトリで RFC への貢献やフィードバックを歓迎します!
diff --git a/content/intermediate/templates/looping-over-collections/index.md b/content/intermediate/templates/looping-over-collections/index.md
deleted file mode 100644
index de44e0f06..000000000
--- a/content/intermediate/templates/looping-over-collections/index.md
+++ /dev/null
@@ -1,523 +0,0 @@
----
-title: "Looping over collections with Fn::ForEach"
-weight: 641
----
-
-_Lab Duration: ~45 minutes_
-
----
-
-### Overview
-
-When you describe infrastructure with code, there are use cases where the code you write describes resources that share the same configuration, or that contains some differences that could be managed with mechanisms like variables. As the number of such resources and relevant properties grow, the code you write grows as well, thus making it not easy to maintain over time, and prone to human errors.
-
-In the [Language extensions](../language-extensions) lab, you’ve used the `AWS::LanguageExtensions` [transform](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-aws-languageextensions.html) to leverage a number of functions that extend the [AWS CloudFormation](https://aws.amazon.com/cloudformation/) language: such functions are the result of feedback that the CloudFormation team receives from the community via open discussions driven by an [RFC mechanism](https://github.com/aws-cloudformation/cfn-language-discussion). One of these functions is the `Fn::ForEach` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-foreach.html), that you’ll learn how to use in this lab. This intrinsic function allows you to describe resources, that share the same/similar configuration, with dynamic iterations that you use to map resource configurations to loop-like structures.
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* Identify example use cases where you can simplify and reduce statically-described code, for resources that share the same/similar configuration, using `Fn::ForEach`.
-* Describe, with code, the desired state of resources by using `Fn::ForEach` to loop over collections.
-* Discover, for applicable use cases, how you can use `Fn::ForEach` to have fewer lines of code, thus leading to code that is easier to maintain, and less prone to human errors.
-
-### Start lab
-
-### Lab part 1: basic looping over a collection for S3 buckets
-
-Let’s start with an example use case: you’re tasked with describing 3 [Amazon Simple Storage Service (Amazon S3)](https://aws.amazon.com/s3/) buckets that will have a number of configuration properties in common, for example [bucket encryption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-bucketencryption.html) set to use [AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/), [lifecycle configuration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-lifecycleconfig.html) set to transition to the `GLACIER` [storage class](https://aws.amazon.com/s3/storage-classes/) after 30 days and to expire objects after 1 year, `PublicAccessBlockConfiguration` [properties](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html) set to `true`, and tags set to use `aws-cloudformation-workshop` as the tag value for the `Name` tag key.
-
-S3 buckets you’re tasked to describe with code share the same properties in this use case. While you certainly can describe all of them with three discrete code blocks, in this lab you choose to use `Fn::ForEach` to reduce the code size and relative complexity, so that you describe all the three buckets once with a single, iterative structure. This also has the benefit of having code that is easier to maintain, and it helps with reducing human errors as well.
-
-If you were to describe the three S3 buckets above *without* `Fn::ForEach`, the resulting template would be something like the following one, shown here as an example:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-AWSTemplateFormatVersion: "2010-09-09"
-
-Description: AWS CloudFormation workshop lab - sample S3 buckets with the same configuration settings.
-
-Resources:
- S3Bucket1:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: aws:kms
- LifecycleConfiguration:
- Rules:
- - ExpirationInDays: 365
- Id: Example Glacier Rule
- Status: Enabled
- Transitions:
- - StorageClass: GLACIER
- TransitionInDays: 30
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
-
- S3Bucket2:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: aws:kms
- LifecycleConfiguration:
- Rules:
- - ExpirationInDays: 365
- Id: Example Glacier Rule
- Status: Enabled
- Transitions:
- - StorageClass: GLACIER
- TransitionInDays: 30
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
-
- S3Bucket3:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: aws:kms
- LifecycleConfiguration:
- Rules:
- - ExpirationInDays: 365
- Id: Example Glacier Rule
- Status: Enabled
- Transitions:
- - StorageClass: GLACIER
- TransitionInDays: 30
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
-:::
-
-In this lab, you choose to use `Fn::ForEach` to describe the S3 bucket configuration properties only once, by looping over a collection of buckets. This means that, in this case, the initial template you'll use will have fewer lines of code, thus making it easier to maintain. As a result, you’ll have a template, processed by the `AWS::LanguageExtensions` transform, that will describe content like the above, with three S3 bucket resources having the same properties but different [logical IDs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html), such as `S3Bucket1`, `S3Bucket2`, and `S3Bucket3`.
-
-Let’s get started! Navigate to the `code/workspace/looping-over-collections` directory, and open the `s3-buckets.yaml` file in your favorite text editor.
-
-::alert[Note the `Transform: AWS::LanguageExtensions` line, that is already present in the `s3-buckets.yaml` template you just opened (you've already used this transform in the [Language extensions](../language-extensions) lab). This line activates the language extension [transform](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-aws-languageextensions.html), that is *required* in order to use the `Fn::ForEach` intrinsic function.]{type="warning"}
-
-With the `s3-buckets.yaml` file opened in your text editor, remove the TODO reminder line that is commented out, and append the code shown next to the `Resources` section (indentation matters - make sure the leading character of the `Fn::ForEach::S3Buckets` line starts at column number `2` in your editor):
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=8}
- Fn::ForEach::S3Buckets:
- - S3BucketLogicalId
- - [S3Bucket1, S3Bucket2, S3Bucket3]
- - ${S3BucketLogicalId}:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: aws:kms
- LifecycleConfiguration:
- Rules:
- - Id: Example Glacier Rule
- ExpirationInDays: 365
- Status: Enabled
- Transitions:
- - TransitionInDays: 30
- StorageClass: GLACIER
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
-:::
-
-Save the updated file to disk. Looking at the code you just pasted, you note that the content starting from the `Type: AWS::S3::Bucket` line is something you’ve seen in the example at the beginning of this lab: it is the same set of properties that all the three S3 buckets have in common. Let’s look into the lines that are above `Type: AWS::S3::Bucket` to understand how `Fn::ForEach` works!
-
-In this example, you want to iterate over a three-element collection, that is composed of the three S3 buckets. You choose to create this collection as `[S3Bucket1, S3Bucket2, S3Bucket3]`, and use each of the elements, that are denoted by the `S3BucketLogicalId` identifier described above the collection itself. In this example, you described the collection as an array, but you could also have used a reference to a template [parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) of type `CommaDelimitedList`.
-
-On the top of the code you pasted, you note the `Fn::ForEach::S3Buckets:` line, that describes the intent of using `Fn::ForEach` to iterate over a collection. The rightmost part of the line, `S3Buckets`, indicates the name you choose for the loop. When you create a loop, make sure you indicate a name that is unique within the template: do not choose a name used for another loop in the template, and that you used or plan to use for the logical ID of a resource in the same template.
-
-The line right above `Type: AWS::S3::Bucket`, that is `${S3BucketLogicalId}:`, denotes the `OutputKey` content that you’ll find in the template that will be transformed. In this case, the value of `OutputKey` will be the logical ID of each of the 3 S3 buckets: `S3Bucket1` in the first loop iteration, `S3Bucket2` in the second, and `S3Bucket3` in the third.
-
-The lines starting with `Type: AWS::S3::Bucket` and below, in the example, constitute the `OutputValue` that will be replicated for each `OutputKey` in the processed template. These lines contain the common configuration that will be applied to the three S3 bucket resources with the logical IDs mentioned in the previous paragraph.
-
-::alert[CloudFormation uses service quotas that are applied to the processed template. For more information on CloudFormation service quotas, see [AWS CloudFormation quotas](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html) in the CloudFormation User Guide.]{type="warning"}
-
-It’s now time to create a new CloudFormation stack, to see how your three S3 buckets will be provisioned by looping over the collection you described above! You'll create a new stack in the `us-east-1` region.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-Run the following AWS CLI command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name looping-over-collections-s3-buckets \
---template-body file://s3-buckets.yaml \
---region us-east-1 \
---capabilities CAPABILITY_AUTO_EXPAND
-:::
-
-The command above should return the ID of the stack you are creating. Wait until the stack is in the `CREATE_COMPLETE` status by using the [wait stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) AWS CLI command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---region us-east-1 \
---stack-name looping-over-collections-s3-buckets
-:::
-
-::::
-::::tab{id="local" label="Local development"}
-Steps:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Make sure you are in the **US East (N. Virginia)** region.
-1. From the left navigation panel, select the **Stacks** tab.
-1. From the right side of the page, choose **Create Stack**, and then choose **With new resources (standard).**
-1. From **Prerequisite**-**Prepare template**, choose **Template is ready**.
-1. Under **Specify template**, select **Template source**, and choose **Upload a template file**.
-1. Select **Choose file**, and provide the `s3-buckets.yaml` template you updated earlier. Choose **Next**.
-1. In the **Specify Stack details** page, specify a **Stack** name: `looping-over-collections-s3-buckets`. Choose **Next**.
-1. On **Configure Stack options**, leave the configuration as it is. Choose **Next**.
-1. On the **Review** page, review the contents of the page. At the bottom of the page, choose to acknowledge all the capabilities shown in the **Capabilities and transforms** section. Choose **Submit**.
-1. Refresh the stack creation page until you see the stack to be in the `CREATE_COMPLETE` status.
-::::
-:::::
-
-When stack creation is complete, navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/), and locate the `looping-over-collections-s3-buckets` stack. Select the stack, and then select the **Template** pane. Note the following:
-
-* you should see the initial template you provided, that uses the loop over the collection of buckets you described;
-* choose **View processed template**: you should see the expanded template, that instead of the looping structure shows the three S3 buckets statically described, as a result of the processing. Note that you’ll see the processed configuration in JSON format;
-* navigate to the **Resources** tab, and note the 3, newly-created S3 buckets whose logical IDs should be `S3Bucket1`, `S3Bucket2`, and `S3Bucket3`.
-
-Congratulations! You have completed the first part of this lab, and have learned the basics of `Fn::ForEach`. In the next part, you’ll go over a new example with more moving parts.
-
-### Lab part 2: inner loops for VPC-related resources
-
-In this part of the lab, you’ll learn how to nest `Fn::ForEach` looping structures, when needed. Recall the usage of `Fn::ForEach` above: you pass the following parameters to the intrinsic function, right below the definition of the unique loop:
-
-* `Identifier`
-* `Collection`
-* `OutputKey`
-
-In the previous example, you have used `${S3BucketLogicalId}:` as the `OutputKey` for the logical ID of each bucket you wanted to create. In this example, you’ll use another `Fn::ForEach` loop instead for the `OutputKey`, to drive an inner looping logic for a new use case: the creation of resources related to an [Amazon Virtual Private Cloud (Amazon VPC)](https://aws.amazon.com/vpc/) resource.
-
-Let’s get started! Make sure you are in the `code/workspace/looping-over-collections` directory, and open the `vpc.yaml` file in your favorite text editor. Note the `Transform: AWS::LanguageExtensions` line in the code, that is *required* for the `Fn::ForEach` intrinsic function you’ll use next. The template already describes a VPC [resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html), an `InternetGateway` [resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html), and a `VPCGatewayAttachment` [resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html) without the use of `Fn::ForEach`, because you’re defining such resources only once in the template. In the template, you can also find a `Mappings` [section](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html) with a number of settings for the VPC and VPC-related resources that you’ll use next.
-
-Remove the TODO reminder line in the file you just opened, and append the code shown next, to start describing public and private subnets. Make sure the level of indentation is the same as for the `VpcGatewayAttachment` resource declaration (that is, starting at column `2`):
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=63}
- Fn::ForEach::SubnetTypes:
- - SubnetType
- - [Public, Private]
- - Fn::ForEach::SubnetNumbers:
- - SubnetNumber
- - ["1", "2"]
- - ${SubnetType}Subnet${SubnetNumber}:
- Type: AWS::EC2::Subnet
- Properties:
- AvailabilityZone: !Select
- - !FindInMap
- - SubnetAzIndexes
- - !Ref SubnetType
- - !Ref SubnetNumber
- - !GetAZs ""
- CidrBlock: !FindInMap
- - SubnetCidrs
- - !Ref SubnetType
- - !Ref SubnetNumber
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
- VpcId: !Ref Vpc
-:::
-
-The code you added above shows the intent of describing two public subnets, and two private subnets for a total of 4 `AWS::EC2::Subnet` resources.
-
-With the first `Fn::ForEach::SubnetTypes` loop, you iterate over the collection of subnet types (public and private), and with the second, inner loop (that you are using here as your `OutputKey`), you iterate through each subnet (subnet 1 and subnet 2, using the strings `["1", "2"]` in the collection), of a specific type (public, private).
-
-::alert[The numbers `1` and `2`, that are elements of the `["1", "2"]` example collection, are represented here as quoted because a collection must be a list of strings.]{type="warning"}
-
-In the `OutputKey` section of the inner loop, `${SubnetType}Subnet${SubnetNumber}`, you compose the name of the logical ID of each resource that, respectively, will be `PublicSubnet1`, `PublicSubnet2`, `PrivateSubnet1`, and `PrivateSubnet2` as both outer and inner loops iterate through the collections (`[Public, Private]`, and `["1", "2"]`) that you defined in the loops.
-
-In each inner loop iteration, besides the four logical IDs above, each resource will have its properties configured to pull CIDR addressing information from the `SubnetCidrs` mapping via the `Fn::FindInMap` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html), as well as the indexes to use when selecting Availability Zones for subnets with the `Fn::GetAZs` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getavailabilityzones.html). The intent with the configuration used for the indexes in the `SubnetAzIndexes` mapping is to create public and private subnets with ID 1 in the same Availability Zone, and public and private subnets with ID 2 in a different Availability Zone: the reason behind this choice is to optimize Availability Zone-related traffic, so to have resources for a private subnet in the same Availability Zone as the NAT gateway, that you associate to the relevant public subnet (for example, to have `PrivateSubnet1` use the NAT gateway target that is associated to `PublicSubnet1`). For more information, see [NAT gateways](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html) in the Amazon VPC User Guide.
-
-Other properties, for subnets, that will be replicated over inner loop iterations also include `Tags` and `VpcId`.
-
-Let’s continue to describe other resources you’ll need: this time, you want to describe two public and two private route tables, and then associate such route tables to the relevant subnets you defined above. Add the following code to the existing inner loop (make sure the indentation is correct: the column where `${SubnetType}RouteTable${SubnetNumber}` starts must be the same as where `${SubnetType}Subnet${SubnetNumber}` above starts, which is column `10`):
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=86}
- ${SubnetType}RouteTable${SubnetNumber}:
- Type: AWS::EC2::RouteTable
- Properties:
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
- VpcId: !Ref Vpc
- ${SubnetType}SubnetRouteTableAssociation${SubnetNumber}:
- Type: AWS::EC2::SubnetRouteTableAssociation
- Properties:
- RouteTableId: !Ref
- Fn::Sub: ${SubnetType}RouteTable${SubnetNumber}
- SubnetId: !Ref
- Fn::Sub: ${SubnetType}Subnet${SubnetNumber}
-:::
-
-With the above, you create four route tables (two public, and two private) with the first block and, with the second block, you associate them to the relevant subnets you’re defining within the same inner loop iterations.
-
-Now that you have the subnets you need for this lab’s example use case, and that each subnet has a route table associated to it, it’s time to add default routes to all IPv4 destinations (`0.0.0.0/0`) that are assumed to be a requirement in your example use case as well. Now, while the `0.0.0.0/0` CIDR is going to be the same for routes you’ll assign to both public and private subnets, public routes will need the `InternetGateway` you created earlier as a target, whereas private subnets will need a Network Address Translation (NAT) mechanism instead. You then choose to describe public and private routes with two separate, new loop iterations to decouple public from private routes in specialized business logic for each type.
-
-Let’s start with creating routes for public subnets first, that we’ll add to the public route tables you described earlier; here, you create a new loop that you’ll indent 2 columns to the right (that is, column number `2`); add the content below to the `vpc.yaml` file:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=101}
- Fn::ForEach::DefaultRoutesForPublicSubnets:
- - SubnetNumber
- - ["1", "2"]
- - DefaultRouteForPublicSubnet${SubnetNumber}:
- DependsOn: VpcGatewayAttachment
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref
- Fn::Sub: PublicRouteTable${SubnetNumber}
- DestinationCidrBlock: 0.0.0.0/0
- GatewayId: !Ref InternetGateway
-:::
-
-With the new loop above, you described 2 `AWS::EC2::Route` resources for public subnets - that is, each is configured to be a default route with the `InternetGateway` (that is already described in the template you're using for this lab) as a target.
-
-::alert[The `AWS::EC2::Route` resources described above use the `DependsOn` attribute to add an explicit dependency on the VPC gateway attachment. The same is also true for `AWS::EC2::EIP` resources you'll define next. See [When a DependsOn attribute is required](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html#gatewayattachment) to learn more on why these resources need `DependsOn` in the current context.]{type="warning"}
-
-You’ll now need to set up routes for private subnets. For this, you choose to create a new loop where you describe 2 `AWS::EC2::EIP` [resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-eip.html), that you’ll use for 2 `AWS::EC2::NatGateway` resources you’ll define in this new loop as well later on. You’ll also describe two routes for private subnets that will have each NAT gateway as a target, respectively. Add the following code for the new loop to the template:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=113}
- Fn::ForEach::NatGateways:
- - SubnetNumber
- - ["1", "2"]
- - Eip${SubnetNumber}:
- DependsOn: VpcGatewayAttachment
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
- NatGateway${SubnetNumber}:
- Type: AWS::EC2::NatGateway
- Properties:
- AllocationId: !GetAtt
- - !Sub Eip${SubnetNumber}
- - AllocationId
- SubnetId: !Ref
- Fn::Sub: PublicSubnet${SubnetNumber}
- Tags:
- - Key: Name
- Value: aws-cloudformation-workshop
- DefaultRouteForPrivateSubnet${SubnetNumber}:
- Type: AWS::EC2::Route
- Properties:
- RouteTableId: !Ref
- Fn::Sub: PrivateRouteTable${SubnetNumber}
- DestinationCidrBlock: 0.0.0.0/0
- NatGatewayId: !Ref
- Fn::Sub: NatGateway${SubnetNumber}
-:::
-
-In the code above, note the logical IDs for the two elastic IP resources you’re creating (`Eip${SubnetNumber}`), the logical IDs for the two NAT gateways (`NatGateway${SubnetNumber}`), and the logical IDs for the two routes for private subnets (`DefaultRouteForPrivateSubnet${SubnetNumber}`).
-
-Moreover, note the `AllocationId` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html#cfn-ec2-natgateway-allocationid) of the NAT gateway resource: when you describe this property, you use the `Fn::GetAtt` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html) to consume the allocation ID of the relevant elastic IP resource, by passing the logical ID of the elastic IP resource as well. In the example above, you first use the `Fn::Sub` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) to compose the logical ID of each elastic IP resource (`!Sub Eip${SubnetNumber}`), and then you use the `Ref` [intrinsic function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) to pass the composed logical ID as a reference for the relevant resource described in the template (in this case, described as part of a looping iteration). The `RouteTableId` property for `AWS::EC2::Route` resources uses a similar logic (`Fn::Sub: PrivateRouteTable${SubnetNumber}`) when composing the logical ID of the route table. The same also holds true for the `SubnetId` property of the `AWS::EC2::NatGateway` resource.
-
-It’s now time to provision the infrastructure for the VPC-related resources you described with code! Save the `vpc.yaml` file with all the changes you’ve been applying along this part of the lab, and follow the indications below to create a new stack, called `looping-over-collections-vpc`, using the `vpc.yaml` file. You'll create the new stack in the `us-east-1` region.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-Run the following AWS CLI command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack \
---stack-name looping-over-collections-vpc \
---template-body file://vpc.yaml \
---region us-east-1 \
---capabilities CAPABILITY_AUTO_EXPAND
-:::
-
-The command above should return the ID of the stack you are creating. Wait until the stack is in the `CREATE_COMPLETE` status by using the [wait stack-create-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-create-complete.html) AWS CLI command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-create-complete \
---region us-east-1 \
---stack-name looping-over-collections-vpc
-:::
-
-::::
-::::tab{id="local" label="Local development"}
-Steps:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Make sure you are in the **US East (N. Virginia)** region.
-1. From the left navigation panel, select the **Stacks** tab.
-1. From the right side of the page, choose **Create Stack**, and then choose **With new resources (standard).**
-1. From **Prerequisite - Prepare template**, choose **Template is ready**.
-1. Under **Specify template**, select **Template source**, and choose **Upload a template file**.
-1. Select **Choose file**, and provide the `vpc.yaml` template you updated earlier. Choose **Next**.
-1. In the **Specify Stack details** page, specify a **Stack** name: `looping-over-collections-vpc`. Choose **Next**.
-1. On **Configure Stack options**, leave the configuration as it is. Choose **Next**.
-1. On the **Review** page, review the contents of the page. At the bottom of the page, choose to acknowledge all the capabilities shown in the **Capabilities and transforms** section. Choose **Submit**.
-1. Refresh the stack creation page until you see the stack to be in the `CREATE_COMPLETE` status.
-::::
-:::::
-
-Once you created the new stack with the method of your choice, continue to follow directions you found in part 1 of the lab to navigate to the **Template** and **Resources** sections, this time for the `looping-over-collections-vpc` stack: compare the template you provided with the processed one, to see how the code maintainability has improved with the method of looping over collections.
-
-Congratulations! You completed the second part of the lab, and learned how to use inner loops when needed in more complex use cases.
-
-### Challenge
-
-In this challenge, you’re tasked with adding the IDs of public and private subnets to the `Outputs` [section](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) of the `vpc.yaml` file, using `Fn::ForEach`. Requirements for outputs are:
-
-* add the `Outputs` section in the `vpc.yaml` template;
-* add a meaningful description for each output, so that it will contain text composed such as:
- * `The ID of PublicSubnet1.`
- * `The ID of PublicSubnet2.`
- * `The ID of PrivateSubnet1.`
- * `The ID of PrivateSubnet2.`
-* Add the `Value` for each output, as a reference to the relevant subnet ID.
-* Add the `Export` [name](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) for each output, so that you can [consume](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) it from other stacks in the future. Create the name of each export using this pattern: `YOUR_AWS_ACCOUNT_ID-SUBNET_TYPESubnetSUBNET_NUMBERId`; example for the first public subnet: `111122223333-PublicSubnet1Id`.
-
-:::expand{header="Need a hint?"}
-* Use the same outer + inner loops logic you followed to create the two public and the two private subnets, and apply it to content you'll write underneath the `Outputs` section.
-* Make sure you recall how to describe the [structure](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) of an output when you build the looping logic for your outputs.
-* When you describe the `Value` of each output, you’ll need to reference the logical ID of a subnet, but you need to compose it first using `Fn::Sub`. Look at the example pattern you used for composing the referenced value for `RouteTableId` in the inner loop you used to describe `AWS::EC2::Route` resources, or the `SubnetId` property of the `AWS::EC2::NatGateway` resource.
-* Is there a [pseudo parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html) you can use to return the ID of the current AWS account you're using?
-:::
-
-::::::expand{header="Want to see the solution?"}
-The complete solution is available in the `vpc.yaml` file, that you can find on the `code/solutions/looping-over-collections` directory.
-
-Append the following content to the `vpc.yaml` file:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=141}
-Outputs:
- Fn::ForEach::SubnetIdsOutputs:
- - SubnetType
- - [Public, Private]
- - Fn::ForEach::SubnetNumbers:
- - SubnetNumber
- - ["1", "2"]
- - ${SubnetType}Subnet${SubnetNumber}:
- Description: !Sub 'The ID of ${SubnetType}Subnet${SubnetNumber}.'
- Export:
- Name: !Sub ${AWS::AccountId}-${SubnetType}Subnet${SubnetNumber}Id
- Value: !Ref
- Fn::Sub: ${SubnetType}Subnet${SubnetNumber}
-:::
-
-Next, update the existing `looping-over-collections-vpc` stack with the updated template containing the `Outputs` information below.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-Run the following AWS CLI command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation update-stack \
---stack-name looping-over-collections-vpc \
---template-body file://vpc.yaml \
---region us-east-1 \
---capabilities CAPABILITY_AUTO_EXPAND
-:::
-
-Wait until the stack is in the `UPDATE_COMPLETE` status by using the [wait stack-update-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-update-complete.html) AWS CLI command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-update-complete \
---region us-east-1 \
---stack-name looping-over-collections-vpc
-:::
-
-::::
-::::tab{id="local" label="Local development"}
-Steps:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Make sure you are in the **US East (N. Virginia)** region.
-1. From the left navigation panel, select the **Stacks** tab.
-1. Choose the existing `looping-over-collections-vpc` stack from the list of stacks.
-1. From the right side of the page, choose **Update Stack**.
-1. From **Prerequisite - Prepare template**, choose **Replace current template**.
-1. Under **Specify template**, select **Template source**, and choose **Upload a template file**.
-1. Select **Choose file**, and provide the `vpc.yaml` template you updated earlier. Choose **Next**.
-1. In the **Specify Stack details** page, choose **Next**.
-1. On **Configure Stack options**, leave the configuration as it is. Choose **Next**.
-1. On the **Review** page, review the contents of the page. At the bottom of the page, choose to acknowledge all the capabilities shown in the **Capabilities and transforms** section. Choose **Submit**.
-1. Refresh the stack creation page until you see the stack to be in the `UPDATE_COMPLETE` status.
-::::
-:::::
-
-When the stack update is complete, you should be able to see the outputs in the `Outputs` pane for the stack in the CloudFormation console.
-::::::
-
-### Clean up
-
-You'll now delete the resources you created as part of this lab. Use the following steps:
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-Delete the `looping-over-collections-s3-buckets` stack, by running the following AWS CLI command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---region us-east-1 \
---stack-name looping-over-collections-s3-buckets
-:::
-
-Wait until the `DELETE` operation is complete, by using the [wait stack-delete-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-delete-complete.html) AWS CLI command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---region us-east-1 \
---stack-name looping-over-collections-s3-buckets
-:::
-
-When done, repeat the steps above to delete the `looping-over-collections-vpc` stack:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
---region us-east-1 \
---stack-name looping-over-collections-vpc
-:::
-
-Wait until the `DELETE` operation is complete, by using the [wait stack-delete-complete](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/stack-delete-complete.html) AWS CLI command:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---region us-east-1 \
---stack-name looping-over-collections-vpc
-:::
-
-::::
-::::tab{id="local" label="Local development"}
-Steps:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Make sure you are in the **US East (N. Virginia)** region.
-1. From the **Stacks** page, select the `looping-over-collections-s3-buckets` stack.
-1. In the stack details pane, choose **Delete**. Select **Delete** when prompted.
-1. From the **Stacks** page, select the `looping-over-collections-vpc` stack.
-1. In the stack details pane, choose **Delete**. Select **Delete** when prompted.
-::::
-:::::
-
-### Conclusion
-
-Great work! You learned how to loop over collections using the `Fn::ForEach` intrinsic function and the `AWS::LanguageExtensions` transform. For more information, see [Fn::ForEach](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-foreach.html) in the AWS CloudFormation User Guide, and the [Exploring Fn::ForEach and Fn::FindInMap enhancements in AWS CloudFormation](https://aws.amazon.com/blogs/devops/exploring-fnforeach-and-fnfindinmap-enhancements-in-aws-cloudformation/) blog post. We welcome your contributions to RFCs and your feedback in our [cfn-language-discussion](https://github.com/aws-cloudformation/cfn-language-discussion) GitHub repository!
diff --git a/content/intermediate/templates/nested-stacks/index.ja.md b/content/intermediate/templates/nested-stacks/index.ja.md
deleted file mode 100644
index b31b75fe9..000000000
--- a/content/intermediate/templates/nested-stacks/index.ja.md
+++ /dev/null
@@ -1,594 +0,0 @@
----
-title: "ネストされたスタック"
-weight: 400
----
-
-_ラボ実施時間 : 30分程度_
-
----
-
-### 概要
-
-CloudFormation テンプレートは、このワークショップを進めることでボリュームが多くなりました。
-インフラが拡大するにつれ、それぞれのテンプレートで同じコンポーネントを宣言するパターンが出てくることがあります。
-
-同じコンポーネントを宣言するケースにおいては、共通コンポーネントを分離して、専用のテンプレートを作成することが可能です。
-具体的には、[**ネストされたスタック**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html)を用いて、様々なテンプレートを組み合わせ、1 つの統合されたスタックを作成することができます。
-
-
-例えば、Systems Manager Session Manager によるすべての EC2 インスタンスへのアクセスを有効にしたい場合があります。
-同じ IAM ロール設定をコピー & ペーストする代わりに、インスタンスの IAM ロールを含む専用テンプレートを作成できます。
-そして、[AWS::CloudFormation::Stack](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html)リソースを使用して、他のテンプレート内からそのテンプレートを参照することができます。
-
-
-### 取り上げるトピック
-
-このラボでは、以下を作成します。
-
-1. **_root_ スタック** : (第 1 レベルにある親スタックでもあります)。root スタックには、他のすべてのスタックが含まれます。
-1. **VPC スタック** : EC2 インスタンスを配置するシンプルな VPC テンプレートが含まれています。
-1. **IAM インスタンスロールスタック** : EC2 テンプレートから切り離された IAM インスタンスロールテンプレートが含まれています。
-1. **EC2 スタック** : 以前の CloudFormation テンプレートで定義した EC2 インスタンスが含まれます。
-
-> ネストされたスタックの最上位レベルと第 1 レベルの階層
-
-
-
-> インフラストラクチャの概要
-
-
-
-### ラボを開始
-
-1. `code/workspace/nested-stacks` ディレクトリに移動します。
-1. 以下のトピックを読みながら、コードをコピーします。
-
-#### 1. ネストされたスタックのリソース
-
-テンプレート内の CloudFormation スタックを参照するには、`AWS::CloudFormation::Stack` リソースを使用します。
-
-以下のような形です:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-Resources:
- NestedStackExample:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: 'Path/To/Template'
- Parameters:
- ExampleKey: ExampleValue
-:::
-
-`TemplateURL` プロパティは、ネストしたい CloudFormation テンプレートを参照するために使用されます。
-
-`Parameters` プロパティを使用すると、ネストされた CloudFormation テンプレートにパラメータを渡すことができます。
-
-#### 2. S3 バケットを準備
-
-単一のテンプレートの場合は、ローカルマシンからデプロイできますが、ネストされたスタックでは、ネストされたテンプレートを S3 バケットに保存する必要があります。
-
-最初のラボで、S3 バケットを作成する簡単な CloudFormation テンプレートを作成しました。作成したバケット名をメモします。
-
-バケット名の例: `cfn-workshop-s3-s3bucket-2cozhsniu50t`
-
-S3 バケットをお持ちでない場合は、[テンプレートとスタック](/basics/templates/template-and-stack) ラボに戻って、S3 バケットを作成します。
-
-#### 3. ネストされた VPC スタックの作成
-
-VPC テンプレートは既に作成されており、タイトルは `vpc.yaml` です。このテンプレートは、2 つのパブリックサブネット、インターネットゲートウェイ、ルートテーブルを含む VPC スタックを作成することができます。
-
-##### 1. メインテンプレートで VPC パラメータを作成
-
-`vpc.yaml` ファイルを見ると、テンプレートの **Parameters** セクションにいくつかのパラメータがあることがわかります。
-
-これらのパラメータは、ネストされたスタックに渡せるように、メインテンプレートに追加する必要があります。
-
-以下のコードを `main.yaml` テンプレートの **Parameters** セクションにコピーします。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-AvailabilityZones:
- Type: List
- Description: The list of Availability Zones to use for the subnets in the VPC. Select 2 AZs.
-
-VPCName:
- Type: String
- Description: The name of the VPC.
- Default: cfn-workshop-vpc
-
-VPCCidr:
- Type: String
- Description: The CIDR block for the VPC.
- AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
- ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
- Default: 10.0.0.0/16
-
-PublicSubnet1Cidr:
- Type: String
- Description: The CIDR block for the public subnet located in Availability Zone 1.
- AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
- ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
- Default: 10.0.0.0/24
-
-PublicSubnet2Cidr:
- Type: String
- Description: The CIDR block for the public subnet located in Availability Zone 2.
- AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
- ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
- Default: 10.0.1.0/24
-:::
-
-##### 2. メインテンプレートに VPC リソースを作成
-以下のコードでは、単一のスタンドアロンテンプレートを使用する場合と同じように、リソースにパラメータ値を渡すことができます。
-メインテンプレートのパラメータ名が VPC テンプレートのパラメータ名と一致することを確認してください。
-
-このコードをメインテンプレート (`main.yaml`) の **Resources** セクションに追加します
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-VpcStack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/vpc.yaml
- TimeoutInMinutes: 20
- Parameters:
- AvailabilityZones:
- Fn::Join:
- - ','
- - !Ref AvailabilityZones
- VPCCidr: !Ref VPCCidr
- VPCName: !Ref VPCName
- PublicSubnet1Cidr: !Ref PublicSubnet1Cidr
- PublicSubnet2Cidr: !Ref PublicSubnet2Cidr
-:::
-
-##### 3. VPC スタックを S3 にアップロード
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/nested-stacks` ディレクトリに移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. 以下のコマンドを実行して `vpc.yaml` を S3 バケットにコピーします。`bucket-name` を前のステップのバケット名に置き換えてください。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws s3 cp vpc.yaml s3://{bucket-name}
- :::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [S3 コンソール](https://console.aws.amazon.com/s3/home?region=eu-west-1) に移動し、バケットを選択します。
-1. **アップロード** ボタンをクリックし、 **ファイルを追加** をクリックします。
-1. `vpc.yaml` ファイルを選択します。
-1. **アップロード** ボタンをクリックし、ファイルをアップロードします。
-::::
-:::::
-
-##### 4. ネストされた VPC スタックをデプロイ
-
-:::alert{type="info"}
-**YAML** はインデントに敏感なマークダウン言語であることに注意してください。`cfn-lint` または CloudFormation コンソールが`Template format error: [/Resources/VpcStack] resource definition is malformed` というエラーを報告した場合、 **Parameters** と **Resources** セクションが正しくフォーマットされていることを再確認してください。インストール方法や詳細なガイダンスについては、以前の [静的解析とテスト](/basics/templates/linting-and-testing)のラボを参照してください。
-:::
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/nested-stacks` ディレクトリに移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. AWS EC2 Api を使用して VPC からアベイラビリティーゾーンのリストを取得し、出力から任意の 2 つの AZ をコピーして次のステップで使用します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 describe-availability-zones --output json --query "AvailabilityZones[*].ZoneName"
- :::
-1. AWS CLI を使用してスタックを作成します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。`ParameterValue` の **bucketName** を [S3 バケットの準備](#2.-s3)セクションでメモした値に置き換えてください。`ParameterValue` の **AZ1** と **AZ2** を前のステップでコピーした値に置き換えてください。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack --stack-name cfn-workshop-nested-stacks \
- --template-body file://main.yaml \
- --parameters ParameterKey="S3BucketName",ParameterValue="bucketName" ParameterKey="AvailabilityZones",ParameterValue=AZ1\\,AZ2 \
- --capabilities CAPABILITY_NAMED_IAM
- :::
-1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
- :::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-nested-stacks/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。最新のスタックステータスを確認するには、定期的に更新を選択する必要があります。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. コンソールで CloudFormation に移動し、 **新しいリソースを使用 (標準)** をクリックします。
-1. **テンプレートの準備** セクションで、 **テンプレート準備完了** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. `main.yaml` ファイルを選択します。
-1. **スタック名** を入力します。例えば、`cfn-workshop-nested-stack` と入力します。
-1. **AvailabilityZone** パラメータには、2 つの AZ を選択します。
-1. **S3BucketName** には、[S3 バケットを準備](#2.-s3) セクションに書き留めたバケット名を入力します。
-1. 残りのパラメータはデフォルトのままとします。
-1. **スタックオプションの設定** はデフォルトのままにして、 **次へ** をクリックします。
-1. **レビュー ** ページで一番下までスクロールし、両方の **IAM Capabilities** チェックボックスにチェックを入れます。
- 
-1. **スタックの作成** をクリックします。CloudFormation コンソールで作成中のネストスタックの進行状況を確認できます。
-1. 数分後にスタックが作成されます。`CREATE_COMPLETE` のステータスが表示されるまで、更新ボタンを数回クリックします。
-::::
-:::::
-
-#### 4. ネストされた IAM スタックの作成
-
-##### 1. IAM ロールテンプレートの準備
-
-**IAM ロール** テンプレートが既に作成されています。タイトルは `iam.yaml` です。
-このテンプレートは、[Session Manager](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager.html) が EC2 インスタンスにアクセスすることを許可する `AmazonSSMManagedInstanceCore` ポリシーを使用して IAM ロールを作成します。
-
-
-1. `iam.yaml` ファイルを開きます。
-1. 以下のコードをテンプレートの **Resources** セクションにコピーします。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-SSMIAMRole:
- Type: AWS::IAM::Role
- Properties:
- AssumeRolePolicyDocument:
- Statement:
- - Effect: Allow
- Principal:
- Service:
- - ec2.amazonaws.com
- Action:
- - sts:AssumeRole
- ManagedPolicyArns:
- - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
-
-WebServerInstanceProfile:
- Type: AWS::IAM::InstanceProfile
- Properties:
- Path: /
- Roles:
- - !Ref SSMIAMRole
-:::
-
-##### 2. メインテンプレートに IAM リソースを作成
-以下のコードを `main.yaml` テンプレートの **Resources** セクションにコピーします。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-IamStack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/iam.yaml
- TimeoutInMinutes: 10
-:::
-
-
-##### 3. IAM スタックを S3 にアップロード
-
-[VPC スタック](#3.-vpc-s3) と同様に、IAM テンプレートを S3 にアップロードします。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/nested-stacks` ディレクトリに移動します。
- :::code{language=shell showLineNumbers=true showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. 以下のコマンドを実行して `iam.yaml` を S3 バケットにコピーします。`bucket-name` を前のステップのバケット名に置き換えてください。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws s3 cp iam.yaml s3://{bucket-name}
- :::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. コンソールで S3 バケットに移動して選択します。
-1. **アップロード** ボタン -> **ファイルを追加** をクリックします。
-1. `iam.yaml` ファイルを選択します。
-1. **アップロード** ボタンをクリックしてファイルをアップロードします。
-::::
-:::::
-
-##### 4. ネストされた IAM スタックをデプロイ
-
-以前に作成したネストスタックを新しいテンプレートで更新します。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/nested-stacks` ディレクトリに移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. AWS EC2 Api を使用して VPC からアベイラビリティーゾーンのリストを取得し、出力から任意の 2 つの AZ をコピーして次のステップで使用します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 describe-availability-zones --output json --query "AvailabilityZones[*].ZoneName"
- :::
-1. AWS CLI を使用してスタックを更新します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。`ParameterValue` の **bucketName** を [S3 バケットの準備](#2.-s3)セクションでメモした値に置き換えてください。`ParameterValue` の **AZ1** と **AZ2** を前のステップでコピーした値に置き換えてください。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-nested-stacks \
- --template-body file://main.yaml \
- --parameters ParameterKey="S3BucketName",ParameterValue="bucketName" ParameterKey="AvailabilityZones",ParameterValue=AZ1\\,AZ2 \
- --capabilities CAPABILITY_NAMED_IAM
- :::
-1. `update-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-nested-stacks/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **UPDATE_COMPLETE** になっているかどうかを確認します。最新のスタックステータスを確認するには、定期的に更新を選択する必要があります。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. AWS コンソールの Cloudformation サービスに移動します。
-1. **root** スタック ( **ネストされた** タグが関連付けられていないスタック) を選択します。
-1. 右上の **更新** をクリックします。
-1. **テンプレートの準備** セクションで、 **既存のテンプレートを置き換える** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. **ファイルを選択** ボタンをクリックし、ワークショップディレクトリに移動します。
-1. `main.yaml` テンプレートファイルを選択し、 **次へ** をクリックします。
-1. ウィザードに従い、IAM Capabilities を確認し、 **送信** をクリックします。
-::::
-:::::
-
-#### 5. ネストされた EC2 スタックの作成
-
-##### 1. メインテンプレートで EC2 パラメータを作成する
-
-VPC テンプレートと同様に、`ec2.yaml` テンプレートの **Parameters** セクションを見ると、次の 3 つのパラメータがあります。
-
-* `SubnetId` - このプロパティは VPC スタックが作成されると VPC スタックから渡されます。
-* `EnvironmentType` - このプロパティにはデフォルト値があり、頻繁に変更される可能性があるので、Parameters に追加します。
-* `AmiId` - このプロパティにはデフォルト値があるため、メインテンプレートから除外してもかまいません。
-
-`main.yaml` テンプレートの **Parameters** セクションに以下のコードを追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-EnvironmentType:
- Description: 'Specify the Environment type of the stack.'
- Type: String
- Default: Test
- AllowedValues:
- - Dev
- - Test
- - Prod
- ConstraintDescription: 'Specify either Dev, Test or Prod.'
-:::
-
-##### 2. メインテンプレートに EC2 リソースを作成
-
-以下のコードを `main.yaml` テンプレートの **Resources** セクションにコピーします。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-EC2Stack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/ec2.yaml
- TimeoutInMinutes: 20
-:::
-
-##### 3. EnvironmentType を EC2 スタックに追加します
-
-テンプレートに `EnvironmentType` パラメータを追加したので、これを `EC2Stack` リソースで参照する必要があります。
-
-`main.yaml` テンプレートの EC2 スタック [6-7] 行目に、`Parameters` セクションと `EnvironmentType` を追加します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=6-7}
-EC2Stack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/ec2.yaml
- TimeoutInMinutes: 20
- Parameters:
- EnvironmentType: !Ref EnvironmentType
-:::
-
-#### 6. 別のネストされたスタックから変数を渡す
-
-CloudFormation のネストスタックを更新する前に、やるべきことが他にもいくつかあります。
-
-+ EC2 セキュリティグループを作成する VPC を指定する必要があります。VPC パラメータを指定しないと、セキュリティグループは **デフォルト VPC** に作成されます。
-
-+ EC2 インスタンスを作成するサブネットを指定する必要があります。
-
-##### 1. セキュリティグループリソースを準備
-
-1. `ec2.yaml` ファイルを開き、テンプレートの **Parameters** セクションに `VpcId` と `SubnetId` の 2 つのパラメータを作成します。
-
- :::code{language=yaml showLineNumbers=true showCopyAction=true}
- VpcId:
- Type: AWS::EC2::VPC::Id
- Description: 'The VPC ID'
-
- SubnetId:
- Type: AWS::EC2::Subnet::Id
- Description: 'The Subnet ID'
- :::
-
-1. 次に、`WebServerSecurityGroup` リソースを探します。
-1. `WebServerSecurityGroup` リソース [18] 行目に `VpcId` プロパティを追加し、 `VpcId` パラメータを参照します。セキュリティグループリソースは以下のコードのようになっているはずです。
-
- :::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=18}
- WebServerSecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Enable HTTP and HTTPS access
- SecurityGroupIngress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
- SecurityGroupEgress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
- - IpProtocol: tcp
- FromPort: 443
- ToPort: 443
- CidrIp: 0.0.0.0/0
- VpcId: !Ref VpcId
- :::
-
-##### 2. VPC テンプレートの準備
-
-あるスタックから別のスタックに変数を渡すには、その変数を渡すスタックの値を含む出力を作成する必要があります。
-
-組み込み関数 `!GetAtt` を利用すると、CloudFormation はそのスタックの値にアクセスでき、それをパラメータとして渡します。
-
-以下のコードを `vpc.yaml` テンプレートに追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-Outputs:
- VpcId:
- Value: !Ref VPC
-
- PublicSubnet1:
- Value: !Ref VPCPublicSubnet1
-
- PublicSubnet2:
- Value: !Ref VPCPublicSubnet2
-:::
-
-##### 3. VpcId と SubnetId を **EC2Stack** スタックに追加する
-
-これで、VPC スタックから値を取得して EC2 スタックに渡すことができます。
-
-`VpcId` と `SubnetId` パラメータを `main.yaml` テンプレートの EC2 スタックに追加します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=8-9}
-EC2Stack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/ec2.yaml
- TimeoutInMinutes: 20
- Parameters:
- EnvironmentType: !Ref EnvironmentType
- VpcId: !GetAtt VpcStack.Outputs.VpcId
- SubnetId: !GetAtt VpcStack.Outputs.PublicSubnet1
-:::
-
-##### 4. IAM テンプレートの準備
-
-`iam.yaml` を開いて、以下のコードを追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-Outputs:
- WebServerInstanceProfile:
- Value: !Ref WebServerInstanceProfile
-:::
-
-##### 5. EC2 テンプレートの準備
-
-1. `ec2.yaml` を開きます。
-1. テンプレートの **Parameters** セクションに `WebServerInstanceProfile` パラメータを作成します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-WebServerInstanceProfile:
- Type: String
- Description: 'Instance profile resource ID'
-:::
-
-##### 6. WebServerInstanceProfile を **EC2Stack** スタックに追加
-
-`webServerInstanceProfile` パラメータを `main.yaml` テンプレートの EC2 スタック [10] 行目に追加します。
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=10}
-EC2Stack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/ec2.yaml
- TimeoutInMinutes: 20
- Parameters:
- EnvironmentType: !Ref EnvironmentType
- VpcId: !GetAtt VpcStack.Outputs.VpcId
- SubnetId: !GetAtt VpcStack.Outputs.PublicSubnet1
- WebServerInstanceProfile: !GetAtt IamStack.Outputs.WebServerInstanceProfile
-:::
-
-##### 7. メインテンプレートの `WebsiteURL` を出力する
-
-`WebsiteURL` を `main.yaml` テンプレートの `Outputs` セクションに追加します。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-Outputs:
- WebsiteURL:
- Value: !GetAtt EC2Stack.Outputs.WebsiteURL
-:::
-
-##### 8. EC2 スタックを S3 にアップロード
-更新されたネストスタックをデプロイする前に、親テンプレート `main.yaml` が参照する S3 バケットのテンプレートを更新する必要があります。
-
-前のステップの [VPC スタックのアップロード](#3.-vpc-s3) と同様に、`vpc.yaml`、`ec2.yaml`、 `iam.yaml` テンプレートを S3 バケットにアップロードします。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/nested-stacks` ディレクトリに移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. 以下のコマンドを実行して、`iam.yaml`、`vpc.yaml`、`ec2.yaml` を S3 バケットにコピーします。`bucket-name` を前のステップのバケット名に置き換えてください。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws s3 cp iam.yaml s3://{bucket-name}
-aws s3 cp vpc.yaml s3://{bucket-name}
-aws s3 cp ec2.yaml s3://{bucket-name}
- :::
-::::
-::::tab{id="local" label="ローカル開発"}
-1. コンソールで S3 バケットに移動して選択します。
-1. **アップロード** ボタン -> **ファイルの追加** をクリックします。
-1. `vpc.yaml`、`iam.yaml`、`ec2.yaml` ファイルを選択します。
-1. **アップロード** ボタンをクリックしてファイルをアップロードします。
-::::
-:::::
-
-##### 9. ネストされた EC2 スタックをデプロイ
-
-以前に作成したネストスタックを新しいテンプレートで更新します。
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/nested-stacks` ディレクトリに移動します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. AWS EC2 Api を使用して VPC からアベイラビリティーゾーンのリストを取得し、出力から任意の 2 つの AZ をコピーして次のステップで使用します。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 describe-availability-zones --output json --query "AvailabilityZones[*].ZoneName"
- :::
-1. AWS CLI を使用してスタックを更新します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。`ParameterValue` の **bucketName** を [S3 バケットの準備](#2.-s3)セクションでメモした値に置き換えてください。`ParameterValue` の **AZ1** と **AZ2** を前のステップでコピーした値に置き換えてください。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-nested-stacks \
- --template-body file://main.yaml \
- --parameters ParameterKey="S3BucketName",ParameterValue="bucketName" ParameterKey="AvailabilityZones",ParameterValue=AZ1\\,AZ2 \
- --capabilities CAPABILITY_NAMED_IAM
- :::
-1. `update-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
- :::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-nested-stacks/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **UPDATE_COMPLETE** になっているかどうかを確認します。最新のスタックステータスを確認するには、定期的に更新を選択する必要があります。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. AWS コンソールの Cloudformation サービスに移動します。
-1. **root** スタック ( **ネストされた** タグが関連付けられていないスタック) を選択します。
-1. 右上の **更新** をクリックします。
-1. **テンプレートの準備** セクションで、 **既存のテンプレートを置き換える** を選択します。
-1. **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。
-1. **ファイルを選択** ボタンをクリックし、ワークショップディレクトリに移動します。
-1. `main.yaml` テンプレートファイルを選択し、 **次へ** をクリックします。
-1. ウィザードに従い、IAM Capabilities を確認し、 **送信** をクリックします。
-::::
-:::::
-
-#### 7.デプロイメントのテスト
-
-##### 1. アプリケーションが正常にデプロイされたことを確認
-
-プライベートモードで新しいブラウザウィンドウを開き、`WebsiteURL` を入力します。
-
-`WebsiteURL` は、CloudFormation コンソールのメインスタックの **出力** タブから取得できます。
-
-
-
-ブラウザウィンドウに、以下の図のようなインスタンスメタデータが表示されます。
-
-
-
-##### 2. SSM セッションマネージャーを使用してインスタンスにログイン
-
-**[セッションマネージャ](https://console.aws.amazon.com/systems-manager)** 経由でインスタンスにログインできることを確認します。インスタンスがデプロイされているのと同じリージョン、たとえば`米国東部(バージニア北部) us-east-1` を選択します。
-### クリーンアップ
-
-作成したリソースをクリーンアップするには、次の手順に従います。
-
-1. **[CloudFormation コンソール](https://console.aws.amazon.com/cloudformation)** で、このラボで作成した **root** スタックを選択します。具体的には、`cfn-workshop-nested-stacks` を選択します。
-1. **root** スタックは、すべての **子** スタックの削除を自動的に処理します。
-1. 右上の **削除** をクリックします。
-1. ポップアップウィンドウで、 **削除** をクリックします。
-1. **DELETE_COMPLETE** のステータスが表示されるまで、 **更新** ボタンを数回クリックします。
-
----
-### まとめ
-
-ネストされたスタックを使用すると、CloudFormation テンプレートを作成できます。これにより、大きなテンプレートを、再利用可能な小さなテンプレートに分解することができます。
-また、1 つのテンプレートのリソース制限を回避するのにも役立ちます。ネストされたスタックのコンポーネントは、他の CloudFormation リソースと同様にテンプレートに定義することができます。
diff --git a/content/intermediate/templates/nested-stacks/index.md b/content/intermediate/templates/nested-stacks/index.md
deleted file mode 100644
index 639b4455b..000000000
--- a/content/intermediate/templates/nested-stacks/index.md
+++ /dev/null
@@ -1,602 +0,0 @@
----
-title: "Nested stacks"
-weight: 400
----
-
-_Lab Duration: ~30 minutes_
-
----
-
-### Overview
-
-Your CloudFormation template has grown considerably over the course of this workshop. As your infrastructure grows, common
-patterns can emerge in which you declare the same components in each of your templates.
-
-You can separate out these common components and create dedicated templates for them. That way, you can mix and match
-different templates but use **[nested stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html)**
-to create a single, unified stack.
-
-For example, you may wish to enable Systems Manager Session Manager access to every EC2 Instance. Instead of copying and
-pasting the same IAM role configuration, you can create a dedicated template containing the IAM role for the instance.
-Then, you just use the **[AWS::CloudFormation::Stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html)**
-resource to reference that template from within other templates.
-
-### Topics Covered
-
-In this lab, you will build:
-
-1. **The _root_ stack** (which is also a parent stack for the first level stacks). This root stack will contain all the other stacks.
-1. **The VPC stack**. This contains a simple VPC template which the EC2 instance will be placed into.
-1. **The IAM instance role stack**. This contains the IAM instance role template decoupled form your EC2 template.
-1. **The EC2 stack**. This contains the EC2 instance you have defined in your previous CloudFormation template.
-
-> Top level and first level hierarchy of nested stacks.
-
-
-
-> The following diagram represents high level overview of the infrastructure:
-
-
-
-### Start Lab
-
-1. Go to the `code/workspace/nested-stacks`
-1. Copy the code as you go through the topics below.
-
-#### 1. Nested Stack Resource
-
-To reference a CloudFormation stack in your template, use the `AWS::CloudFormation::Stack` resource.
-
-It looks like this:
-
-:::code{language=yaml showLineNumbers=false showCopyAction=false}
-Resources:
- NestedStackExample:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: 'Path/To/Template'
- Parameters:
- ExampleKey: ExampleValue
-:::
-
-The `TemplateURL` property is used to reference the CloudFormation template that you wish to nest.
-
-The `Parameters` property allows you to pass parameters to your nested CloudFormation template.
-
-#### 2. Prepare S3 bucket
-
-Whilst single templates can be deployed from your local machine, Nested Stacks require that the nested templates are stored in an S3 bucket.
-
-In the very first lab, you have created simple CloudFormation template which created S3 bucket. Please make a note of the bucket name.
-
-For example:
-
-Bucket name: `cfn-workshop-s3-s3bucket-2cozhsniu50t`
-
-If you don't have S3 bucket, please go back to [Template and stack](/basics/templates/template-and-stack) lab and create one.
-
-#### 3. Create VPC Nested Stack
-
-The VPC template has been created for you. It is titled `vpc.yaml`. This template will create VPC stack with 2 Public Subnets, Internet Gateway, and Route tables.
-
-##### 1. Create VPC parameters in the main template
-
-If you look in the `vpc.yaml` file, you will notice that there are some parameters in the **Parameters** section of the template.
-
-These parameters need to be added to the main template so that they can be passed to the nested stack.
-
-Copy the code below to the **Parameters** section of the `main.yaml` template.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-AvailabilityZones:
- Type: List
- Description: The list of Availability Zones to use for the subnets in the VPC. Select 2 AZs.
-
-VPCName:
- Type: String
- Description: The name of the VPC.
- Default: cfn-workshop-vpc
-
-VPCCidr:
- Type: String
- Description: The CIDR block for the VPC.
- AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
- ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
- Default: 10.0.0.0/16
-
-PublicSubnet1Cidr:
- Type: String
- Description: The CIDR block for the public subnet located in Availability Zone 1.
- AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
- ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
- Default: 10.0.0.0/24
-
-PublicSubnet2Cidr:
- Type: String
- Description: The CIDR block for the public subnet located in Availability Zone 2.
- AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
- ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
- Default: 10.0.1.0/24
-:::
-
-##### 2. Create VPC resource in the main template
-In the code below, note that passing parameter values to resources works the same as if using a single standalone template.
-Make sure that parameter name in the main template matches parameter name in the VPC template.
-
-Add this code in the **Resources** section of the main template (`main.yaml`)
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-VpcStack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/vpc.yaml
- TimeoutInMinutes: 20
- Parameters:
- AvailabilityZones:
- Fn::Join:
- - ','
- - !Ref AvailabilityZones
- VPCCidr: !Ref VPCCidr
- VPCName: !Ref VPCName
- PublicSubnet1Cidr: !Ref PublicSubnet1Cidr
- PublicSubnet2Cidr: !Ref PublicSubnet2Cidr
-:::
-
-##### 3. Upload the VPC stack to S3
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/nested-stacks`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. Run the below command to copy the `vpc.yaml` to S3 bucket. Replace the `bucket-name` with the bucket name from previous step.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws s3 cp vpc.yaml s3://{bucket-name}
- :::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [S3 console](https://console.aws.amazon.com/s3/home) and select your bucket.
-1. Click on **Upload** button, **Add files**.
-1. Locate the `vpc.yaml` file and select it.
-1. Click **Upload** button to upload the file.
-::::
-:::::
-
-##### 4. Deploy VPC Nested Stack
-
-:::alert{type="info"}
-Please note **YAML** is indention sensitive mark down language. If `cfn-lint` or CloudFormation console reports errors,
-such as `Template format error: [/Resources/VpcStack] resource definition is malformed`, \
-please double-check **Parameters** and **Resources** sections are correctly formatted.\
-See the earlier [Linting and Testing](/basics/templates/linting-and-testing) lab to install or for more guidance.
-:::
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/nested-stacks`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. Use AWS EC2 Api to get list of availability zones from your vpc and copy any 2 AZ's from the output to use them in next step:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 describe-availability-zones --output json --query "AvailabilityZones[*].ZoneName"
- :::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you. Replace the `ParameterValue` **bucketName** with the value you have written down in [Prepare S3 bucket](#2.-prepare-s3-bucket) section. Replace the `ParameterValue` **AZ1** and **AZ2** which you copied in previous step.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack --stack-name cfn-workshop-nested-stacks \
- --template-body file://main.yaml \
- --parameters ParameterKey="S3BucketName",ParameterValue="bucketName" ParameterKey="AvailabilityZones",ParameterValue=AZ1\\,AZ2 \
- --capabilities CAPABILITY_NAMED_IAM
- :::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-nested-stacks/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to CloudFormation in the console and click **Create stack With new resources (standard)**.
-1. In **Prepare template** select **Template is ready**.
-1. In **Template source** select **Upload a template file**.
-1. Choose a file `main.yaml`.
-1. Enter a **Stack name**. For example, `cfn-workshop-nested-stacks`.
-1. For the **AvailabilityZones** parameter, select 2 AZs.
-1. For the **S3BucketName** provide the name of the bucket you have written down in [Prepare S3 bucket](#2.-prepare-s3-bucket) section.
-1. You can leave rest of the parameters default and choose **Next**.
-1. You can leave **Configure stack options** default, click **Next**.
-1. On the **Review ** page, scroll down to the bottom and tick both **IAM Capabilities** check boxes.
- 
-1. Click on **Submit**. You can view the progress of Nested stacks being created in CloudFormation console.
-1. In a few minutes, stacks will be created. Hit the refresh button a few times until you see in the status CREATE_COMPLETE.
-::::
-:::::
-
-#### 4. Create IAM Nested Stack
-
-##### 1. Prepare IAM role template
-
-The **IAM role** template has been created for you. It is titled `iam.yaml`. This template will create IAM role with
-`AmazonSSMManagedInstanceCore` policy which will allow [Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html)
-to access EC2 instance.
-
-1. Open the `iam.yaml` file.
-1. Copy the code below to the **Resources** section of the template.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-SSMIAMRole:
- Type: AWS::IAM::Role
- Properties:
- AssumeRolePolicyDocument:
- Statement:
- - Effect: Allow
- Principal:
- Service:
- - ec2.amazonaws.com
- Action:
- - sts:AssumeRole
- ManagedPolicyArns:
- - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
-
-WebServerInstanceProfile:
- Type: AWS::IAM::InstanceProfile
- Properties:
- Path: /
- Roles:
- - !Ref SSMIAMRole
-:::
-
-##### 2. Create IAM resource in the main template
-Copy the code below to the **Resources** section of the `main.yaml` template.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-IamStack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/iam.yaml
- TimeoutInMinutes: 10
-:::
-
-##### 3. Upload the IAM stack to S3
-
-Similarly to the [VPC stack](#3.-upload-the-vpc-stack-to-s3), upload the IAM template to the S3.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/nested-stacks`:
- :::code{language=shell showLineNumbers=true showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. Run the below command to copy the `iam.yaml` to S3 bucket. Replace the `bucket-name` with the bucket name from previous step.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws s3 cp iam.yaml s3://{bucket-name}
- :::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [S3 console](https://console.aws.amazon.com/s3/home) and select your bucket.
-1. Click on **Upload** button, **Add files**.
-1. Locate the `iam.yaml` file and select it.
-1. Click **Upload** button to upload the file.
-::::
-:::::
-
-##### 4. Deploy IAM Nested Stack
-
-Update the previously created nested stack with a new template.
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/nested-stacks`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. Use AWS EC2 Api to get list of availability zones from your vpc and copy any 2 AZ's from the output to use them in next step:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 describe-availability-zones --output json --query "AvailabilityZones[*].ZoneName"
- :::
-1. Use the AWS CLI to update the stack. The required parameter `--template-body` have been pre-filled for you. Replace the `ParameterValue` **bucketName** with the value you have written down in [Prepare S3 bucket](#2.-prepare-s3-bucket) section. Replace the `ParameterValue` **AZ1** and **AZ2** which you copied in previous step.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-nested-stacks \
- --template-body file://main.yaml \
- --parameters ParameterKey="S3BucketName",ParameterValue="bucketName" ParameterKey="AvailabilityZones",ParameterValue=AZ1\\,AZ2 \
- --capabilities CAPABILITY_NAMED_IAM
- :::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-nested-stacks/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to Cloudformation service in the AWS console.
-1. Select the **root** stack (it is the one without the **nested** tag associated).
-1. In the top right corner click on **Update**.
-1. In **Prepare template**, choose **Replace current template**.
-1. In **Template source**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the `main.yaml` template file and click **Next**.
-1. Follow the wizard, acknowledge IAM capabilities and click on **Submit**.
-::::
-:::::
-
-#### 5. Create EC2 Nested Stack
-
-##### 1. Create EC2 parameters in the main template
-
-Similarly to the VPC template, if you look into **Parameters** section of the `ec2.yaml` template there are three parameters:
-
-* `SubnetId` - this property will be passed from VPC stack once the VPC stack is created.
-* `EnvironmentType` - this property has a default value and is likely to often change, so let's add this one.
-* `AmiID` - this property has default value, it can be left out from the main template.
-
-Add the code below to the **Parameters** section of the `main.yaml` template:
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-EnvironmentType:
- Description: 'Specify the Environment type of the stack.'
- Type: String
- Default: Test
- AllowedValues:
- - Dev
- - Test
- - Prod
- ConstraintDescription: 'Specify either Dev, Test or Prod.'
-:::
-
-##### 2. Create EC2 resource in the main template
-
-Copy the code below to the **Resources** section of the `main.yaml` template.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-EC2Stack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/ec2.yaml
- TimeoutInMinutes: 20
-:::
-
-##### 3. Add EnvironmentType to the EC2 stack
-
-As you have added `EnvironmentType` parameter to the template, you need to reference this in `EC2Stack` resource.
-
-Add the `EnvironmentType` to the `Parameters` section of the EC2 stack in the `main.yaml` template, lines [6-7]:
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=6-7}
-EC2Stack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/ec2.yaml
- TimeoutInMinutes: 20
- Parameters:
- EnvironmentType: !Ref EnvironmentType
-:::
-
-#### 6. Pass variable from another nested stack
-
-Before you update your CloudFormation nested stack, there are a couple more things to do.
-
-+ You need to specify which VPC to create the EC2 security group in. Without specifying the VPC parameter, the security group would be created in the **Default VPC**.
-
-+ You need to specify which subnet to create the EC2 instance in.
-
-##### 1. Prepare the security group resource
-
-1. Open up `ec2.yaml` file and create two parameters, `VpcId` and `SubnetId` in **Parameters** section of the template.
-
- :::code{language=yaml showLineNumbers=true showCopyAction=true}
- VpcId:
- Type: AWS::EC2::VPC::Id
- Description: 'The VPC ID'
-
- SubnetId:
- Type: AWS::EC2::Subnet::Id
- Description: 'The Subnet ID'
- :::
-
-1. Next, locate the `WebServerSecurityGroup` resource.
-1. Add `VpcId` property and reference `VpcId` parameter in the `WebServerSecurityGroup` resource, line [18]. Your security group resource should look like the code below.
- :::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=18}
- WebServerSecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Enable HTTP and HTTPS access
- SecurityGroupIngress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
- SecurityGroupEgress:
- - IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
- - IpProtocol: tcp
- FromPort: 443
- ToPort: 443
- CidrIp: 0.0.0.0/0
- VpcId: !Ref VpcId
- :::
-
-##### 2. Prepare the VPC template
-
-To pass the variable from one stack to another, you need to create an output containing the value in the stack that will be passing it on.
-
-Using the intrinsic function `!GetAtt`, CloudFormation can access the value from that stack and will pass it on as a parameter.
-
-Add the code below to the `vpc.yaml` template.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-Outputs:
- VpcId:
- Value: !Ref VPC
-
- PublicSubnet1:
- Value: !Ref VPCPublicSubnet1
-
- PublicSubnet2:
- Value: !Ref VPCPublicSubnet2
-:::
-
-##### 3. Add VpcId and SubnetId to **EC2Stack** stack
-
-Now, you can grab the values from VPC stack and pass them to EC2 stack.
-
-Add `VpcId` and `SubnetId` parameters to the EC2 stack in the `main.yaml` template.
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=8-9}
-EC2Stack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/ec2.yaml
- TimeoutInMinutes: 20
- Parameters:
- EnvironmentType: !Ref EnvironmentType
- VpcId: !GetAtt VpcStack.Outputs.VpcId
- SubnetId: !GetAtt VpcStack.Outputs.PublicSubnet1
-:::
-
-##### 4. Prepare the IAM template
-
-Open up `iam.yaml` and add the code below.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-Outputs:
- WebServerInstanceProfile:
- Value: !Ref WebServerInstanceProfile
-:::
-
-##### 5. Prepare the EC2 template
-
-1. Open up `ec2.yaml`
-1. Create the parameter `WebServerInstanceProfile` in the **Parameters** section of the template.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-WebServerInstanceProfile:
- Type: String
- Description: 'Instance profile resource ID'
-:::
-
-##### 6. Add WebServerInstanceProfile to **EC2Stack** stack
-
-Add the `WebServerInstanceProfile` parameter to the EC2 stack in the `main.yaml` template, line[10].
-:::code{language=yaml showLineNumbers=true showCopyAction=true highlightLines=10}
-EC2Stack:
- Type: AWS::CloudFormation::Stack
- Properties:
- TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com/ec2.yaml
- TimeoutInMinutes: 20
- Parameters:
- EnvironmentType: !Ref EnvironmentType
- VpcId: !GetAtt VpcStack.Outputs.VpcId
- SubnetId: !GetAtt VpcStack.Outputs.PublicSubnet1
- WebServerInstanceProfile: !GetAtt IamStack.Outputs.WebServerInstanceProfile
-:::
-
-##### 7. Output the `WebsiteURL` in the main template
-
-Add the `WebsiteURL` to the `Outputs` section of the `main.yaml` template.
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true}
-Outputs:
- WebsiteURL:
- Value: !GetAtt EC2Stack.Outputs.WebsiteURL
-:::
-
-##### 8. Upload the EC2 stack to S3
-Before you can deploy the updated nested stack, you must update the templates in your S3 bucket that are referenced by the parent template, `main.yaml`.
-
-Similar to the [uploading the VPC stack](#3.-upload-the-vpc-stack-to-s3) in a previous step, upload the `vpc.yaml`, `ec2.yaml`
-and `iam.yaml` templates to your S3 bucket.
-
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/nested-stacks`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. Run the below command to copy the `iam.yaml`, `vpc.yaml` and `ec2.yaml` to S3 bucket. Replace the `bucket-name` with the bucket name from previous step.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws s3 cp iam.yaml s3://{bucket-name}
-aws s3 cp vpc.yaml s3://{bucket-name}
-aws s3 cp ec2.yaml s3://{bucket-name}
- :::
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to your S3 bucket in the console and select it.
-1. Click on **Upload** button -> **Add files**.
-1. Locate the `vpc.yaml`, `iam.yaml` and `ec2.yaml` files and select them.
-1. Click **Upload** button to upload the file.
-::::
-:::::
-
-##### 9. Deploy EC2 Nested Stack
-
-Update the previously created nested stack with a new template.
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/nested-stacks`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/nested-stacks
- :::
-1. Use AWS EC2 Api to get list of availability zones from your vpc and copy any 2 AZ's from the output to use them in next step:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 describe-availability-zones --output json --query "AvailabilityZones[*].ZoneName"
- :::
-1. Use the AWS CLI to update the stack. The required parameter `--template-body` have been pre-filled for you. Replace the `ParameterValue` **bucketName** with the value you have written down in [Prepare S3 bucket](#2.-prepare-s3-bucket) section. Replace the `ParameterValue` **AZ1** and **AZ2** which you copied in previous step.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation update-stack --stack-name cfn-workshop-nested-stacks \
- --template-body file://main.yaml \
- --parameters ParameterKey="S3BucketName",ParameterValue="bucketName" ParameterKey="AvailabilityZones",ParameterValue=AZ1\\,AZ2 \
- --capabilities CAPABILITY_NAMED_IAM
- :::
-1. If the `update-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=json showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-nested-stacks/739fafa0-e4d7-11ed-a000-12d9009553ff"
- :::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **UPDATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to Cloudformation service in the AWS console.
-1. Select the **root** stack (it is the one without the **nested** tag associated).
-1. In the top right corner click on **Update**.
-1. In **Prepare template**, choose **Replace current template**.
-1. In **Template source**, choose **Upload a template file**.
-1. Click on **Choose file** button and navigate to your workshop directory.
-1. Select the `main.yaml` template file and click **Next**.
-1. Follow the wizard, acknowledge IAM capabilities and click on **Submit**.
-::::
-:::::
-
-#### 7. Test the deployment
-
-##### 1. Verify that application has been deployed successfully
-
-Open a new browser window in private mode and enter the `WebsiteURL`.
-
-You can get the `WebsiteURL` from the **Outputs** tab of the main stack in CloudFormation console.
-
-
-
-In the browser window, you should see some instance metadata, similar to the picture below.
-
-
-
-##### 2. Log in to instance using SSM Session Manager
-
-Verify that you can log in to the instance via **[Session Manager](https://console.aws.amazon.com/systems-manager)**. Select the same region as the instance is deployed in, for example `US East (N. Virginia) us-east-1`.
-
-### Clean up
-
-Follow these steps to clean up created resources:
-
-1. In the **[CloudFormation console](https://console.aws.amazon.com/cloudformation)**, select the **root** stack you have created in this lab. For example `cfn-workshop-nested-stacks`.
-1. The **root** stack will handle the deletion of all the **children** stacks for you.
-1. In the top right corner, click on **Delete**.
-1. In the pop-up window click on **Delete**.
-1. You can click the **refresh** button a few times until you see in the status **DELETE_COMPLETE**.
-
----
-### Conclusion
-
-Nested stacks allow you to compose CloudFormation templates. This allows you to decompose large templates into smaller
-reusable components. It also assists in avoiding resource limits of a single template. Nested Stack components are defined
-in a template like any other CloudFormation resource.
diff --git a/content/intermediate/templates/package-and-deploy/index.ja.md b/content/intermediate/templates/package-and-deploy/index.ja.md
deleted file mode 100644
index 2c0b1a950..000000000
--- a/content/intermediate/templates/package-and-deploy/index.ja.md
+++ /dev/null
@@ -1,341 +0,0 @@
----
-title: "パッケージ化とデプロイ"
-weight: 600
----
-
-_ラボ実施時間 : 15分程度_
-
----
-
-### 概要
-
-このワークショップの [基本](/basics)で、CloudFormation コンソールを介して単一の YAML テンプレートをデプロイしました。
-基本編は、非常に簡単な作業でしたが、CloudFormation テンプレートが他のファイルまたはアーティファクトを参照する場合もあります。
-
-例えば、Lambda のソースコードや ZIP ファイル、またはネストされた CloudFormation テンプレートファイルは、アーティファクトです。
-[ネストされたスタックのラボ](/intermediate/templates/nested-stacks)で学んだように、 メインの CloudFormation テンプレートをデプロイする前に、これらのファイルが S3 で利用可能になっている必要があります。
-
-より複雑なスタックのデプロイは多段階のプロセスが必要ですが、AWS CLI には、他のファイルを参照して CloudFormation テンプレートをデプロイする方法が用意されています。
-
-このセクションでは、AWS CLI で CloudFormation テンプレートをパッケージ化、検証、デプロイするために使用する 3 つの主要なコマンドについて説明します。
-
-
-
-### 取り上げるトピック
-
-このラボを修了すると、次のことができるようになります。
-* テンプレートをパッケージ化する必要があるケースを確認
-* `aws cloudformation package` コマンドを使ってテンプレートをパッケージ化
-* `aws cloudformation validate-template` コマンドを使用して CloudFormation テンプレートを検証
-* `aws cloudformation deploy` コマンドを使用してテンプレートをデプロイ
-
-### ラボを開始
-
-`code/workspace/package-and-deploy` ディレクトリにあるサンプルプロジェクトを見てください。
-
-プロジェクトの構成は以下のとおりです。
-
-* インフラストラクチャをスピンアップするための CloudFormation テンプレート
-* 1 つの Lambda 関数
-* 関数の依存関係をインストールするための要件ファイル
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-cfn101-workshop/code/workspace/package-and-deploy
-├── infrastructure.template
-└── lambda/
- ├── lambda_function.py
- └── requirements.txt
-:::
-
-#### CloudFormation テンプレート内のローカルファイルを参照
-
-従来は、すべての Lambda ソースを圧縮して S3 にアップロードし、次にテンプレートで S3 ロケーションを参照する必要がありました。この作業はかなり面倒です。
-
-ただし、[aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) を使えば、ローカルファイルを直接参照できます。直接参照の方が、S3 を参照する従来の方法と比較し利用が簡単です。
-
-`infrastructure.template` スニペットを見ると、`Code` プロパティのローカルディレクトリの [9] 行目への参照が分かります。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=false lineNumberStart=19}
-PythonFunction:
- Type: AWS::Lambda::Function
- Properties:
- FunctionName: cfn-workshop-python-function
- Description: Python Function to return specific TimeZone time
- Runtime: python3.12
- Role: !GetAtt LambdaBasicExecutionRole.Arn
- Handler: lambda_function.handler
- Code: lambda/ # <<< This is a local directory
-:::
-
-#### アーティファクトをパッケージ化してアップロード
-
-`aws cloudformation package` は以下のアクションを実行します。
-
-1. ローカルファイルを ZIP で圧縮します。
-1. 指定された S3 バケットにアップロードします。
-1. ローカルパスが S3 URI に置き換えられた新しいテンプレートを生成します。
-
-##### 1. S3 バケットの作成
-
-一番最初に、CloudFormation テンプレートをデプロイする AWS リージョンを決定します。Lambda がパッケージ化されたアーティファクトにアクセスできるようにするには、S3 バケットが Lambda と同じリージョンにある必要があります。
-
-::alert[`s3://` の後のバケット名は必ず一意の名前に置き換えてください!]{type="info"}
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3 mb s3://example-bucket-name --region us-east-1
-:::
-
-##### 2. インストール機能の依存関係
-
-私たちの関数は外部ライブラリ [pytz](https://pypi.org/project/pytz/) に依存しているため、ローカルにインストールする必要があります。
-関数のパッケージに含むために、[pip](https://pypi.org/project/pip/) でローカルフォルダーにインストールする必要があります。
-
-`code/workspace/package-and-deploy` ディレクトリ内から以下を実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install pytz --target lambda
-:::
-
-`python 3` がお使いの場合は、上記のコマンドで `pip` の代わりに `pip3` を使う必要があるかもしれません。
-
-`lambda/` フォルダの中に `pytz` パッケージがあるはずです。
-
-##### 3. `package` コマンドの実行
-
-`code/workspace/package-and-deploy` ディレクトリ内から以下を実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation package \
---template-file infrastructure.template \
---s3-bucket example-bucket-name \
---s3-prefix cfn-workshop-package-deploy \
---output-template-file infrastructure-packaged.template
-:::
-
-上記のコマンドで使った個々の `package` オプションを詳しく見てみましょう。
-
-* `--template-file` - これは CloudFormation テンプレートが置かれているパス
-* `--s3-bucket` - アーティファクトがアップロードされる S3 バケットの名前
-* `--s3-prefix` - プレフィックス名は S3 バケットのパス名 (フォルダ名)
-* `—output-template-file` - 出力される AWS CloudFormation テンプレートの書き込み先ファイルパス
-
-##### 4. パッケージファイルを確認する
-
-新しく生成されたファイル `infrastructure-packaged.template` を見てみましょう。
-
-`Code` プロパティが [12-14] 行目の `S3Bucket` と `S3Key` の 2 つの新しい属性で更新されていることが分かります。
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=16 highlightLines=12-14}
-PythonFunction:
- Type: AWS::Lambda::Function
- Properties:
- FunctionName: cfn-workshop-python-function
- Description: Python Function to return specific TimeZone time
- Runtime: python3.12
- Role:
- Fn::GetAtt:
- - LambdaBasicExecutionRole
- - Arn
- Handler: lambda_function.handler
- Code:
- S3Bucket: example-bucket-name
- S3Key: cfn-workshop-package-deploy/1234567890
-:::
-
-アップロードされたファイルの内容も見てみましょう。上記のリストから、ダウンロードするバケットとオブジェクト名が判明しています。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3 cp s3://example-bucket-name/cfn-workshop-package-deploy/1234567890 .
-:::
-
-`package` はファイルを ZIP 形式で圧縮することがわかっているので `.zip` 拡張子がなくても `unzip` できます。
-
-:::::tabs{variant="container"}
-::::tab{id="shell" label="Unix/Linux"}
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-unzip -l ce6c47b6c84d94bd207cea18e7d93458
-
-Archive: ce6c47b6c84d94bd207cea18e7d93458
- Length Date Time Name
---------- ---------- ----- ----
- 12 02-12-2020 17:21 requirements.txt
- 455 02-12-2020 17:18 lambda_function.py
- 4745 02-13-2020 14:36 pytz/tzfile.py
-:::
-::::
-::::tab{id="powershell" label="Powershell"}
-:::code{language=powershell showLineNumbers=false showCopyAction=false}
-rename-item ce6c47b6c84d94bd207cea18e7d93458 packagedLambda.zip
-
-Expand-Archive -LiteralPath packagedLambda.zip -DestinationPath packagedLambda
-
-ls packagedLambda
-
-Directory: C:\Users\username\cfn101-workshop\code\workspace\package-and-deploy\tmp
-Mode LastWriteTime Length Name
----- ------------- ------ ----
-d----- 10/29/2021 4:25 PM pytz
-d----- 10/29/2021 4:25 PM pytz-2021.3.dist-info
--a---- 10/29/2021 11:19 AM 475 lambda_function.py
--a---- 10/29/2021 11:19 AM 14 requirements.txt
-:::
-::::
-:::::
-
-### テンプレートの検証
-
-CloudFormation テンプレートのデプロイは、テンプレートの構文エラーが原因で失敗することがあります。
-
-[`aws cloudformation validate-template`](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/validate-template.html) で CloudFormation テンプレートをチェックして、有効な JSON または YAML であることを確認します。これは開発時間を短縮するのに役立ちます。
-
-パッケージ化されたテンプレートを検証しましょう。`code/workspace/package-and-deploy` ディレクトリ内で以下を実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation validate-template \
- --template-body file://infrastructure-packaged.template
-:::
-
-成功すると、CloudFormation はパラメータ、テンプレートの説明、機能のリストを含むレスポンスを送信します。
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-{
- "Parameters": [],
- "Description": "AWS CloudFormation workshop - Package and deploy.",
- "Capabilities": [
- "CAPABILITY_IAM"
- ],
- "CapabilitiesReason": "The following resource(s) require capabilities: [AWS::IAM::Role]"
-}
-:::
-
-### 「パッケージ化された」テンプレートのデプロイ
-
-[`aws cloudformation deploy`](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy/index.html) コマンドは、CLI を使用して CloudFormation テンプレートをデプロイするために使用されます。
-
-パッケージ化されたテンプレートをデプロイしましょう。
-
-`code/workspace/package-and-deploy` ディレクトリ内で以下を実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation deploy \
---template-file infrastructure-packaged.template \
---stack-name cfn-workshop-package-deploy-lambda \
---region eu-west-1 \
---capabilities CAPABILITY_IAM
-:::
-
-::alert[S3 のアーティファクトを参照するパッケージテンプレート `infrastructure-packaged.template` を利用した点に注意してください。ローカルパスを持つオリジナルのものではありません!]{type="info"}
-
-`--parameter-overrides` オプションを設定してテンプレート内のパラメータを指定することもできます。
-`'key=value'` のペアを含む文字列や、[提供された json ファイル](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-usage-parameters.html#cli-usage-parameters-json) などを用いて指定します。
-
-##### Capabilities
-
-コンソールを使用する際に、このテンプレートをデプロイするとリソースが作成される可能性があることを認識する必要があります。
-アカウントの権限に影響する可能性があり、意図せずに誤って権限を変更しないようにするためです。
-
-CLI を使用する際には、このスタックによって IAM の権限に影響するリソースが作成される可能性があることも確認する必要があります。
-そのためには、前の例で示したように、`--capabilities` フラグを使います。capabilities については、
-[`aws cloudformation deploy` のドキュメント](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy/index.html)をご参照ください。
-
-#### Lambda のテスト
-
-Lambda 関数をテストするには、[aws lambda invoke](https://docs.aws.amazon.com/cli/latest/reference/lambda/invoke.html) コマンドを使用します。
-
-Lambda 関数は、現在の UTC の日付と時刻を取得します。次に、UTC 時刻をペイロードオプションで指定されたタイムゾーンに変換します。
-
-ターミナルから以下を実行します。
-
-:::::tabs{variant="container"}
-::::tab{id="sh" label="Unix/Linux"}
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws lambda invoke \
---function-name cfn-workshop-python-function \
---payload "{\"time_zone\": \"Asia/Tokyo\"}" \
---cli-binary-format raw-in-base64-out \
-response.json
-:::
-::::
-::::tab{id="cmd" label="CMD"}
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws lambda invoke ^
---function-name cfn-workshop-python-function ^
---payload "{\"time_zone\": \"Asia/Tokyo\"}" ^
---cli-binary-format raw-in-base64-out ^
-response.json
-:::
-::::
-::::tab{id="powershell" label="Powershell"}
-:::code{language=powershell showLineNumbers=false showCopyAction=true}
-aws lambda invoke `
- --function-name cfn-workshop-python-function `
- --payload "{\`"time_zone\`": \`"Asia/Tokyo\`"}" `
- --cli-binary-format raw-in-base64-out `
- response.json
-:::
-::::
-:::::
-
-Lambda がトリガーされ、Lambda からのレスポンスが `response.json` ファイルに保存されます。
-
-以下のコマンドを実行すると、ファイルの結果を確認できます。
-
-:::::tabs{variant="container"}
-
-::::tab{id="sh" label="Unix/Linux"}
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cat response.json
-:::
-::::
-
-::::tab{id="cmd" label="CMD/Powershell"}
-:::code{language=powershell showLineNumbers=false showCopyAction=true}
-more response.json
-:::
-::::
-:::::
-
----
-
-### クリーンアップ
-
-次の手順に従ってこのラボで作成したリソースをクリーンアップしてください。
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. 次の AWS CLI コマンドを使用して S3 バケットを削除します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3 rb s3://example-bucket-name --force
-:::
-1. 次の AWS CLI コマンドを使用してスタックを削除します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --stack-name cfn-workshop-package-deploy-lambda
-:::
-1. 次の AWS CLI コマンドを使用して、スタックの削除が完了するのを待ちます。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---stack-name cfn-workshop-package-deploy-lambda
-:::
-::::
-::::tab{id="LocalDevelopment" label="ローカル開発"}
-1. [AWS S3 コンソール](https://s3.console.aws.amazon.com/s3/)に移動します。
-1. このラボで作成した S3 バケットを選択し、 **空にする** を選択します。
-1. コンソールの指示に従って、バケット内のオブジェクトの削除を確認します。
-1. 次に S3 コンソールに戻り、このラボで作成した S3 バケットを選択し、 **削除** を選択します
-1. コンソールの指示に従って、S3 バケットの削除を確認します。
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. `cfn-workshop-package-deploy-lambda` という名前のスタックを選択し、 **削除** を選択します。
-1. ポップアップウィンドウで、 **削除** を選択します。
-1. **DELETE_COMPLETE** というステータスが表示されるまで、画面を更新します。
-::::
-:::::
-
----
-
-### まとめ
-
-おめでとうございます。コマンドラインを使用して CloudFormation テンプレートを正常にパッケージ化およびデプロイしました。
-
-* `package` コマンドは、ネストされたスタック等を使用するテンプレートや、ローカルアセットを参照するテンプレートのデプロイを簡略化します。
-* `validate` コマンドは、エラーをより迅速に検出することでテンプレートの開発をスピードアップできます。
-* `deploy` コマンドを使うと、CloudFormation テンプレートをデプロイすることができます。
diff --git a/content/intermediate/templates/package-and-deploy/index.md b/content/intermediate/templates/package-and-deploy/index.md
deleted file mode 100644
index c8ebbe898..000000000
--- a/content/intermediate/templates/package-and-deploy/index.md
+++ /dev/null
@@ -1,340 +0,0 @@
----
-title: "Package and deploy"
-weight: 600
----
-
-_Lab Duration: ~15 minutes_
-
----
-
-### Overview
-
-In the [Basics](/basics) part of this workshop, you have deployed single YAML templates via CloudFormation console.
-That was pretty easy to do so. However, in some cases, CloudFormation templates refer to other files, or artifacts.
-
-For example Lambda source code or ZIP file, or nested CloudFormation Template files may be such “artifacts”. As you
-learn in [Nested Stacks Lab](/intermediate/templates/nested-stacks), these files have to be available in S3 before
-you can deploy the main CloudFormation template.
-
-Deploying more complex stacks is a multi-stage process, but fortunately AWS-CLI provides a method for deploying
-CloudFormation templates that refer to other files.
-
-This section will cover three key commands, used to package, validate and deploy CloudFormation templates with the AWS CLI.
-
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-* Identify when packaging a template is required
-* Package a template using `aws cloudformation package` command
-* Validate a CloudFormation template using `aws cloudformation validate-template` command
-* Deploy a template using the ` aws cloudformation deploy` command
-
-### Start Lab
-
-Have a look at the sample project at `code/workspace/package-and-deploy` directory.
-
-The project consists of:
-
-* A CloudFormation template to spin up the infrastructure.
-* One Lambda function.
-* Requirements file to install your function dependencies.
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-cfn101-workshop/code/workspace/package-and-deploy
-├── infrastructure.template
-└── lambda/
- ├── lambda_function.py
- └── requirements.txt
-:::
-
-#### Reference local files in CloudFormation template
-
-Traditionally you would have to zip up and upload all the lambda sources to S3 first and then in the template refer to these S3 locations. This can be quite cumbersome.
-
-However, with [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) you can refer to the local files directly. That’s much more convenient!
-
-If you look at `infrastructure.template` snippet, you can see the reference in the `Code` property to the local directory, line [9].
-
-:::code{language=yaml showLineNumbers=true showCopyAction=false lineNumberStart=19}
-PythonFunction:
- Type: AWS::Lambda::Function
- Properties:
- FunctionName: cfn-workshop-python-function
- Description: Python Function to return specific TimeZone time
- Runtime: python3.12
- Role: !GetAtt LambdaBasicExecutionRole.Arn
- Handler: lambda_function.handler
- Code: lambda/ # <<< This is a local directory
-:::
-
-#### Package and Upload the artifacts
-
-The `aws cloudformation package` performs the following actions:
-
-1. ZIPs up the local files.
-1. Uploads them to a designated S3 bucket.
-1. Generates a new template where the local paths are replaced with the S3 URIs.
-
-##### 1. Create S3 bucket
-
-Decide on the AWS region where you will be deploying your Cloudformation template. The S3 bucket has to be in the same region as Lambda, to allow Lambda access to packaged artifacts.
-
-::alert[Make sure to replace the name of the bucket after `s3://` with a unique name!]{type="info"}
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3 mb s3://example-bucket-name --region us-east-1
-:::
-
-##### 2. Install function dependencies
-
-Our function depends on an external library [pytz](https://pypi.org/project/pytz/). You need to install it to a local
-directory with [pip](https://pypi.org/project/pip/), so it can be packaged with your function code.
-
-From within a `code/workspace/package-and-deploy` directory run:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-pip install pytz --target lambda
-:::
-
-If you have `python 3` installed you may have to use `pip3` instead of `pip` for the above command.
-
-You should see the `pytz` package inside the `lambda/` folder.
-
-##### 3. Run the `package` command
-
-From within a `code/workspace/package-and-deploy` directory run:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation package \
---template-file infrastructure.template \
---s3-bucket example-bucket-name \
---s3-prefix cfn-workshop-package-deploy \
---output-template-file infrastructure-packaged.template
-:::
-
-Let's have a closer look at the individual `package` options you have used in the command above.
-
-* `--template-file` - This is a path where your CloudFormation template is located.
-* `--s3-bucket` - The name of the S3 bucket where the artifacts will be uploaded to.
-* `--s3-prefix` - The prefix name is a path name (folder name) for the S3 bucket.
-* `--output-template-file` - The path to the file where the command writes the output AWS CloudFormation template.
-
-##### 4. Examine the packaged files
-
-Let's have a look at the newly generated file `infrastructure-packaged.template`.
-
-You can notice that the `Code` property has been updated with two new attributes, `S3Bucket` and `S3Key`, lines [12-14].
-
-:::code{language=yaml showLineNumbers=true showCopyAction=true lineNumberStart=16 highlightLines=12-14}
-PythonFunction:
- Type: AWS::Lambda::Function
- Properties:
- FunctionName: cfn-workshop-python-function
- Description: Python Function to return specific TimeZone time
- Runtime: python3.12
- Role:
- Fn::GetAtt:
- - LambdaBasicExecutionRole
- - Arn
- Handler: lambda_function.handler
- Code:
- S3Bucket: example-bucket-name
- S3Key: cfn-workshop-package-deploy/1234567890
-:::
-
-For completeness let’s also look what’s in the uploaded files. From the listing above we know the bucket and object name to download.
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3 cp s3://example-bucket-name/cfn-workshop-package-deploy/1234567890 .
-:::
-
-We know that `package` will generate ZIP files, so even there is no `.zip` extension you can still `unzip` it.
-
-:::::tabs{variant="container"}
-::::tab{id="shell" label="Unix/Linux"}
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-unzip -l ce6c47b6c84d94bd207cea18e7d93458
-
-Archive: ce6c47b6c84d94bd207cea18e7d93458
- Length Date Time Name
---------- ---------- ----- ----
- 12 02-12-2020 17:21 requirements.txt
- 455 02-12-2020 17:18 lambda_function.py
- 4745 02-13-2020 14:36 pytz/tzfile.py
-:::
-::::
-::::tab{id="powershell" label="Powershell"}
-:::code{language=powershell showLineNumbers=false showCopyAction=false}
-rename-item ce6c47b6c84d94bd207cea18e7d93458 packagedLambda.zip
-
-Expand-Archive -LiteralPath packagedLambda.zip -DestinationPath packagedLambda
-
-ls packagedLambda
-
-Directory: C:\Users\username\cfn101-workshop\code\workspace\package-and-deploy\tmp
-Mode LastWriteTime Length Name
----- ------------- ------ ----
-d----- 10/29/2021 4:25 PM pytz
-d----- 10/29/2021 4:25 PM pytz-2021.3.dist-info
--a---- 10/29/2021 11:19 AM 475 lambda_function.py
--a---- 10/29/2021 11:19 AM 14 requirements.txt
-:::
-::::
-:::::
-
-### Validating a template
-
-Sometimes a CloudFormation template deployment will fail due to syntax errors in the template.
-
-[`aws cloudformation validate-template`](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/validate-template.html)
-checks a CloudFormation template to ensure it is valid JSON or YAML. This is useful to speed up development time.
-
-Let's validate our packaged template. From within a `code/workspace/package-and-deploy` directory run:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation validate-template \
---template-body file://infrastructure-packaged.template
-:::
-
-If successful, CloudFormation will send you a response with a list of parameters, template description and capabilities.
-
-:::code{language=json showLineNumbers=false showCopyAction=false}
-{
- "Parameters": [],
- "Description": "AWS CloudFormation workshop - Package and deploy.",
- "Capabilities": [
- "CAPABILITY_IAM"
- ],
- "CapabilitiesReason": "The following resource(s) require capabilities: [AWS::IAM::Role]"
-}
-:::
-
-### Deploying the "packaged" template
-
-The [`aws cloudformation deploy`](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy/index.html)
-command is used to deploy CloudFormation templates using the CLI.
-
-Let's deploy packaged template.
-
-From within a `code/workspace/package-and-deploy` directory run:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation deploy \
---template-file infrastructure-packaged.template \
---stack-name cfn-workshop-package-deploy-lambda \
---region eu-west-1 \
---capabilities CAPABILITY_IAM
-:::
-
-::alert[Note that we used the packaged template `infrastructure-packaged.template` that refers to the artifacts in S3. Not the original one with local paths!]{type="info"}
-
-You can also set `--parameter-overrides` option to specify parameters in the template.
-This can be string containing `'key=value'` pairs or a via a [supplied json file](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-parameters.html#cli-usage-parameters-json).
-
-##### Capabilities
-
-You may recall when using the console, you are required to acknowledge that deploying this template may create resource
-that can affect permissions in your account. This is to ensure you don't accidentally change the permissions unintentionally.
-
-When using the CLI, you are also required to acknowledge this stack might create resources that can affect IAM permissions.
-This is done using the `--capabilities` flag, as demonstrated in the previous example. Read more about the possible capabilities
-in the [`aws cloudformation deploy` documentation](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy/index.html)
-
-#### Test the Lambda
-
-To test the Lambda function, we will use [aws lambda invoke](https://docs.aws.amazon.com/cli/latest/reference/lambda/invoke.html) command.
-
-The Lambda function will determinate current UTC date and time. Then it will convert the UTC time to the Timezone specified in the payload option.
-
-From your terminal run:
-
-:::::tabs{variant="container"}
-::::tab{id="sh" label="Unix/Linux"}
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws lambda invoke \
---function-name cfn-workshop-python-function \
---payload "{\"time_zone\": \"Europe/London\"}" \
---cli-binary-format raw-in-base64-out \
-response.json
-:::
-::::
-::::tab{id="cmd" label="CMD"}
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws lambda invoke ^
---function-name cfn-workshop-python-function ^
---payload "{\"time_zone\": \"Europe/London\"}" ^
---cli-binary-format raw-in-base64-out ^
-response.json
-:::
-::::
-::::tab{id="powershell" label="Powershell"}
-:::code{language=powershell showLineNumbers=false showCopyAction=true}
-aws lambda invoke `
- --function-name cfn-workshop-python-function `
- --payload "{\`"time_zone\`": \`"Europe/London\`"}" `
- --cli-binary-format raw-in-base64-out `
- response.json
-:::
-::::
-:::::
-
-Lambda will be triggered, and the response form Lambda will be saved in `response.json` file.
-
-You can check the result of the file by running command below:
-
-:::::tabs{variant="container"}
-::::tab{id="sh" label="Unix/Linux"}
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cat response.json
-:::
-::::
-::::tab{id="cmd" label="CMD/Powershell"}
-:::code{language=powershell showLineNumbers=false showCopyAction=true}
-more response.json
-:::
-::::
-:::::
-
----
-### Cleanup
-
-Choose to follow cleanup steps shown next to clean up resources you created with this lab:
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. Delete the S3 bucket by using the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws s3 rb s3://example-bucket-name --force
-:::
-1. Delete the stack by using the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation delete-stack \
- --stack-name cfn-workshop-package-deploy-lambda
-:::
-1. Wait for the Stack deletion to complete by using the following AWS CLI command
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation wait stack-delete-complete \
---stack-name cfn-workshop-package-deploy-lambda
-:::
-::::
-::::tab{id="LocalDevelopment" label="LocalDevelopment"}
-1. Navigate to the [AWS S3 Console](https://s3.console.aws.amazon.com/s3/).
-1. Select the S3 bucket that you have created during this lab, Choose **Empty**.
-1. Follow the instructions on the console to confirm the deletion of objects in the buckets.
-1. Now switch back to S3 Console, Select the S3 bucket that you have created during this lab, Choose **Delete**
-1. Follow the instructions on the console to confirm the deletion of the S3 bucket.
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. Select the stack named `cfn-workshop-package-deploy-lambda` and choose **Delete**.
-1. In the pop-up window choose **Delete**.
-1. You can click the refresh button a few times until you see in the status **DELETE_COMPLETE**.
-::::
-:::::
-
----
-
-### Conclusion
-Congratulations, you have successfully packaged and deployed CloudFormation template using the command line.
-
-* The `package` command simplifies deployment of templates that use features such as nested stacks, or refer to other local assets.
-* The `validate` command can speed up development of templates by catching errors more quickly.
-* The `deploy` command allows you to deploy CloudFormation templates.
diff --git a/content/intermediate/templates/policy-as-code-with-guard/index.ja.md b/content/intermediate/templates/policy-as-code-with-guard/index.ja.md
deleted file mode 100644
index fbbcdb7f1..000000000
--- a/content/intermediate/templates/policy-as-code-with-guard/index.ja.md
+++ /dev/null
@@ -1,408 +0,0 @@
----
-title: "Policy-as-code with Guard"
-weight: 700
----
-
-
-### 概要
-
-一般的な組織では、セキュリティチームが組織が必要とするセキュリティ、ガバナンス、およびポリシーコンプライアンスの要件を設定します。要件には、Infrastructure as Code (IaC) 設定の要件も含まれます。例えば、セキュリティチームが [Amazon Simple Storage Service](https://aws.amazon.com/jp/s3/) (Amazon S3) バケットをデフォルトでサーバー側の暗号化で設定し、バージョニングを有効にするというポリシーを規定します。
-
-ベストプラクティスの一環として、policy-as-code プラクティスを採用して、ソフトウェア開発ライフサイクル(SDLC)のごく早い段階で、次のようなポリシー・コンプライアンスの問題をプログラムで検出します。
-
-* 開発者のワークステーションで検出
-* デリバリーパイプラインの継続的インテグレーション (CI) フェーズで検出
-
-policy-as-code を採用すると、SDLC プロセスの早い段階で発見したポリシー・コンプライアンスの問題に対処する機会が得られるため、 **SDLC のフィードバック・ループをスピードアップ** できます。
-
-Policy-as-Code をプログラムで活用するには、ポリシー要件を、Policy-as-Code ツールが理解できる言語で記述されたルールに変換する必要があります。このラボでは、[AWS CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) (Guard) などのツールを使用して、作成したルールに対するポリシーコンプライアンスの検証方法を学びます。
-
-
-### 取り上げるトピック
-
-このラボを修了すると、次のことができるようになります。
-
-* Guard が使用するドメイン固有言語 (DSL) の基本を理解
-* 最初のガードルールを記述
-* デフォルトのターゲット選択方法としてフィルターを使用
-* ルール / ルール節をモジュール性と再利用性を考慮して記述
-* 初めてのガードルールテストを記述
-* ガードルールを書く際のプラクティスとしてテスト駆動開発 (TDD) を採用
-* 詳細と高度な使用例については、Guard のドキュメントを参照
-
-
-### ラボを開始
-
-#### Guard をインストール
-使用しているオペレーティングシステムに応じて、ワークステーションに [Guard](https://github.com/aws-cloudformation/cloudformation-guard#installation) をインストールします。マシンに [Rust と Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) がインストールされている場合 (または Rust と Cargo をインストールする場合)、以下の方法で Guard を簡単にインストールすることができます。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cargo install cfn-guard
-:::
-
-Guard をセットアップしたら、次のコマンドを正常に実行できることを確認します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard help
-:::
-
-#### 最初のガードルールを記述
-
-このセクションでは、サンプルの CloudFormation テンプレートが [Amazon S3 バケット](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html) と必要な次のプロパティを記述していることを検証するためのガードルール節の例を記述します。
-
-* AES256 アルゴリズムを例として使用し、[サーバー側の暗号化](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-bucketencryption.html)
-* [バージョニング](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-versioningconfig.html) 有効化
-
-さあ、始めましょう! 次に示す手順に従って進めます。
-
-1. `code/workspace/policy-as-code-with-guard` ディレクトリに移動します。
-1. お好みのテキストエディタで `example_bucket.yaml` CloudFormation テンプレートを開きます。
-1. テンプレートには `AWS::S3::Bucket` リソースタイプが記述されています。AES256 アルゴリズムを使用して [サーバー側の暗号化](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-bucketencryption.html)と[バージョニング](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-versioningconfig.html)有効化設定を含む `Properties` セクションを追加してテンプレートを更新します。次に表示される内容をコピーし、`example_bucket.yaml` ファイルにペーストします。
-
-```yaml
-Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
- VersioningConfiguration:
- Status: Enabled
-```
-
-1. ガードルール節の例を作成して、両方のプロパティが期待どおりに記述されていることを確認します。前述と同じディレクトリにある `example_bucket.guard` ファイルを開き、 **type ブロック** を作成して、テンプレートに記述した `AWS::S3::Bucket` タイプのリソースの設定を検証します。次に表示されるコンテンツをコピーし、`example_bucket.guard` ファイルにペーストします。
-
-```json
-AWS::S3::Bucket {
- Properties {
- BucketEncryption.ServerSideEncryptionConfiguration[*] {
- ServerSideEncryptionByDefault.SSEAlgorithm == 'AES256'
- <>
- }
- VersioningConfiguration.Status == 'Enabled'
- <>
- }
-}
-```
-
-::alert[ガードルールを書くときは、リソースタイプを選択するデフォルトモードとして **filters** を使用します。新しい概念について少しずつ学んでいくので、このセクションでは引き続き type ブロック (特定の型をマッチさせる場合に使うフィルターのためのブロック) を使います。フィルターについては次のセクションで学びます。]{type="info"}
-
-1. 前述のルール節のサンプルセットを確認してください。次の点に注意してください。
- * 外側のブロックには `AWS::S3::Bucket` タイプが含まれています。このブロック内のルール条項は、入力データとして提供しているテンプレートで宣言した `AWS::S3::Bucket` タイプのすべてのリソースに適用されます。
- * ルール節は、ドット (`.`) 文字を使ってデータ階層を下ります (例えば、`VersioningConfiguration.Status` は `VersioningConfiguration` の下の `Status` プロパティを参照します)。
- * ワイルドカード (`*`) 文字は、特定のレベルのすべての配列インデックスを辿るために使われます (例えば、`ServerSideEncryptionConfiguration[*]`)。
- * ルール節には、`<<` と `>>` ブロックで区切られたオプションのセクションが含まれており、[カスタムメッセージ](https://docs.aws.amazon.com/ja_jp/cfn-guard/latest/ug/writing-rules.html#clauses-custom-messages) を指定できます。
- * 例で宣言されているルール節は検証に合格することが期待されます。Guard では、[連言標準形](https://ja.wikipedia.org/wiki/%E9%80%A3%E8%A8%80%E6%A8%99%E6%BA%96%E5%BD%A2) (CNF) を使用し、複数の論理的な `AND` 節を、`OR` 節を交えて記述します。前述の例では、ルール節は `AND` 節として解釈されます (つまり、サーバー側の暗号化 *と* バージョン管理を検証し、データがルールに照らして検証に合格するには、*両方* が満たされる必要があります。)。例えば、ClauseA *または* ClauseB が満たされているかを検証したいユースケースがある場合は、ClauseA の行に `OR` を追加してこの動作を記述します。次の例において、ルールを合格するためには、`ExampleClause1` と `ExampleClause2` の両方の要件が満たされている必要があります。`ExampleClauseA` か `ExampleClauseB` のどちらかが満たされなければなりません:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-[...]
-ExampleClause1
-ExampleClause2
-ExampleClauseA OR
-ExampleClauseB
-[...]
-:::
-
-1. ルール節の例を詳しく見てきたので、次に示すように、`-d` (または `—data`) フラグでテンプレートを指定し、`-r` (または `—rules`) でルールを指定して、`validate` Guard サブコマンドを実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard --show-summary pass
-:::
-
-1. テンプレートがルール節に対する検証に合格したことを示す次のような出力が得られるはずです。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-example_bucket.yaml Status = PASS
-PASS rules
-example_bucket.guard/default PASS
----
-Evaluation of rules example_bucket.guard against data example_bucket.yaml
---
-Rule [example_bucket.guard/default] is compliant for template [example_bucket.yaml]
---
-:::
-
-::alert[前述の `example_bucket.guard/default` 出力部分に示されている `default` サフィックスは、ルール節が `default` という名前のルールに属していることを示しています。このラボの後半で、特定の名前 ( **名前付きルール** ) でルールを作成し、デフォルトルールの代わりに使用します。この作業を実施することで、モジュール化された再利用可能なルールを作成できます。]{type="info"}
-
-おめでとうございます! 最初のガードルールを作成し、それを使用して S3 バケット設定例を記述したサンプルテンプレートを検証しました。
-
-
-#### フィルタリング
-
-前の例では、type ブロックを使用して、入力テンプレートに記述した特定のタイプのターゲットリソースを選択しました。このセクションでは、ルールに照らして検証したいターゲットを柔軟に選択できる **filters** について学びます。例えば、テンプレートに記述した全ての [AWS::IAM::Policy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html) と [AWS::IAM::ManagedPolicy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html) リソースの `PolicyDocument` プロパティ (両方のリソースタイプに共通するプロパティ) を検証するには、次のような両方のタイプのリソースをクエリするフィルタを作成します。
-
-:::code{language=json showLineNumbers=false showCopyAction=true}
-Resources.*[
- Type in [ 'IAM::Policy', 'IAM::ManagedPolicy' ]
-]
-:::
-
-先程使ったルール節の例をフィルターで書き直してみましょう! この演習の一部として、`let` を使用して `my_buckets` サンプル変数を宣言し、次に示すように `%` 文字を使用したサンプルルールで、その変数を参照します。
-
-```javascript
-let my_buckets = Resources.*[ Type == 'AWS::S3::Bucket' ]
-
-
-%my_buckets.Properties {
- BucketEncryption.ServerSideEncryptionConfiguration[*] {
- ServerSideEncryptionByDefault.SSEAlgorithm == 'AES256'
- <>
- }
- VersioningConfiguration.Status == 'Enabled'
- <>
-}
-```
-
-`example_bucket.guard` の既存のルール節を新しい内容に置き換えて、検証を再実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard
-:::
-
-フィルターを使用しているルール節に対する検証が合格するはずです。
-
-::alert[Guard は *file*、*rule*、*block* レベルで変数スコープをサポートしています。特定のスコープ内の変数の具体的な配置によって、ガードルールを含むファイルでの変数の可視性が決まります。前に示した `my_buckets` 変数のスコープはファイルレベルのスコープなので、`example_bucket.guard` ルールファイルに記述したルール / ルール節から `my_buckets` が見えるはずです。詳細については、[AWS CloudFormation Guard ルールにおける変数の割り当てと参照](https://docs.aws.amazon.com/ja_jp/cfn-guard/latest/ug/variables.html) をご参照ください。]{type="info"}
-
-おめでとうございます! テンプレート内の特定のタイプのリソースに一致するフィルターを作成し、ファイルレベルでスコープした変数も再利用しました。
-
-
-#### モジュール性と再利用性を考慮してルールを書き直す
-
-このセクションでは、ルール節を別々のルールに分解して、モジュール化して再利用できるようにします。 **シンプルでモジュール化されたガードルールを作成すると、再利用の機会が得られるだけでなく、データを検証したときに失敗したルールを特定したり、必要に応じてルールをトラブルシューティングしたりするのが簡単になります。**
-
-前に示したルール節の例を思い出してください。1 つの節では、バケットに設定したサーバー側の暗号化設定を検証し、もう 1 つの節ではバケットのバージョニング有効化設定を検証しました。このロジックを 2 つの [名前付きルール](https://docs.aws.amazon.com/ja_jp/cfn-guard/latest/ug/named-rule-block-composition.html) に書き換えてみましょう。これらは名前を割り当てたルールです。
-
-`rule validate_bucket_sse_example` と `validate_bucket_versioning_example` の 2 つの名前付きルールを作成します。各ルール宣言ステートメントでは、入力データに選択ターゲット (この場合は `AWS::S3::Bucket` リソース) が存在する場合にのみ入力データに対して指定されたルールを実行することを目的として、`when` キーワードを使用します。
-
-```javascript
-let my_buckets = Resources.*[ Type == 'AWS::S3::Bucket' ]
-
-
-rule validate_bucket_sse_example when %my_buckets !empty {
- %my_buckets.Properties {
- BucketEncryption.ServerSideEncryptionConfiguration[*] {
- ServerSideEncryptionByDefault.SSEAlgorithm == 'AES256'
- <>
- }
- }
-}
-
-
-rule validate_bucket_versioning_example when %my_buckets !empty {
- %my_buckets.Properties {
- VersioningConfiguration.Status == 'Enabled'
- <>
- }
-}
-```
-
-`example_bucket.guard` 内の既存のルール節を置き換えます。上記、名前付きの 2 つのルールをコピーして貼り付けます。完了したら、検証を再実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard
-:::
-
-すると、以下のような出力が得られるはずです。前に確認した `default` ルールの代わりに、`rule validate_bucket_sse_example` と `validate_bucket_versioning_example` ルールに割り当てた名前が表示されるはずです。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-example_bucket.yaml Status = PASS
-PASS rules
-example_bucket.guard/validate_bucket_sse_example PASS
-example_bucket.guard/validate_bucket_versioning_example PASS
----
-Evaluation of rules example_bucket.guard against data example_bucket.yaml
---
-Rule [example_bucket.guard/validate_bucket_sse_example] is compliant for template [example_bucket.yaml]
-Rule [example_bucket.guard/validate_bucket_versioning_example] is compliant for template [example_bucket.yaml]
---
-:::
-
-::alert[入力データにターゲットの選択が含まれていない場合 (前の例で、テンプレートに Amazon S3 バケットを記述しなかった場合): 前述の (`when %my_buckets !empty`) のように `when` キーワードを使用する場合、ルールの評価はスキップされ、結果の Guard 出力で `SKIP` とマークされます。もし、代わりに `when` キーワードと `%my_buckets !empty` の部分を省略すると、ルールは取得エラーにより失敗します。節、クエリ、演算子の詳細については、[AWS CloudFormation Guard ルールの作成](https://docs.aws.amazon.com/ja_jp/cfn-guard/latest/ug/writing-rules.html)をご参照ください。]{type="info"}
-
-おめでとうございます! 最初のルール節を 2 つの別々の名前付きルールに分離したので、モジュール性と再利用性が優先されます。 また、必要に応じてコードを書いたり、使用したり、トラブルシューティングしたりするための小規模のコードの例も用意しました。
-
-
-#### ルールの相互関係
-
-ユースケースやビジネスロジックの実装ニーズに応じて、別のルール内から名前付きルールを参照できます。前の例を思い出してみましょう。`example_bucket.guard` ファイルに、次の内容を追加します。
-
-```json
-rule correlation_example when %my_buckets !empty {
- validate_bucket_sse_example
- validate_bucket_versioning_example
-}
-```
-
-`correlation_example` のサンプルルールは、同じファイルで前に説明した他の 2 つの名前付きルールを参照しています。`correlation_example` が合格するには、両方の名前付きルールが満たされている必要があります。検証を再実行します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard
-:::
-
-次の抜粋のような出力が得られるはずです。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-example_bucket.yaml Status = PASS
-PASS rules
-example_bucket.guard/validate_bucket_sse_example PASS
-example_bucket.guard/validate_bucket_versioning_example PASS
-example_bucket.guard/correlation_example PASS
-[...]
-:::
-
-`validate_bucket_sse_example` ルールや `validate_bucket_versioning_example` ルールが失敗した場合、`correlation_example` ルールも失敗します。
-
-おめでとうございます!これで、名前付きルールを相互に関連付けて参照する方法がわかりました。
-
-
-#### 初めてのガードルールテストの記述
-
-Guard では、ルールのテストを作成して、ルールが期待どおりに機能することを検証できます。この側面は、ワークフローで [テスト駆動開発](https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA) (TDD) のプラクティスを活用する機会も開きます。最初にルールのテストを作成することから始め、次にルールのテストを作成して実行します。
-
-さあ、始めましょう! お好みのテキストエディタで `example_bucket_tests.yaml` ファイルを開き、以前に使用した名前付きルールのテストを含む次の内容を追加します。
-
-```yaml
-- input:
- Resources:
- MyExampleBucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
- expectations:
- rules:
- validate_bucket_sse_example: PASS
-
-- input:
- Resources:
- MyExampleBucket:
- Type: AWS::S3::Bucket
- Properties:
- VersioningConfiguration:
- Status: Suspended
- expectations:
- rules:
- validate_bucket_versioning_example: FAIL
-```
-
-先ほど示したテスト内容の例を見ると、テストには 2 つの `input` セクションがあり、この例では各テストケースに 1 つずつあることがわかります。
-* 最初のテストケースでは、`validate_bucket_sse_example` ルール検証のサーバー側の暗号化検証ロジックが、期待されるテスト入力が提供されたときに合格することをテストします。この例では、`bucketEncryption` の下の `SSEAlgorithm` プロパティに `AES256` を使用しています。
-* 2 つ目のテストケースでは、`VersioningConfiguration` の `Status` に、(`Enabled` ではなく) `Suspended` を提供すると、`validate_bucket_versioning_example` ルールの検証が失敗することが予想されます。
-
-テストを実行しましょう! `test` Guard サブコマンドを使用してテストファイルを指定し、その後に `-t` (または `—test-data`) を使用してテストファイルを指定し、`-r` (または `—rules-file`) を使用してテスト対象のルールを含むファイルを指定します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard test -t example_bucket_tests.yaml -r example_bucket.guard
-:::
-
-テストケースの例と期待する結果の両方を示した、次の例のような出力が得られるはずです。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-Test Case #1
- No Test expectation was set for Rule validate_bucket_versioning_example
- No Test expectation was set for Rule correlation_example
- PASS Rules:
- validate_bucket_sse_example: Expected = PASS, Evaluated = PASS
-
-Test Case #2
- No Test expectation was set for Rule validate_bucket_sse_example
- No Test expectation was set for Rule correlation_example
- PASS Rules:
- validate_bucket_versioning_example: Expected = FAIL, Evaluated = FAIL
-:::
-
-おめでとうございます! ガードルールの最初のテストを書いて実行しました!
-
-
-### チャレンジ
-
-[Amazon S3 バケット](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html) の `PublicAccessBlockConfiguration` の全ての[プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-properties) を `true` (Boolean) に設定します。
-
-タスクは以下のとおりです。
-1. `example_bucket_tests.yaml` ユニットテストファイルの内容に、`true` に設定されたすべての `publicAccessBlockConfiguration` プロパティを含むテスト入力データを提供するときに、これから作成する `validate_bucket_public_access_block_example` という新しいルールを検証するための新しい `input` セクションを追加します。
-1. `example_bucket.guard` ファイルに `validate_bucket_public_access_block_example` ルールを実装します。ルールに記述する各節の後に、`PublicAccessBlockConfiguration` プロパティごとにカスタムメッセージを追加します。
-1. テストを実行するには、`test` サブコマンドで Guard を実行します。ユニットテストの出力に Test Case #3 セクションがあり、新しいルールのユニットテストが成功したことを示す `validate_bucket_public_access_block_example: Expected = PASS, Evaluated = PASS` のような行があるはずです。
-1. `example_bucket.yaml` テンプレートを更新し、関連する `PublicAccessBlockConfiguration` 設定を追加します。
-1. `validate` サブコマンドを使用して Guard を実行し、`example_bucket.yaml` ファイルの内容を、`example_bucket.guard` ファイルに記述したルールと照らし合わせて検証します。結果の出力には、新しいルールに対する検証が成功したことを示す `example_bucket.guard/validate_bucket_public_access_block_example PASS` のような文字列が表示されるはずです。
-
-
-:::expand{header= "ヒントが必要ですか?"}
-* `PublicAccessBlockConfiguration` プロパティドキュメント [ページ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html) に移動して、その下にあるプロパティの名前を調べます。
-* `versioningConfiguration.Status` 節についても、同じルール構造に従います。`PublicAccessBlockConfiguration` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html) のそれぞれについて記述するルール節については、文字列の代わりに ブール値 `true` を利用します。
-:::
-
-
-::::expand{header= "解決策を確認しますか?"}
-注:次に示す内容は、`code/solutions/policy-as-code-with-guard` ディレクトリにある関連ファイルにもあります。
-
-* 下記の内容を `example_bucket_tests.yaml` ユニットテストファイルに追加します。
-
-```yaml
-- input:
- Resources:
- MyExampleBucket:
- Type: AWS::S3::Bucket
- Properties:
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- expectations:
- rules:
- validate_bucket_public_access_block_example: PASS
-```
-
-
-* 下記の内容を `example_bucket.guard` ファイルに追加します。
-
-```json
-rule validate_bucket_public_access_block_example when %my_buckets !empty {
- %my_buckets.Properties {
- PublicAccessBlockConfiguration.BlockPublicAcls == true
- <>
-
- PublicAccessBlockConfiguration.BlockPublicPolicy == true
- <>
-
- PublicAccessBlockConfiguration.IgnorePublicAcls == true
- <>
-
- PublicAccessBlockConfiguration.RestrictPublicBuckets == true
- <>
- }
-}
-```
-
-
-* ユニットテストを実行し、検証に合格することを確認します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard test -t example_bucket_tests.yaml -r example_bucket.guard
-:::
-
-
-* このコンテンツを `example_bucket.yaml` テンプレートに追加します。
-
-```yaml
-PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
-```
-
-
-* テンプレートデータをルールに照らして検証し、すべてのルールが検証に合格することを確認します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard
-:::
-::::
-
-
----
-### まとめ
-
-ガードルールの作成とテストの基礎を理解することができました! Guard の詳細については、[ドキュメント](https://docs.aws.amazon.com/ja_jp/cfn-guard/latest/ug/what-is-guard.html) をご参照ください。また、よくある質問や例を含むコンテンツ [Guard リポジトリ](https://github.com/aws-cloudformation/cloudformation-guard)もご参照ください。
diff --git a/content/intermediate/templates/policy-as-code-with-guard/index.md b/content/intermediate/templates/policy-as-code-with-guard/index.md
deleted file mode 100644
index fe5497367..000000000
--- a/content/intermediate/templates/policy-as-code-with-guard/index.md
+++ /dev/null
@@ -1,408 +0,0 @@
----
-title: "Policy-as-code with Guard"
-weight: 700
----
-
-
-### Overview
-
-In a typical organization, a Security team establishes security, governance, and policy compliance requirements the organization needs. This includes requirements for Infrastructure as Code (IaC) configurations: for example, a Security team establishes a policy prescribing that [Amazon Simple Storage Service](https://aws.amazon.com/s3/) (Amazon S3) buckets must be configured with server-side encryption by default, and with versioning enabled.
-
-As part of best practices, you choose to adopt the policy-as-code practice to programmatically detect policy compliance issues very early in the Software Development Life Cycle (SDLC), such as:
-
-* in developers’ workstations, and
-* in the Continuous Integration (CI) phase of your delivery pipelines
-
-When you adopt the policy-as-code practice, you **speed up your SDLC feedback loop** because you have the opportunity to address policy compliance issues you detected early in the SDLC process.
-
-In order to programmatically leverage policy-as-code, a company first needs to translate their policy requirements into rules written in a language that a policy-as-code tool understands. In this lab, you will learn how you can use a tool such as [AWS CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) (Guard) for policy compliance validation against rules you write.
-
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* Understand basics of the domain-specific language (DSL) used by Guard
-* Write your first Guard rule
-* Use filters as the default method for selecting targets
-* Rewrite your rules/rule clauses for modularity and reusability
-* Write your first Guard rule test
-* Adopt test-driven development (TDD) as a practice when you write Guard rules
-* Reference the Guard documentation for more information and advanced use cases
-
-
-### Start Lab
-
-#### Install Guard
-Choose to [install Guard](https://github.com/aws-cloudformation/cloudformation-guard#installation) in your workstation, by using a method of your choice depending on the operating system you use. If you have [Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) installed on your machine (or if choose to install Rust and Cargo), it is easy to install Guard with:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cargo install cfn-guard
-:::
-
-Once you have set up Guard with a method you chose, verify you can successfully run it:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard help
-:::
-
-#### Write your first Guard rule
-
-In this section, you will write example Guard rule clauses to validate that a sample CloudFormation template describes an [Amazon S3 bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html) with following properties you require:
-
-* [server-side encryption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-bucketencryption.html) using the AES256 algorithm as an example, and
-* [versioning](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-versioningconfiguration.html) enabled
-
-Let's get started! Choose to follow steps shown next:
-
-1. Change directory to the `code/workspace/policy-as-code-with-guard` directory.
-2. Open the `example_bucket.yaml` CloudFormation template in your favorite text editor.
-3. The template describes an `AWS::S3::Bucket` resource type; update the template by appending a `Properties` section with [server-side encryption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-bucketencryption.html) configuration using the AES256 algorithm, and [versioning](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-versioningconfiguration.html) enabled. Choose to copy content shown next, and paste it in the `example_bucket.yaml` file by appending it to the existing file content:
-
-```yaml
-Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
- VersioningConfiguration:
- Status: Enabled
-```
-
-4. Create example Guard rule clauses to validate both properties are described as you expect. Open the `example_bucket.guard` file in the same directory mentioned earlier, and create a **type block** to validate your configuration for resource(s) of type `AWS::S3::Bucket` you describe in your template. Copy content shown next, and paste it in the `example_bucket.guard` file by appending it to the existing content:
-
-```json
-AWS::S3::Bucket {
- Properties {
- BucketEncryption.ServerSideEncryptionConfiguration[*] {
- ServerSideEncryptionByDefault.SSEAlgorithm == 'AES256'
- <>
- }
- VersioningConfiguration.Status == 'Enabled'
- <>
- }
-}
-```
-
-::alert[When you write your Guard rules, use **filters** as the default mode for selecting resource types. As you are gradually learning about new concepts, in this section you will continue to use a type block (which is a syntactic sugar block for a filter that only matches a selection by a given type), and you will learn about filters in the next section.]{type="info"}
-
-5. Inspect the previous set of example rule clauses. Note the following:
- * the outer, enclosing block contains a `AWS::S3::Bucket` type; rule clauses inside this block will apply to all the resources of the `AWS::S3::Bucket` type you declare in the template you are providing as input data;
- * rule clauses use the dot (`.`) character to traverse down the data hierarchy (for example, `VersioningConfiguration.Status` to refer to the `Status` property underneath `VersioningConfiguration`);
- * the wildcard (`*`) character is used to traverse down all array indexes for a given level (e.g., for `ServerSideEncryptionConfiguration[*]`);
- * rule clauses contain optional sections, delimited by `<<` and `>>` blocks, where you can choose to provide a [custom message](https://docs.aws.amazon.com/cfn-guard/latest/ug/writing-rules.html#clauses-custom-messages);
- * you expect that rule clauses as declared in the example pass validation. With Guard, you use the [Conjunctive Normal Form](https://en.wikipedia.org/wiki/Conjunctive_normal_form) (CNF) to describe logical `AND` clauses across `OR` clauses: in the example shown earlier, rule clauses are interpreted as `AND` clauses (that is, you validate server-side encryption *and* versioning configurations, and *both* must be satisfied for your data to pass validation against your rule). When you have use cases where you want to validate that e.g., *either* clause A *or* clause B are satisfied instead, you describe this behavior by appending `OR` to the line for clause A. In the next example, for your rule to pass, both `ExampleClause1` and `ExampleClause2` requirements must be satisfied, and either `ExampleClauseA` or `ExampleClauseB` must be satisfied:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-[...]
-ExampleClause1
-ExampleClause2
-ExampleClauseA OR
-ExampleClauseB
-[...]
-:::
-
-6. Now that you have taken a closer look at example rule clauses, run the `validate` Guard subcommand by specifying your template with the `-d` (or `--data`) flag, and your rules with `-r` (or `--rules`) as shown next:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard --show-summary pass
-:::
-
-7. You should then get an output similar to the following, that indicates your template passed validation against your rule clauses:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-example_bucket.yaml Status = PASS
-PASS rules
-example_bucket.guard/default PASS
----
-Evaluation of rules example_bucket.guard against data example_bucket.yaml
---
-Rule [example_bucket.guard/default] is compliant for template [example_bucket.yaml]
---
-:::
-
-::alert[The `default` suffix shown in the preceding `example_bucket.guard/default` output portion indicates that your rule clauses belong to a rule named `default`. Later on in this lab, you will write rules with a given name (**named rules**), and you will use such rules instead of the default rule. This will give you opportunities to create modular and reusable rules.]{type="info"}
-
-Congratulations! You created your first Guard rule, and you used it to validate an example template that described an example S3 bucket configuration!
-
-
-#### Filtering
-
-In the previous example, you have used type blocks to select target resources of a given type that you describe in your input template. In this section, you will learn about **filters**, that give you flexibility in selecting targets you wish to validate against your rules. For example, if you want to validate that all [AWS::IAM::Policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html) and [AWS::IAM::ManagedPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html) resources you describe in your template contain a `PolicyDocument` property (that is a common property for both resource types), you first create a filter to query for resources of both types such as:
-
-:::code{language=json showLineNumbers=false showCopyAction=true}
-Resources.*[
- Type in [ 'IAM::Policy', 'IAM::ManagedPolicy' ]
-]
-:::
-
-Let's rewrite example rule clauses you used earlier by using filters! As part of this exercise, you will also declare a `my_buckets` example variable by using `let`, and you will reference that variable in the new implementation of example rules with the `%` character as shown next:
-
-```javascript
-let my_buckets = Resources.*[ Type == 'AWS::S3::Bucket' ]
-
-
-%my_buckets.Properties {
- BucketEncryption.ServerSideEncryptionConfiguration[*] {
- ServerSideEncryptionByDefault.SSEAlgorithm == 'AES256'
- <>
- }
- VersioningConfiguration.Status == 'Enabled'
- <>
-}
-```
-
-Replace existing rule clauses in `example_bucket.guard` with the new content just shown, and run the validation again:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard
-:::
-
-Validation against your rule clauses that now use filters should pass.
-
-::alert[Guard supports variable scopes at the *file*, *rule* and *block* level. The specific placement of a variable in a given scope determines its visibility in a file containing your Guard rules. The scope of the `my_buckets` variable shown earlier is a file-level scope: thus, `my_buckets` should be visible to rules/rule clauses you describe in the `example_bucket.guard` rules file. For more information, see [Assigning and referencing variables in AWS CloudFormation Guard rules](https://docs.aws.amazon.com/cfn-guard/latest/ug/variables.html).]{type="info"}
-
-Congratulations! You have created a filter that matches resources of a given type in your template, and you have also reused a variable you scoped at the file level.
-
-
-#### Rewrite your rule for modularity and reusability
-
-In this section, you will decouple rule clauses into separate rules, to favor modularity and reuse. **Writing simple and modular Guard rules not only gives you reuse opportunities, but it also makes it easier for you to pinpoint which rule failed when you validated your data, and/or to troubleshoot your rules as needed.**
-
-Recall example rule clauses shown earlier. With one clause, you validated the server-side encryption configuration you set up for your bucket, and with another clause you validated that you enabled versioning for your bucket. Let's rewrite this logic into two [named rules](https://docs.aws.amazon.com/cfn-guard/latest/ug/named-rule-block-composition.html), that are rules with a name you assign.
-
-You will create two named rules: `rule validate_bucket_sse_example` and `validate_bucket_versioning_example`. For each rule declaration statement, you will use the `when` keyword with the intent of running the given rule against your input data only when selection targets (in this case, `AWS::S3::Bucket` resources) are present in your input data:
-
-```javascript
-let my_buckets = Resources.*[ Type == 'AWS::S3::Bucket' ]
-
-
-rule validate_bucket_sse_example when %my_buckets !empty {
- %my_buckets.Properties {
- BucketEncryption.ServerSideEncryptionConfiguration[*] {
- ServerSideEncryptionByDefault.SSEAlgorithm == 'AES256'
- <>
- }
- }
-}
-
-
-rule validate_bucket_versioning_example when %my_buckets !empty {
- %my_buckets.Properties {
- VersioningConfiguration.Status == 'Enabled'
- <>
- }
-}
-```
-
-Copy and paste the two named rules by replacing existing rule clauses in `example_bucket.guard`. When done, run the validation again:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard
-:::
-
-You should then get an output similar to the following, where instead of `default` rule occurrences you have seen earlier, you should now see names you assigned to `rule validate_bucket_sse_example` and `validate_bucket_versioning_example` rules you decoupled:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-example_bucket.yaml Status = PASS
-PASS rules
-example_bucket.guard/validate_bucket_sse_example PASS
-example_bucket.guard/validate_bucket_versioning_example PASS
----
-Evaluation of rules example_bucket.guard against data example_bucket.yaml
---
-Rule [example_bucket.guard/validate_bucket_sse_example] is compliant for template [example_bucket.yaml]
-Rule [example_bucket.guard/validate_bucket_versioning_example] is compliant for template [example_bucket.yaml]
---
-:::
-
-::alert[If your input data does not contain target selections (in the previous example, if you did not describe Amazon S3 buckets in your template): if you use the `when` keyword as shown earlier (`when %my_buckets !empty`), the rule evaluation will be skipped and marked as `SKIP` in the resulting Guard output. If you, instead, omit the `when` keyword and the `%my_buckets !empty` portion as shown earlier, the rule will fail due to a retrieval error. For more information on clauses, queries, operators, see [Writing AWS CloudFormation Guard rules](https://docs.aws.amazon.com/cfn-guard/latest/ug/writing-rules.html).]{type="info"}
-
-Congratulations! You have decoupled initial rule clauses into two separate named rules, thus favoring modularity and reusability! You also now have examples of smaller code portions to write, consume, and troubleshoot as needed.
-
-
-#### Rule correlation
-
-Depending on your use cases or business logic implementation needs, you have the option to reference a named rule from within another rule. Let's recall the previous example: append, to the `example_bucket.guard` file, the following content:
-
-```json
-rule correlation_example when %my_buckets !empty {
- validate_bucket_sse_example
- validate_bucket_versioning_example
-}
-```
-
-The `correlation_example` example rule references the two other named rules you described in the same file earlier: both named rules must be satisfied for `correlation_example` to pass. Run validation again:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard
-:::
-
-You should get an output similar to the following excerpt:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-example_bucket.yaml Status = PASS
-PASS rules
-example_bucket.guard/validate_bucket_sse_example PASS
-example_bucket.guard/validate_bucket_versioning_example PASS
-example_bucket.guard/correlation_example PASS
-[...]
-:::
-
-If the `validate_bucket_sse_example` rule and/or the `validate_bucket_versioning_example` rule fail(s), the `correlation_example` rule will also fail.
-
-Congratulations! You have learned how to correlate and reference named rules!
-
-
-#### Write your first Guard rule test
-
-Guard gives you the ability to write tests for your rules, to validate that your rules work as you expect. This aspect also opens up the opportunity to leverage the [test-driven development](https://en.wikipedia.org/wiki/Test-driven_development) (TDD) practice in your workflow, where you start with writing tests for your rules first, and you write and run test for your rules next.
-
-Let's get started! Open the `example_bucket_tests.yaml` file with your favorite text editor, and append the following content that contains tests for named rules you used earlier:
-
-```yaml
-- input:
- Resources:
- MyExampleBucket:
- Type: AWS::S3::Bucket
- Properties:
- BucketEncryption:
- ServerSideEncryptionConfiguration:
- - ServerSideEncryptionByDefault:
- SSEAlgorithm: AES256
- expectations:
- rules:
- validate_bucket_sse_example: PASS
-
-- input:
- Resources:
- MyExampleBucket:
- Type: AWS::S3::Bucket
- Properties:
- VersioningConfiguration:
- Status: Suspended
- expectations:
- rules:
- validate_bucket_versioning_example: FAIL
-```
-
-When you look at the example test content just shown, you note that tests contain two `input` sections, one for each test case in this example:
-* with the first test case, you test that the server-side encryption validation logic of your `validate_bucket_sse_example` rule validation will pass when provided with expected test input, that in your example uses `AES256` for the `SSEAlgorithm` property underneath `BucketEncryption`;
-* with the second test case, you expect the `validate_bucket_versioning_example` rule validation will fail when providing `Suspended` (instead of `Enabled`) for the `VersioningConfiguration` `Status`.
-
-Let's run tests! Choose to use the `test` Guard subcommand, followed by `-t` (or `--test-data`) to specify your test file, and `-r` (or `--rules-file`) to specify the file containing your rules to put under test:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard test -t example_bucket_tests.yaml -r example_bucket.guard
-:::
-
-You should get an output similar to the one following next, depicting both example test cases and the outcome you expect:
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-Test Case #1
- No Test expectation was set for Rule validate_bucket_versioning_example
- No Test expectation was set for Rule correlation_example
- PASS Rules:
- validate_bucket_sse_example: Expected = PASS, Evaluated = PASS
-
-Test Case #2
- No Test expectation was set for Rule validate_bucket_sse_example
- No Test expectation was set for Rule correlation_example
- PASS Rules:
- validate_bucket_versioning_example: Expected = FAIL, Evaluated = FAIL
-:::
-
-Congratulations! You have written and ran your first tests for your Guard rules!
-
-
-### Challenge
-
-In this example, you want to configure your [Amazon S3 bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html) with all [properties](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html#aws-resource-s3-bucket-properties) underneath `PublicAccessBlockConfiguration` set to `true` (Boolean).
-
-Your tasks are:
-1. Append, to the `example_bucket_tests.yaml` unit test file content, a new `input` section to validate that a new rule you will create, called `validate_bucket_public_access_block_example`, is expected to pass when you provide test input data containing all `PublicAccessBlockConfiguration` properties set to `true`.
-2. Implement the `validate_bucket_public_access_block_example` rule in the `example_bucket.guard` file. Add a custom message after each clause you will write, in the rule, for each one of the `PublicAccessBlockConfiguration` properties;
-3. Run Guard with the `test` subcommand to run your tests. You should see a Test Case #3 section in the unit tests output, with a line such as: `validate_bucket_public_access_block_example: Expected = PASS, Evaluated = PASS` to indicate unit tests for the new rule succeeded.
-3. Update the `example_bucket.yaml` template, and add the relevant `PublicAccessBlockConfiguration` configuration.
-4. Run Guard with the `validate` subcommand to validate the `example_bucket.yaml` file content against rules you wrote in the `example_bucket.guard` file. You should see a line such as `example_bucket.guard/validate_bucket_public_access_block_example PASS` in the resulting output to indicate validation against your new rule succeeded.
-
-
-:::expand{header="Need a hint?"}
-* Navigate to the `PublicAccessBlockConfiguration` property documentation [page](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html) to determine names of properties underneath it;
-* follow the same rule structure for the `VersioningConfiguration.Status` clause; for rule clauses you will write for each of the `PublicAccessBlockConfiguration` [properties](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html), use a boolean value for `true` instead of a string.
-:::
-
-
-::::expand{header="Want to see the solution?"}
-Note: content shown next is also available in relevant files located in the `code/solutions/policy-as-code-with-guard` directory.
-
-* Append this content to the `example_bucket_tests.yaml` unit test file:
-
-```yaml
-- input:
- Resources:
- MyExampleBucket:
- Type: AWS::S3::Bucket
- Properties:
- PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
- expectations:
- rules:
- validate_bucket_public_access_block_example: PASS
-```
-
-
-* Append this content to the `example_bucket.guard` file:
-
-```json
-rule validate_bucket_public_access_block_example when %my_buckets !empty {
- %my_buckets.Properties {
- PublicAccessBlockConfiguration.BlockPublicAcls == true
- <>
-
- PublicAccessBlockConfiguration.BlockPublicPolicy == true
- <>
-
- PublicAccessBlockConfiguration.IgnorePublicAcls == true
- <>
-
- PublicAccessBlockConfiguration.RestrictPublicBuckets == true
- <>
- }
-}
-```
-
-
-* Run unit tests, and make sure they pass:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard test -t example_bucket_tests.yaml -r example_bucket.guard
-:::
-
-
-* Append this content to the `example_bucket.yaml` template:
-
-```yaml
-PublicAccessBlockConfiguration:
- BlockPublicAcls: true
- BlockPublicPolicy: true
- IgnorePublicAcls: true
- RestrictPublicBuckets: true
-```
-
-
-* Validate your template data against your rules, and make sure all rules pass the validation:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cfn-guard validate -d example_bucket.yaml -r example_bucket.guard
-:::
-::::
-
-
----
-### Conclusion
-
-Great work! You have learned the basics of writing and testing Guard rules! To learn more about Guard, see the [documentation](https://docs.aws.amazon.com/cfn-guard/latest/ug/what-is-guard.html), as well as the [Guard repository](https://github.com/aws-cloudformation/cloudformation-guard) for content that include FAQs and examples.
diff --git a/content/intermediate/templates/resource-dependencies/index.ja.md b/content/intermediate/templates/resource-dependencies/index.ja.md
deleted file mode 100644
index f84615ca5..000000000
--- a/content/intermediate/templates/resource-dependencies/index.ja.md
+++ /dev/null
@@ -1,335 +0,0 @@
----
-title: "リソース依存関係"
-weight: 200
----
-
-_ラボ実施時間 : 15分程度_
-
----
-
-### 概要
-
-[AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/) を使用して、テンプレートに記述したリソースをプログラム的にプロビジョニングする際、あるリソースが 1 つ以上のリソースに依存する場合があります。例えば、[Amazon Elastic Compute Cloud](https://aws.amazon.com/jp/ec2/) (Amazon EC2) インスタンスは、Amazon EC2 インスタンスに使用するセキュリティグループに依存します。CloudFormation スタックにおいて、EC2 がセキュリティグループを参照するように記述することで、最初にセキュリティグループが作成され、次に Amazon EC2 インスタンスが作成されます。
-
-テンプレートで定義したリソース間に依存関係がない場合、CloudFormation はすべてのリソースの作成を並行して開始します。リソースの作成順序を定義、もしくは、[必須](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html#gatewayattachment)である場合、CloudFormation は、一部のリソースを他のリソースよりも先に作成します。
-
-このラボでは、`DependsOn` [属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html)を使用して、リソースの作成順序を明示的に定義する方法を学びます。また、`Ref` と `Fn::GetAtt` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)を使用して、依存関係が確立されている場合に、CloudFormation に作成順序を処理させる方法も学びます。
-
-### 対象トピック
-
-このラボを修了すると、次のことができるようになります。
-
-* `DependsOn` [リソース属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html)の使い方を理解して、リソースの作成順序を明示的に定義
-* `Ref` と `Fn::GetAtt` [組み込み関数](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)を使用して、リソース間の依存関係を作成
-
-### ラボを開始
-
-#### ラボ 1
-
-* `code/workspace/resource-dependencies` ディレクトリに移動します。
-* `resource-dependencies-without-dependson.yaml` ファイルを開きます。
-* ラボの手順に従ってテンプレートの内容を更新します。
-
-ラボ 1 では、次のことを学習します。
-
-* 依存関係が定義されていない場合に CloudFormation のリソース作成順序の処理
-* リソースの作成順序を明示的に定義する方法
-
-
-リソース間に依存関係がない場合に、CloudFormation がリソースの作成順序をどのように処理するかを見てみましょう。
-
-次に示すテンプレートの抜粋にある 2 つのリソースに注目してください。1 つは [Amazon Simple Storage Service](https://aws.amazon.com/jp/s3/) (Amazon S3) [Buket](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html)、もう 1 つは [Amazon Simple Notification Service](https://aws.amazon.com/jp/sns/) (Amazon SNS) [Topic](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sns-topic.html) です。両方のリソースには、相互に依存関係が定義されていません。
-
-::alert[次の例には、Amazon S3 バケットのための `BucketName` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-properties)と Amazon SNS トピックのための `TopicName` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sns-topic.html#aws-resource-sns-topic-properties)は含まれていません。どちらの場合も、CloudFormation は指定されたリソースに一意の名前を生成します。]{type="info"}
-
-`resource-dependencies-without-dependson.yaml` ファイルに、以下のコンテンツをコピーし追加します。次に、スタックを作成し、スタックイベントを確認してリソースが作成される順序を確認します。
-
-```yaml
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-
- SNSTopic:
- Type: AWS::SNS::Topic
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-```
-
-AWS CloudFormation コンソールにて、`resource-dependencies-without-dependson.yaml` を使用し、[スタックを作成](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-create-stack.html)します。
-
-:::::tabs{variant="container"}
-
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/resource-dependencies` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/resource-dependencies
-:::
-1. AWS CLI を使用してスタックを作成します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-resource-dependencies \
---template-body file://resource-dependencies-without-dependson.yaml
-:::
-1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-dependencies/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
- 1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。
-::::
-
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. **スタックの作成** 、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレート準備完了** オプションを選択します。 **テンプレートの指定** セクションで、 **テンプレートファイルのアップロード** を選択します。`resource-dependencies-without-dependson.yaml` テンプレートをアップロードし、 **次へ** をクリックします。
-1. スタック名を入力します。例えば、`resource-dependencies-lab` と入力します。準備ができたら、 **次へ** をクリックします。
-1. **スタックオプションの設定** ページはデフォルト値のまま、ページの一番下までスクロールして **次へ** をクリックします。
-1. **レビュー** ページを一番下までスクロールして **送信** をクリックします。
-::::
-:::::
-
-スタックの `CREATE_COMPLETE` ステータスが表示されるまでページを更新します。それでは、スタックイベントを確認しましょう。次に示す画像のようになるはずです。
-
-
-
-スタックイベントを見ると、`SNSTopic` リソースと `S3Bucket` リソースの作成が同時に開始されたことがわかります。2 つのリソース間には依存関係がないため、CloudFormation は両方のリソースの作成を並行して開始しました。
-
-ここで、最初に Amazon S3 バケットを作成し、バケットが正常に作成されて初めて Amazon SNS トピックの作成を開始するシナリオを考えてみましょう。シナリオを実現するために、`DependsOn` 属性の使用が役立ちます。`DependsOn` を使用して `SNStopic` リソースの依存関係を明示的に定義し、`DependsOn` 属性の値として Amazon S3 バケットリソースの論理 ID (例では、`S3Bucket` を指定) を使用します。`DependsOn` を利用すると、CloudFormation は S3 バケットの作成が完了するのを待ってから、トピックの作成を開始します。それでは、見てみましょう!
-
-* `code/workspace/resource-dependencies` ディレクトリにいることを確認します。
-* `resource-dependencies-with-dependson.yaml` ファイルを開きます。
-* ラボの手順に従ってテンプレートの内容を更新します。
-
-次に示すテンプレートをコピーして、`resource-dependencies-with-dependson.yaml` ファイルに貼り付けます。次のステップでは、スタックを作成してスタックイベントを確認します。
-
-```yaml
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-
- SNSTopic:
- Type: AWS::SNS::Topic
- DependsOn: S3Bucket
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-```
-
-
-上記と同じ手順に従って、`resource-dependencies-with-dependson.yaml` テンプレートファイルを使用して新しいスタックを作成します。その際、別のスタック名 (例: `cfn-workshop-resource-dependencies-dependson`) を指定し、スタックを作成します。
-
-前回とは、スタックイベントが違って見えるはずです。
-
-
-
-次に、新しいスタックのスタックイベントを確認しましょう。テンプレートで説明されている Amazon SNS トピックに `DependsOn` 属性を追加し、その属性の値として Amazon S3 バケットの論理 ID を指定しました。その結果、CloudFormation は、最初に `S3Bucket` リソースを作成し、次に `SNSTopic` リソースを作成しました。スタックを削除する場合、最初に作成されたリソースが最後に削除されることに注目してください。
-
-::alert[`DependsOn` 属性には文字列または文字列のリストを指定できます。 詳細については、[DependsOn 属性](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html)を参照してください。]{type="info"}
-
-おめでとうございます! これで、`DependsOn` 属性を使用してリソースの作成順序を明示的に定義する方法を学習しました。
-
-
-#### ラボ 2
-
-このラボでは、別のリソースの戻り値を参照するリソースプロパティを記述するときに、CloudFormation がリソースの依存関係をどのように処理するかを学びます。リソースの戻り値は、ユースケースに応じて `Ref` や `Fn::GetAtt` などの組み込み関数を使用して参照します。例えば、Amazon SNS [Topic](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sns-topic.html#aws-resource-sns-topic-return-values) と Amazon S3 [Bucket](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-return-values) で使用可能な戻り値を確認できます。
-
-スタックを作成して、実際のリソース作成順序を見てみましょう。
-
-* `code/workspace/resource-dependencies` ディレクトリにいることを確認します。
-* `resource-dependencies-with-intrinsic-functions.yaml` ファイルを開きます。
-* ラボの手順に従ってテンプレートの内容を更新します。
-
-`resource-dependencies-with-intrinsic-functions.yaml` ファイルに、サンプルテンプレートをコピーして追加します。
-
-```yaml
-Parameters:
- EmailAddress:
- Description: Enter an email address to subscribe to your Amazon SNS topic.
- Type: String
-
-Resources:
- SNSTopic:
- Type: AWS::SNS::Topic
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-
- SNSTopicSubscription:
- Type: AWS::SNS::Subscription
- Properties:
- Endpoint: !Ref EmailAddress
- Protocol: email
- TopicArn: !Ref SNSTopic
-
- SecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Workshop Security Group
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-
- SecurityGroupIngress:
- Type: AWS::EC2::SecurityGroupIngress
- Properties:
- GroupId: !GetAtt SecurityGroup.GroupId
- IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
-```
-
-
-テンプレートに貼り付けたテンプレートスニペットには、Amazon SNS [Topic](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sns-topic.html)、Amazon SNS [Topic Subscription](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic-subscription.html)、Amazon EC2 [SecurityGroup](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html)、[SecurityGroup Ingress](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-rule-1.html) の 4 つのリソースがあります。次の点にご注目ください。
-
-* Topic リソースの論理 ID である `SNSTopic` は、`SNSTopicSubscription` リソースの `TopicArn` プロパティの `Ref` で参照されます。`TopicArn` プロパティには、サブスクライブする Topic の [Amazon Resource Name](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-arns-and-namespaces.html) (ARN) が必要です。`AWS::SNS::Topic` リソースタイプは、`Ref` 組み込み関数を使用するときに Topic の ARN を返します。詳細については、Amazon SNS Topic [戻り値](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sns-topic.html#aws-resource-sns-topic-return-values)をご参照ください。つまり、CloudFormation は SNSTopic の作成を開始する前に `SNSTopicSubscription` の作成が完了するのを待ちます。
-* セキュリティグループリソース `SecurityGroup` の論理 ID は、`SecurityGroupIngress` リソースの `Fn::GetAtt` で参照されます。ここでの目的は、`SecurityGroupIngress` リソースの `GroupId` プロパティに `SecurityGroup` リソースの ID を指定することです。`AWS::EC2::SecurityGroup` リソースタイプは、`Fn::GetAtt` 組み込み関数を使用して `GroupID` 属性を `Fn::GetAtt` に渡すと、セキュリティグループの ID を返します。代わりに `Ref` 関数はリソース ID を返すか、EC2-Classic やデフォルト VPC の場合はリソース名を返します。詳細については、[EC2 セキュリティグループの戻り値](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html#aws-properties-ec2-security-group-return-values)をご参照ください。
-* `SecurityGroup` リソースが `CREATE_COMPLETE` ステータスになると、`SecurityGroupIngress` の作成が開始されます。同様に、`SNSTopicSubscription` リソースの作成が開始されます。
-* `SNSTopic` と `SecurityGroup` リソースの間には依存関係がないことにご注目ください。つまり、CloudFormation は両方のリソースの作成を並行して開始します。
-
-スタックを作成して、上記の動作を確認してみましょう。AWS CloudFormation コンソールにて、`resource-dependency-with-intrinsic-functions.yaml` を使用し、[スタックを作成](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-console-create-stack.html)します。
-
-:::::tabs{variant="container"}
-
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/resource-dependencies` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/resource-dependencies
-:::
-1. AWS CLI を使用してスタックを作成します。必須パラメータ `--stack-name` と `--template-body` はあらかじめ入力されています。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-resource-dependencies-ref-getatt \
---template-body file://resource-dependencies-with-intrinsic-functions.yaml \
---parameters ParameterKey="EmailAddress",ParameterValue="your-email-address-here"
-
-:::
-1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-dependencies-ref-getatt/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。
-::::
-
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. **スタックの作成** 、 **新しいリソースを使用 (標準)** を選択します。
-1. **テンプレート準備完了** オプションを選択します。 **テンプレートを指定** セクションで、 **テンプレートファイルのアップロード** を選択します。`resource-dependencies-with-intrinsic-functions.yaml` テンプレートをアップロードし、 **次へ** をクリックします。
-1. スタック名を入力します。例えば、`cfn-workshop-resource-dependencies-ref-getatt` と入力します。準備ができたら、 **次へ** をクリックします。
-1. **パラメータ** セクションで、Amazon SNS トピックサブスクリプションのメールアドレスを入力します。準備ができたら、 **次へ** をクリックします。
-1. **スタックオプションの設定** ページはデフォルト値のまま、ページの一番下までスクロールして **次へ** をクリックします。
-1. **レビュー** ページを一番下までスクロールして **送信** をクリックします。
-::::
-:::::
-
-スタックが作成されると、スタックのイベントは次のようになります。
-
-
-
-`cfn-workshop-resource-dependencies-ref-getatt` スタックのスタックイベントを確認しましょう。`SNSTopic` リソースと `SecurityGroup` リソースの作成は、両方のリソースには相互に依存関係がないことから、並行して開始されます。また、`SecurityGroupIngress` リソースの作成は `SecurityGroup` リソースが `CREATE_COMPLETE` ステータスになった後にのみ開始され、`SNSTopicSubscription` の作成は、`SNSTopic` リソースが正常に作成された後に開始されます。
-
-スタックを削除すると、CloudFormation は作成順序が逆になります。この場合、`SNSTopicSubscription` と `SecurityGroupIngress` リソースが最初に削除され、続いて `SecurityGroup` と `SNSTopic` が削除されます。
-
-::alert[作成した Amazon SNS トピックへのサブスクリプションを確認するための E メールが、指定したメールアドレスに送信されているはずです。作成したトピックについて受信したサブスクリプション確認メールに記載されているサブスクリプションリンクをたどって、トピックを購読します。購読しなかった場合、スタックを削除してもサブスクリプションは保留状態のままになり、削除することはできません。Amazon SNS は未確認のサブスクリプションを 3 日後に自動削除します。詳細については、[Amazon SNS サブスクリプションおよびトピックを削除する](https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-delete-subscription-topic.html)をご参照ください。]{type="info"}
-
-おめでとうございます!これで、`Ref` または `Fn::GetAtt` を使用してリソースの依存関係を定義するときに、CloudFormation がリソースの作成順序をどのように処理するかについて学習しました。
-
-
-### チャレンジ
-
-このセクションでは、Amazon EC2 [インスタンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#aws-properties-ec2-instance-properties)、[セキュリティグループ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html#aws-properties-ec2-security-group-properties)、Amazon S3 [バケット](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-properties)を記述した既存のサンプルテンプレートを更新する作業を行います。Amazon EC2 インスタンスリソースの `SecurityGroups` プロパティでセキュリティグループの論理 ID を参照する必要があります。また、Amazon EC2 インスタンスリソースが正常に作成された後にのみ、CloudFormation が Amazon S3 バケットリソースの作成を開始するようにします。上記の要件例に従ってテンプレートを正しく設計すれば、スタックイベントが次のようになることを確認できるはずです。
-
-* CloudFormation はセキュリティグループリソースの作成を開始します。
-* セキュリティグループが `CREATE_COMPLETE` としてマークされると、Amazon EC2 インスタンスリソースの作成が開始されます。
-* Amazon EC2 インスタンスが正常に作成されると、CloudFormation は Amazon S3 バケットの作成を開始します。
-
-はじめに、`code/workspace/resource-dependencies` ディレクトリにある `resource-dependencies-challenge.yaml` テンプレートを、お好みのコードエディターで開きます。上記の要件例に従い、必要に応じてリソースの依存関係を確立します。準備ができたら、`cfn-workshop-resource-dependencies-challenge` という名前の新しいスタックを作成し、スタックイベントが、学んできた一連の流れと一致することを確認します。
-
-:::expand{header="ヒントが必要ですか?"}
-* Amazon EC2 インスタンスの `SecurityGroups` [プロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html#aws-properties-ec2-security-group-properties)で、セキュリティグループを[参照](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)する方法を確認してください。
-* セキュリティグループを参照するときは、`SecurityGroups` プロパティの値の `Type` が _List of String_ であることにも注意してください。この値を YAML 形式でどのように表現しますか?
-* リソースの作成は別のリソースに従うべきだと[指定](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html)するにはどうすればよいでしょうか。
-:::
-
-::::::expand{header="解決策を確認しますか?"}
-* `Ref` 組み込み関数を使用して、セキュリティグループの論理 ID を `SecurityGroups` EC2 インスタンスリソースプロパティのリスト項目として参照します。その後、CloudFormation は最初にセキュリティグループが作成されるのを待ってから、Amazon EC2 インスタンスの作成を開始する必要があります。
-* Amazon EC2 インスタンスリソース定義を次に示すように変更します。
-
-```yaml
-Ec2Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- SecurityGroups:
- - !Ref InstanceSecurityGroup
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-```
-
-* Amazon EC2 インスタンスと Amazon S3 バケットリソースの間には依存関係がないため、Amazon S3 バケットリソースの `DependsOn` 属性を使用し、Amazon EC2 インスタンスの論理 ID を `DependsOn` 属性の値として指定します。
-* 次に示すように、Amazon S3 バケットリソースの `DependsOn` 属性を追加します。
-
-```yaml
-S3Bucket:
- Type: AWS::S3::Bucket
- DependsOn: Ec2Instance
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-```
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. **Code Editor ターミナル** で `code/workspace/resource-dependencies` ディレクトリに移動します。
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/resource-dependencies
-:::
-1. AWS CLI を使用してスタックを作成します。必須パラメータ `--template-body` はあらかじめ入力されています。
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack --stack-name cfn-workshop-resource-dependencies-challenge \
- --template-body file://resource-dependencies-challenge.yaml
-:::
-1. `create-stack` コマンドが成功すると、CloudFormation は `StackId` を返却します。
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-dependencies-ref-getatt/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** コンソールを新しいタブで開き、スタックのステータスが **CREATE_COMPLETE** になっているかどうかを確認します。
-::::
-::::tab{id="local" label="ローカル開発"}
-1. [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/) に移動します。
-1. **スタックの作成** から、 **新規リソースを使用(標準)** を選択します。
-1. **テンプレートの準備完了** オプションを選択します。 **テンプレートを指定** から、 **テンプレートファイルをアップロード** を選択します。`resource-dependencies-challenge.yaml` テンプレートをアップロードし、 **次へ** を選択します。
-1. スタック名を入力します。たとえば、 `cfn-workshop-resource-dependencies-challenge` と入力し、 **次へ** を選択します。
-1. **スタックオプションの設定** ページでデフォルト値をそのまま使用することを選択し、ページの一番下までスクロールして、 **次へ** を選択します。
-1. レビューページの一番下までスクロールし、 **送信** を選択します。
-::::
-:::::
-::::::
-
-この課題の解決策は、`code/solutions/resource-dependencies/resource-dependencies-challenge.yaml` テンプレートの中にあります。
-
-### クリーンアップ
-
-以下の手順に従って、このラボで作成した[スタックを削除](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html)します。
-
-1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)に移動します。
-1. CloudFormation コンソールのスタックページで、`cfn-workshop-resource-dependencies` スタックを選択します。
-1. スタックの詳細ペインで、 **削除** を選択した後、 **スタックの削除** を押して確定します。
-1. 上記の手順を繰り返して、作成した他のスタック `cfn-workshop-resource-dependencies-dependson`、`cfn-workshop-resource-dependencies-ref-getatt`、`cfn-workshop-resource-dependencies-challenge` を削除します。
-
----
-### まとめ
-
-`Ref` と `Fn::GetAtt` 組み込み関数を使用してリソースの依存関係を定義する方法と、`DependsOn` 属性を使用してリソースの依存関係を明示的に定義する方法を学びました。
diff --git a/content/intermediate/templates/resource-dependencies/index.md b/content/intermediate/templates/resource-dependencies/index.md
deleted file mode 100644
index af1e38021..000000000
--- a/content/intermediate/templates/resource-dependencies/index.md
+++ /dev/null
@@ -1,337 +0,0 @@
----
-title: "Resource Dependencies"
-weight: 200
----
-
-_Lab Duration: ~15 minutes_
-
----
-
-### Overview
-
-You use [AWS CloudFormation](https://aws.amazon.com/cloudformation/) to programmatically provision resources you describe in your templates. There are cases where a resource depends on one or more resources; for example, an [Amazon Elastic Compute Cloud](https://aws.amazon.com/ec2/) (Amazon EC2) instance depends on a Security Group that you wish to use for your Amazon EC2 instance: you describe both resources in a way that you reference the Security Group in the EC2 instance, so that your CloudFormation stack creates the Security Group first, and your Amazon EC2 instance next.
-
-If there are no dependencies between resources you define in a template, CloudFormation initiates the creation of all resources in parallel. There are cases where you either want to, or are [required](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html#gatewayattachment) to define the order in which resources will be created: in these cases, CloudFormation creates some resources before other ones.
-
-In this lab, you will learn how to use the `DependsOn` [attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html) to explicitly define resource creation order. You will also learn how to use `Ref` and `Fn::GetAtt` [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html) to have CloudFormation handle the creation order when there are dependencies established.
-
-### Topics Covered
-
-By the end of this lab, you will be able to:
-
-* Understand the usage of the `DependsOn` [resource attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html) to explicitly define resource creation order.
-* Use `Ref` and `Fn::GetAtt` [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html) to create dependencies between resources.
-
-### Start Lab
-
-#### Lab 1
-
-* Change directory to `code/workspace/resource-dependencies`.
-* Open the `resource-dependencies-without-dependson.yaml` file.
-* Update the content of the template as you follow along steps on this lab.
-
-In this part of the lab, you will:
-
-* Learn how CloudFormation handles resource creation order when no dependencies are defined.
-* Learn how you can explicitly define resource creation order.
-
-
-Let’s now see how CloudFormation handles the resource creation order when there are no dependencies between resources.
-
-Note the two resources in the template excerpt shown next: an [Amazon Simple Storage Service](https://aws.amazon.com/s3/) (Amazon S3) [bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html), and an [Amazon Simple Notification Service](https://aws.amazon.com/sns/) (Amazon SNS) [topic](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html). Both resources have no dependencies defined between each other.
-
-::alert[The example shown next does not include the `BucketName` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html#cfn-s3-bucket-bucketname) for the Amazon S3 bucket, and the `TopicName` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html#cfn-sns-topic-topicname) for the Amazon SNS topic. In both cases, CloudFormation will generate a unique name for the given resource.]{type="info"}
-
-Copy and append the example content shown next to the `resource-dependencies-without-dependson.yaml` file. Next, you will create a stack, and review stack events to see in which order resources will be created.
-
-```yaml
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-
- SNSTopic:
- Type: AWS::SNS::Topic
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-```
-
-Use the AWS CloudFormation Console to [create a stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-create-stack.html) using the `resource-dependencies-without-dependson.yaml` template:
-
-:::::tabs{variant="container"}
-
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/resource-dependencies`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/resource-dependencies
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-resource-dependencies \
---template-body file://resource-dependencies-without-dependson.yaml
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-dependencies/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
- 1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-2. From **Create stack**, choose **With new resources (standard)**.
-3. Choose the **Template is ready** option. From **Specify template**, choose **Upload a template file**. Upload the `resource-dependencies-without-dependson.yaml` template, and choose **Next**.
-4. Enter a stack name. For example, specify `cfn-workshop-resource-dependencies`. When ready, choose **Next**.
-5. Choose to accept default values on the **Configure stack options** page; scroll to the bottom of the page, and choose **Next**.
-6. In the **Review** page, scroll to the bottom and choose **Submit**.
-::::
-:::::
-
-Refresh the page until you see the `CREATE_COMPLETE` status for your stack. Now, let’s review stack events, that should look similar to the image shown next:
-
-
-
-Looking at stack events, you can see the creation of the `SNSTopic` and `S3Bucket` resources was initiated at the same time. Since there are no dependencies between the two resources, CloudFormation initiated the creation of both resources in parallel.
-
-Now, think of an example scenario where you want your Amazon S3 bucket to be created first, and only after the bucket is successfully created, the creation of your Amazon SNS topic should start. This is where the use of the `DependsOn` attribute comes into play: you use `DependsOn` to explicitly define a dependency in the `SNSTopic` resource, and provide the logical ID of your Amazon S3 bucket resource (i.e., `S3Bucket` in the example above) as a value for the `DependsOn` attribute. In doing so, CloudFormation will wait for the S3 bucket creation to be completed before initiating the creation of the topic. Let’s take a look!
-
-* Make sure you are in the directory: `code/workspace/resource-dependencies`.
-* Open the `resource-dependencies-with-dependson.yaml` file.
-* Update the content of the template as you follow along steps on this lab.
-
-Copy and paste the template snippet shown next in the `resource-dependencies-with-dependson.yaml` file; in the next step, you will create a stack and review stack events:
-
-```yaml
-Resources:
- S3Bucket:
- Type: AWS::S3::Bucket
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-
- SNSTopic:
- Type: AWS::SNS::Topic
- DependsOn: S3Bucket
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-```
-
-
-Follow the same steps as above to create a new stack using the `resource-dependencies-with-dependson.yaml` template file. Make sure to provide a different stack name, for example `cfn-workshop-resource-dependencies-dependson`, and create the stack.
-
-This time, your stack events should look different:
-
-
-
-Now, let’s review the stack events for your new stack. You added the `DependsOn` attribute to the Amazon SNS topic described in the template, and specified the logical ID of the Amazon S3 bucket as a value for the attribute. This resulted in CloudFormation creating the `S3Bucket` resource first, and the `SNSTopic` resource next. Note that when you will delete the stack, the resource that was created first will be the last one to be deleted.
-
-::alert[You can specify a string or a list of strings to the `DependsOn` attribute. For more information, see [DependsOn attribute](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html).]{type="info"}
-
-Congratulations! You have now learned how to explicitly define resource creation order using the `DependsOn` attribute.
-
-
-#### Lab 2
-
-In this lab, you will learn how CloudFormation handles resource dependencies when you describe a resource property that references the return value of another resource. You reference resource return values with intrinsic functions such as `Ref` and `Fn::GetAtt`, depending on your use case: for example, see which available return values are available for an Amazon SNS [topic](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html#aws-properties-sns-topic-return-values) and for an Amazon S3 [bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html#aws-resource-s3-bucket-return-values).
-
-Let’s create a stack, and see the resource creation order in action!
-
-* Make sure you are in the directory: `code/workspace/resource-dependencies`.
-* Open the `resource-dependencies-with-intrinsic-functions.yaml` file.
-* Update the content of the template as you follow along steps on this lab.
-
-Copy, and append the example template snippet shown next to the `resource-dependencies-with-intrinsic-functions.yaml` file:
-
-```yaml
-Parameters:
- EmailAddress:
- Description: Enter an email address to subscribe to your Amazon SNS topic.
- Type: String
-
-Resources:
- SNSTopic:
- Type: AWS::SNS::Topic
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-
- SNSTopicSubscription:
- Type: AWS::SNS::Subscription
- Properties:
- Endpoint: !Ref EmailAddress
- Protocol: email
- TopicArn: !Ref SNSTopic
-
- SecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Properties:
- GroupDescription: Workshop Security Group
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-
- SecurityGroupIngress:
- Type: AWS::EC2::SecurityGroupIngress
- Properties:
- GroupId: !GetAtt SecurityGroup.GroupId
- IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- CidrIp: 0.0.0.0/0
-```
-
-
-There are four resources in the template snippet you pasted into your template: an Amazon SNS [topic](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html), an Amazon SNS [topic subscription](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html), an Amazon EC2 [Security Group](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html), and a [SecurityGroupIngress](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-ingress.html) resource. Note the following:
-
-* The logical ID of the topic resource, `SNSTopic`, is referenced with `Ref` in the `TopicArn` property of the `SNSTopicSubscription` resource. The `TopicArn` property requires the [Amazon Resource Name](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) (ARN) of the topic to which you want to subscribe: the `AWS::SNS::Topic` resource type returns the ARN of the topic when you use the `Ref` intrinsic function. For more information, see Amazon SNS topic [return values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html#aws-properties-sns-topic-return-values). This implies that CloudFormation waits for the creation of `SNSTopic` to complete before initiating the creation of `SNSTopicSubscription`.
-* The logical ID of the security group resource, `SecurityGroup`, is referenced with `Fn::GetAtt` in the `SecurityGroupIngress` resource: your intent here is to specify the ID of the `SecurityGroup` resource for the `GroupId` property of the `SecurityGroupIngress` resource. The `AWS::EC2::SecurityGroup` resource type returns the ID of the security group when you use the `Fn::GetAtt` intrinsic function and pass the `GroupId` attribute to `Fn::GetAtt`. The `Ref` function, instead, returns either the resource ID, or in the case of EC2-Classic or default VPC, the resource name. For more information, see [EC2 Security Group return values](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html#aws-properties-ec2-security-group-return-values).
-* Once the `SecurityGroup` resource is in the `CREATE_COMPLETE` status, the creation of `SecurityGroupIngress` will start. Similarly, after the creation of `SNSTopic`, the `SNSTopicSubscription` resource creation will be initiated.
-* Note that there are no dependencies between `SNSTopic` and `SecurityGroup` resources: this means that CloudFormation initiates the creation of both these resources in parallel.
-
-Let’s create a stack, and verify the above behavior. Use the AWS CloudFormation Console to [create a stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-create-stack.html) using the `resource-dependency-with-intrinsic-functions.yaml` template:
-
-:::::tabs{variant="container"}
-
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/resource-dependencies`:
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-cd cfn101-workshop/code/workspace/resource-dependencies
-:::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you.
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws cloudformation create-stack --stack-name cfn-workshop-resource-dependencies-ref-getatt \
---template-body file://resource-dependencies-with-intrinsic-functions.yaml \
---parameters ParameterKey="EmailAddress",ParameterValue="your-email-address-here"
-
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-dependencies-ref-getatt/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-2. From **Create stack**, choose **With new resources (standard)**.
-3. Choose the **Template is ready** option. From **Specify template**, choose **Upload a template file**. Upload the `resource-dependencies-with-intrinsic-functions.yaml` template, and choose **Next**.
-4. Enter a stack name. For example, `cfn-workshop-resource-dependencies-ref-getatt`.
-5. In the **Parameters** section, provide an email address for Amazon SNS topic subscription; when ready, choose **Next**.
-6. Choose to accept default values on the **Configure stack options** page; scroll to the bottom of the page, and choose **Next**.
-7. In the review page, scroll to the bottom and choose **Submit**.
-::::
-:::::
-
-
-Once the stack is created, your stack events should look like the following:
-
-
-
-Let’s review stack events for your `resource-dependencies-lab-ref-getatt` stack. Note the creation of `SNSTopic` and `SecurityGroup` resources started in parallel, as both resources had no dependencies between each other. Also, note the `SecurityGroupIngress` resource creation started only after the `SecurityGroup` resource was in the `CREATE_COMPLETE` status, and the `SNSTopicSubscription` creation started after the `SNSTopic` resource was successfully created.
-
-When you will delete your stack, CloudFormation follows creation order in reverse: in this case, for example, `SNSTopicSubscription` and `SecurityGroupIngress` resources will be deleted first, followed by `SecurityGroup` and `SNSTopic`.
-
-::alert[You should have received an email, sent to the email address you provided, for you to confirm the subscription to the Amazon SNS topic you created. Choose to follow the subscription link in the subscription confirmation email you received for the topic you created, to subscribe to your topic. Otherwise, when you delete the stack, the subscription will be left in pending state, and you cannot delete it: Amazon SNS will automatically delete the unconfirmed subscription after 3 days. For more information, see [Deleting an Amazon SNS subscription and topic](https://docs.aws.amazon.com/sns/latest/dg/sns-delete-subscription-topic.html).]{type="info"}
-
-Congratulations! You have now learned how CloudFormation handles the resource creation order when you define resource dependencies with `Ref` or `Fn::GetAtt`.
-
-
-### Challenge
-
-In this section of the lab, you are tasked with updating an existing, example template that describes an Amazon EC2 [instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html), a [security group](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html), and an Amazon S3 [bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-bucket.html). You will need to reference the security group's logical ID in the `SecurityGroups` property of the Amazon EC2 instance resource. Also, choose to have CloudFormation initiate the Amazon S3 bucket resource creation only after the Amazon EC2 instance resource is created successfully. If you design the template correctly, as per example requirements above, you should be able to observe stack events to be as follows:
-
-* CloudFormation starts the creation of the Security Group resource.
-* Once your Security Group is marked as `CREATE_COMPLETE`, the Amazon EC2 instance resource creation starts.
-* After successful creation of your Amazon EC2 instance, CloudFormation starts the creation of your Amazon S3 bucket.
-
-To get started, open the `resource-dependencies-challenge.yaml` template, that you can find in the `code/workspace/resource-dependencies` directory, with your favorite code editor. Follow example requirements above, and establish resource dependencies where needed. When ready, create a new stack, called `resource-dependencies-challenge`, and verify stack events match the series described above.
-
-:::expand{header="Need a hint?"}
-* How can you [reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html) your security group in the `SecurityGroups` [property](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-securitygroups) of your Amazon EC2 instance?
-* When you reference your security group, also note that the `Type` of the `SecurityGroups` property value is a _List of String_. How do you represent this value in YAML format?
-* How can you [specify](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html) that the creation of a resource should follow another resource?
-:::
-
-::::::expand{header="Want to see the solution?"}
-* Reference the Security Group's logical ID as a list item under the `SecurityGroups` EC2 instance resource property, by using the `Ref` intrinsic function. CloudFormation should then wait for the Security Group to be created first, and then initiates the Amazon EC2 instance creation.
-* Modify the Amazon EC2 instance resource definition as shown next:
-
-```yaml
-Ec2Instance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !Ref LatestAmiId
- InstanceType: t2.micro
- SecurityGroups:
- - !Ref InstanceSecurityGroup
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-```
-
-* Since there is no dependency between the Amazon EC2 instance and the Amazon S3 bucket resources, use the `DependsOn` attribute in the Amazon S3 bucket resource, and provide the Amazon EC2 instance's logical ID as a value for the `DependsOn` attribute.
-* Add the `DependsOn` attribute for the Amazon S3 bucket resource as shown next:
-
-```yaml
-S3Bucket:
- Type: AWS::S3::Bucket
- DependsOn: Ec2Instance
- Properties:
- Tags:
- - Key: Name
- Value: Resource-dependencies-workshop
-```
-
-:::::tabs{variant="container"}
-::::tab{id="code-editor" label="Code Editor"}
-1. In the **Code Editor terminal** navigate to `code/workspace/resource-dependencies`:
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- cd cfn101-workshop/code/workspace/resource-dependencies
- :::
-1. Use the AWS CLI to create the stack. The required parameter `--template-body` have been pre-filled for you.
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws cloudformation create-stack --stack-name cfn-workshop-resource-dependencies-challenge \
- --template-body file://resource-dependencies-challenge.yaml
-:::
-1. If the `create-stack` command was successfully sent, CloudFormation will return `StackId`.
- :::code{language=shell showLineNumbers=false showCopyAction=false}
- "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/cfn-workshop-resource-dependencies-challenge/739fafa0-e4d7-11ed-a000-12d9009553ff"
-:::
-1. Open the **[AWS CloudFormation](https://console.aws.amazon.com/cloudformation)** console in a new tab and check if the stack status is **CREATE_COMPLETE**.
-::::
-::::tab{id="local" label="Local development"}
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-1. From **Create stack**, choose **With new resources (standard)**.
-1. Choose the **Template is ready** option. From **Specify template**, choose **Upload a template file**. Upload the `resource-dependencies-challenge.yaml` template, and choose **Next**.
-1. Enter a stack name. For example, `cfn-workshop-resource-dependencies-challenge` and choose **Next**.
-1. Choose to accept default values on the **Configure stack options** page; scroll to the bottom of the page, and choose **Next**.
-1. In the review page, scroll to the bottom and choose **Submit**.
-::::
-:::::
-::::::
-
-
-The full solution for this challenge is available in the `code/solutions/resource-dependencies/resource-dependencies-challenge.yaml` template.
-
-### Cleanup
-
-Follow the steps below to [delete the stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html) you created as a part of this lab:
-
-1. Navigate to the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/).
-2. On the **Stacks** page in the CloudFormation console, select the `cfn-workshop-resource-dependencies` stack.
-3. In the stack details pane, choose **Delete** to delete the stack, and then choose **Delete stack** to confirm.
-4. Repeat steps above to delete other stacks you created: `cfn-workshop-resource-dependencies-dependson`, `cfn-workshop-resource-dependencies-ref-getatt`, and `cfn-workshop-resource-dependencies-challenge`.
-
----
-### Conclusion
-
-Great work! You learned how to use `Ref` and `Fn::GetAtt` intrinsic functions to define resource dependencies, as well as the `DependsOn` attribute to explicitly define resource dependencies.
diff --git a/content/introduction/index.ja.md b/content/introduction/index.ja.md
deleted file mode 100644
index 3e44222de..000000000
--- a/content/introduction/index.ja.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: "イントロダクション"
-weight: 10
----
-
-このワークショップはスキルレベル(初級、中級、上級)とフォーカスしたい内容(テンプレート、オペレーション、リソースタイプ開発)により複数のパートに分かれています。
-
-**初級編**では、基礎的な AWS CloudFormation のコンセプトについて紹介します。**中級編**と**上級編**では、CloudFormation のより深い特徴について学習することができます。
-
-**初級編**では以下の内容を学びます。
-+ 開発環境のセットアップ
-+ CloudFormation テンプレートとスタック
-+ 簡単な **[EC2](https://aws.amazon.com/jp/ec2/)** の Web サーバを立ち上げることにより基礎的な CloudFormation のコンセプト
-
-**中級編**では、以下の内容を学びます。
-+ **[ネストされたスタック](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html)** と **[多層スタック](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html)** の作成を通して複数のスタックの管理方法
-+ S3 バケットから _ネストされたスタック_ の **[パッケージ化](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-cli-package.html)** と **[デプロイ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-cli-deploy.html)** 方法
-
-**上級編**では、以下の内容を学びます。
-+ [AWS CloudFormation レジストリ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/registry.html)
-+ [モジュールの作成](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/modules.html) の作成によって CloudFormation を拡張する方法
-+ [リソースタイプの作成](https://docs.aws.amazon.com/ja_jp/cloudformation-cli/latest/userguide/resource-types.html) により CloudFormation を拡張する方法
diff --git a/content/introduction/index.md b/content/introduction/index.md
deleted file mode 100644
index 563aeb1d2..000000000
--- a/content/introduction/index.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-title: "Introduction"
-weight: 10
----
-
-This workshop is split into multiple parts based on the skill level (Basics, Intermediate, Advanced) and focus (Templates, Operations, Resource Types development).
-
-The **Basics** part introduces foundational AWS CloudFormation concepts. In **Intermediate** and **Advanced** sections, you will dive deeper into CloudFormation features.
-
-In the **Basics** part of the workshop, you will:
-
-+ Set up a development environment.
-+ Learn what is CloudFormation template and stack.
-+ Learn about foundational CloudFormation concepts and features by setting up a simple **[EC2](https://aws.amazon.com/ec2/)** Web Server.
-
-In the **Intermediate** part of the workshop, you will:
-
-+ Learn how to manage multiple stacks by creating **[Nested Stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html)**
-and **[Layered Stacks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html)**.
-+ You will learn how to **[Package](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-cli-package.html)**
-and **[Deploy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-cli-deploy.html)** a _Nested Stack_ from an S3 bucket.
-
-In the **Advanced** part of the workshop, you will:
-
-+ Learn about the [AWS CloudFormation registry](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry.html).
-+ Learn how to extend CloudFormation by [creating modules](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/modules.html).
-+ Learn how to extend CloudFormation by [creating resource types](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-types.html).
diff --git a/content/introduction/workshop-duration/index.ja.md b/content/introduction/workshop-duration/index.ja.md
deleted file mode 100644
index ae8326243..000000000
--- a/content/introduction/workshop-duration/index.ja.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-title: "ワークショップ所要時間とコスト"
-weight: 100
----
-
-### ワークショップ所要時間
-
-CloudFormation と開発の経験によりますが、ワークショップの所要時間は以下の通りです。
-
-#### 事前準備
-
-30分から 1時間程度かかります。
-
-#### 初級編/テンプレート
-
-この章はおよそ 1時間かかります。
-
-#### 初級編/運用
-
-この章はおよそ 2時間かかります。
-
-#### 中級編/テンプレート
-
-この章はおよそ 3時間かかります。
-
-#### 上級編/リソースタイプ
-
-この章はおよそ 3時間かかります。
-
-### コスト
-
-このワークショップで利用する CloudFormation テンプレートはカスタマイズ可能なパラメータを持っています。**インスタンスタイプ**のような設定がデプロイメントのコストに影響を与えます。概算コストを試算する場合は、利用する AWS サービスの料金ページをご参照ください。料金が変わる可能性があります。
-
-::alert[ワークショップで利用するサービスのコストは、利用者にご負担いただきます。ワークショップ自体の利用には追加費用がかかりません。]{type="warning"}
diff --git a/content/introduction/workshop-duration/index.md b/content/introduction/workshop-duration/index.md
deleted file mode 100644
index a0d2cc34b..000000000
--- a/content/introduction/workshop-duration/index.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: "Workshop Duration and Cost"
-weight: 100
----
-
-### Workshop Duration
-
-Depending on the level of your experience with CloudFormation and development, the duration of the workshop is:
-
-#### Prerequisites
-
-About 30 minutes to 1 hour.
-
-#### Basics/Templates
-
-This part will take approximately 1 hour.
-
-#### Basics/Operations
-
-This part will take approximately 2 hour.
-
-#### Intermediate/Templates
-
-This part will take approximately 3 hours.
-
-#### Advanced/Resource Types
-
-This part will take approximately 3 hours.
-
-### Cost
-
-The AWS CloudFormation templates in this workshop include configuration parameters that you can customize. Some of
-these settings, such as **instance type**, will affect the cost of deployment. For cost estimates, see the pricing pages
-for each AWS service you will be using. Prices are subject to change.
-
-::alert[You are responsible for the cost of the AWS services used while running this workshop. There is no additional cost for using this workshop.]{type="warning"}
diff --git a/content/next-steps/aws-quick-starts/index.ja.md b/content/next-steps/aws-quick-starts/index.ja.md
deleted file mode 100644
index e9af48800..000000000
--- a/content/next-steps/aws-quick-starts/index.ja.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "AWS パートナーソリューション"
-weight: 10
----
-
-
-
-AWS パートナーソリューションは、AWS クラウド上の主要なワークロードのリファレンスデプロイを自動化したものです。
-各パートナーソリューションは、セキュリティと可用性に関する AWS のベストプラクティスを使用して、特定のワークロードを AWS にデプロイするために必要な、AWS のコンピューティング、ネットワーク、ストレージ、およびその他のサービスを起動、設定、実行します。
-
-パートナーソリューションを利用すると、何百もの手作業による手順を数ステップにまとめることができます。
-これらはカスタマイズ可能で、本番環境で利用可能なように設計されています。
-
-[AWS Partner Solutions FAQs](https://aws.amazon.com/jp/solutions/partners/faq/)
diff --git a/content/next-steps/aws-quick-starts/index.md b/content/next-steps/aws-quick-starts/index.md
deleted file mode 100644
index c06a918f0..000000000
--- a/content/next-steps/aws-quick-starts/index.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "AWS Partner Solutions"
-weight: 10
----
-
-
-
-AWS Partner Solutions are automated reference deployments for key workloads on the AWS Cloud. Each Partner Solution
-launches, configures, and runs the AWS compute, network, storage, and other services required to deploy a specific
-workload on AWS, using AWS best practices for security and availability.
-
-Partner Solutions are accelerators that condense hundreds of manual procedures into just a few steps. They are
-customizable and designed for production.
-
-[AWS Partner Solutions FAQs](https://aws.amazon.com/solutions/partners/faq/)
diff --git a/content/next-steps/index.ja.md b/content/next-steps/index.ja.md
deleted file mode 100644
index aa22aa03d..000000000
--- a/content/next-steps/index.ja.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: "次のステップ"
-weight: 60
----
-
-このセクションでは、テンプレートの例、一般的なアーキテクチャ設計のソリューション、ツールなど、AWS CloudFormation に関連するコンテンツを確認します。
-
-::children
diff --git a/content/next-steps/index.md b/content/next-steps/index.md
deleted file mode 100644
index f71e1f043..000000000
--- a/content/next-steps/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: "Next Steps"
-weight: 60
----
-
-In this section, you can find additional content related to AWS CloudFormation, such as template examples, solutions to common architecture designs, tools, and more...
-
-::children
diff --git a/content/prerequisites/account/index.ja.md b/content/prerequisites/account/index.ja.md
deleted file mode 100644
index 2abb022ed..000000000
--- a/content/prerequisites/account/index.ja.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: "AWS アカウントの作成"
-weight: 100
----
-
-## 検証のために AWS アカウントを作成
-
-アプリケーションをデプロイするために、AWS アカウントへのアクセスが必要です。すでにアカウントをお持ちで、さらに管理者権限を持っているユーザが利用する環境に設定されている場合は、[次のステップ](../cloud9)に移動しても大丈夫です。
-
-:::alert{type="warning"}
-既存の個人アカウントまたは会社のアカウントを利用する場合は、そのアカウントにリソースを作成する場合の影響とポリシーをご確認ください。
-:::
-
-AWS アカウントを持ちでない場合は、[こちらで無料で AWS アカウントを作成](https://portal.aws.amazon.com/billing/signup)できます。
-
-## 管理者ユーザ
-
-1. AWS アカウントにログインします。
-1. AWS IAM コンソールに遷移して、[ユーザを追加](https://console.aws.amazon.com/iam/home?#/users$new)します。
-1. ユーザ名を入力し (例えば `cfn-workshop`)、**アクセスキー - プログラムによるアクセス** と **パスワード - AWS マネジメントコンソールへのアクセス** にチェックを入れます。
-
- 
-
-1. **次のステップ: アクセス権限** を選択します。
-1. **既存のポリシーを直接アタッチ** を選択し、**AdministratorAccess** にチェックを入れます。
-
- 
-
-1. **次のステップ: タグ** を選択します。
-1. **次のステップ: 確認** を選択します。
-1. **ユーザーの作成** を選択します。
-1. 次の画面で利用する **アクセスキー ID** が表示されます。**シークレットアクセスキー** の隣の **表示** をクリックすると、その値が表示されます。
-
- 
-
-::alert[重要: 次のステップでアクセスキー ID とシークレットアクセスキーが必要になるので、この画面をこのまま維持するか、メモに保存してください。]{type="info"}
diff --git a/content/prerequisites/account/index.md b/content/prerequisites/account/index.md
deleted file mode 100644
index a88fdca80..000000000
--- a/content/prerequisites/account/index.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-title: "Create an AWS Account"
-weight: 100
----
-
-## Create an AWS Account for Experimentation
-
-To deploy our app, you'll need access to an AWS account. If you already have an account, and your system is configured
-with credentials of an administrator user, you can [move to the next step](../cloud9).
-
-:::alert{type="warning"}
-If you are using an existing account, either personal or a company account, make sure you understand the implications
-and policy of provisioning resources into this account.
-:::
-
-If you don't have an AWS account, you can [create a free account here](https://portal.aws.amazon.com/billing/signup).
-
-## Administrator User
-
-1. Sign in to your AWS account
-1. Go to the AWS IAM console and [create a new user](https://console.aws.amazon.com/iam/home?#/users$new).
-1. Type a name for your user (e.g. `cfn-workshop`) and choose both, **Programmatic access** and **AWS Management Console Access**.
-
- 
-
-1. Choose **Next: Permissions** to continue to the next step.
-1. Choose **Attach existing policies directly** and choose **AdministratorAccess**.
-
- 
-
-1. Choose **Next: Tags**
-1. Choose **Next: Review**
-1. Choose **Create User**
-1. In the next screen, you'll see your **Access key ID**, and you will have the option to click **Show** to show the **Secret access key**.
-
- 
-
-::alert[Important: Keep this browser window open for the next step or take a note of the access key ID and secret access key.]{type="info"}
diff --git a/content/prerequisites/code-editor/index.ja.md b/content/prerequisites/code-editor/index.ja.md
deleted file mode 100644
index 5885edce1..000000000
--- a/content/prerequisites/code-editor/index.ja.md
+++ /dev/null
@@ -1,56 +0,0 @@
----
-title: "Code Editor セットアップ (推奨)"
-weight: 200
----
-
-_セットアップ時間 : 5分程度_
-
-## 概要
-
-Code Editor はオープンソースのリモート統合開発環境 (IDE) で、ブラウザだけでコードの記述、実行、デバッグができます。これはブラウザ上で動作する VS Code と考えることができます。コードエディター、デバッガー、ターミナルが含まれています。このワークショップで必要となるライブラリやツールが含まれています。
-
-最高のエクスペリエンスと最小限のセットアップ作業を実現するために、AWS ホストイベントでは Code Editor の使用をおすすめします。なぜなら、必要なツールセットがプリインストールされており、ワークショップのリポジトリも既にクローンされているからです。ローカルでの作業をご希望の場合は、代わりに[ローカル開発セットアップ](/prerequisites/local-development)の手順をご参考ください。
-
-:::alert{type="info"}
-Code Editor は AWS ホストイベントで自動的にプロビジョニングされます。自分でこのワークショップを実行する場合は、代わりに[ローカル開発セットアップ](/prerequisites/local-development)をご利用ください。
-:::
-
-## AWS アカウントへのアクセス
-
-イベントに参加したら、イベント情報とワークショップの詳細が記載されたページが表示されます。左のナビゲーションバーに「AWS アカウントアクセス」というセクションも表示されているはずです。これらのオプションを使用して、提供された一時的な AWS アカウントにアクセスできます。
-
-
-
-### AWS マネジメントコンソール
-
-「AWS コンソール」リンクをクリックすると、AWS マネジメントコンソールのホームページが開きます。これは、各サービスにアクセスできる標準的な AWS コンソールです。ワークショップに関連するインフラストラクチャは、特定のリージョンにデプロイされ、そのリージョンからのみアクセスできることに注意してください。
-
-## Code Editor 環境へのログイン
-
-Code Editor の URL は、[ワークショップの概要ページ](https://catalog.us-east-1.prod.workshops.aws/event/dashboard/) の出力セクションにあります。
-
-
-
-URL をクリックすると、ワークショップで使用する IDE が表示されます。コマンドは画面下部のターミナルで実行できます。ターミナルパネルが自動的に切り替わらない場合は、画面右上の 2 番目の左のアイコンをクリックしてください。
-
-
-
-## ワークショップのファイル
-
-ワークショップのリポジトリは `/cfn101-workshop` ディレクトリに既にクローンされています。作業するテンプレートとコードは、**code** フォルダーにあります。
-
-左側のツリーを展開して、**code** フォルダを開き、ワークショップのファイルを確認してください。
-
-:::alert{type="info"}
-`git clone` を実行する必要はありません。ワークショップのコードは既に環境で利用可能です!
-:::
-
-## ベストプラクティス
-
-- イベントの利用規約を確認してください。アカウントに個人情報や機密情報をアップロードしないでください。
-- AWS アカウントはこのワークショップの間のみ利用できます。ワークショップ終了後はアクセスできなくなります。ワークショップ終了後もアクセスしたい資料はバックアップしておいてください。
-- 事前にプロビジョニングされたインフラストラクチャは、特定のリージョンにデプロイされます。他のリージョンが使用されるかどうかを判断するには、ワークショップのコンテンツを確認してください。
-
----
-
-おめでとうございます。これで、ワークショップの開発環境の準備が整いました。
diff --git a/content/prerequisites/code-editor/index.md b/content/prerequisites/code-editor/index.md
deleted file mode 100644
index eeacc3dee..000000000
--- a/content/prerequisites/code-editor/index.md
+++ /dev/null
@@ -1,56 +0,0 @@
----
-title: "Code Editor Setup (Recommended)"
-weight: 200
----
-
-_Setup Duration: ~5 minutes_
-
-## Overview
-
-Code Editor is an open-source remote integrated development environment (IDE) that lets you write, run, and debug your code with just a browser - think of it as Visual Studio Code running in a browser. It includes a code editor, debugger, and terminal. We have included the libraries and tools you will need during the workshop.
-
-For the best experience and minimal setup effort, we recommend using Code Editor to run this workshop at AWS-hosted events because it comes with the necessary set of tools pre-installed and the workshop repository already cloned. If you prefer to work locally, follow the [Local Development Setup](/prerequisites/local-development) instead.
-
-:::alert{type="info"}
-Code Editor is automatically provisioned for you at AWS-hosted events. If you are running this workshop on your own, please use the [Local Development Setup](/prerequisites/local-development) instead.
-:::
-
-## Accessing your AWS Account
-
-After joining the event, you should see the page with event information and workshop details. You should also see a section titled "AWS account access" on the left navigation bar. You can use these options to access the temporary AWS account provided to you.
-
-
-
-### AWS Management Console
-
-The "AWS console" link will open the AWS Management Console home page. This is the standard AWS Console that provides access to each service. Please note that the infrastructure associated with the workshop will be deployed to a specific region and can only be accessed from that region.
-
-## Login to your Code Editor environment
-
-You can find the URL for the Code Editor in the Output section of the [Workshop welcome](https://catalog.us-east-1.prod.workshops.aws/event/dashboard/) page:
-
-
-
-Follow the link, you will then be presented with the IDE you will use for the labs. The commands can be performed in the terminal section in the bottom part of the window (if the terminal panel is not toggled automatically, choose the second left-most small icon at the top right of your screen):
-
-
-
-## Workshop Files
-
-The workshop repository has been pre-cloned for you in the `/cfn101-workshop` directory. The templates and code you will work on are located in the **code** folder.
-
-Expand the tree on the left to open the **code** folder and explore the workshop files.
-
-:::alert{type="info"}
-No need to run `git clone` - the workshop code is already available in your environment!
-:::
-
-## Best Practices
-
-- Review the terms and conditions of the event. Do not upload any personal or confidential information in the account.
-- The AWS account will only be available for the duration of this workshop, and you will not be able to retain access after the workshop is complete. Backup any materials you wish to keep access to after the workshop.
-- Any pre-provisioned infrastructure will be deployed to a specific region. Check your workshop content to determine whether other regions will be used.
-
----
-
-Congratulations, your workshop development environment is now ready to use!
diff --git a/content/prerequisites/default-vpc/index.ja.md b/content/prerequisites/default-vpc/index.ja.md
deleted file mode 100644
index 05a2db784..000000000
--- a/content/prerequisites/default-vpc/index.ja.md
+++ /dev/null
@@ -1,68 +0,0 @@
----
-title: "デフォルト VPC"
-weight: 400
----
-
-デフォルト VPC では、すぐに利用開始出来ます。例えば、外部に公開するブログや簡単な Web サイトを作成できます。
-
-ワークショップの **[初級編](../../Basics)** では、CloudFormation のテンプレートを実行するリージョンにデフォルト VPC が必須です。
-
-意識的に削除されていない場合は、デフォルト VPC が必ず存在しています。わからない場合は、コマンドラインの手順に記載されている方法で確認してください。
-
-デフォルト VPC を削除した場合は、以下のどちらかの手順で作り直すことができます。
-
-### 1. Amazon VPC のコンソールでデフォルトVPCの作成
-
-1. Amazon VPC のコンソールを [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/) で開きます。
-1. ナビゲーションペインで **お使いの VPC** を選択します。
-1. **アクション** から **デフォルト VPC を作成** を選択します。
-1. **デフォルト VPC を作成** で確認画面を閉じます。
-
-### 2. コマンドラインでデフォルト VPC の作成
-
-ひとまず、デフォルト VPC の存在を確認します。AWS CLI を使って、リージョン内の全ての VPC のリストから取得します。
-
-1. 以下のコマンドラインをターミナルにコピーしてください。`--region` フラグで指定するリージョンをCloudFormation をデプロイする予定のリージョンに合わせてください。
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 describe-vpcs --filters Name=isDefault,Values=true --query "Vpcs[].VpcId" --region ap-northeast-1
- :::
-
-デフォルト VPC が存在している場合は、出力されるはずです。このセクションの残りを飛ばして、[次のステップ](../../Basics) に移行してください。
-
-回答が空欄 `[]` の場合は、リージョンのデフォルト VPC がないということです。
-
-2. 以下のコマンドをターミナルにコピーしてください。`--region` フラグで指定するリージョンをCloudFormation をデプロイする予定のリージョンに合わせてください。
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 create-default-vpc --region ap-northeast-1
- :::
-
- コマンドの結果は、以下の通りに新しく作成された VPC の情報が表示されます。
-
- :::code{language=json showLineNumbers=false showCopyAction=false}
- {
- "Vpc": {
- "CidrBlock": "172.31.0.0/16",
- "DhcpOptionsId": "dopt-c1422ea9",
- "State": "pending",
- "VpcId": "vpc-088b5ae6628fbf3ac",
- "OwnerId": "123456789012",
- "InstanceTenancy": "default",
- "Ipv6CidrBlockAssociationSet": [],
- "CidrBlockAssociationSet": [
- {
- "AssociationId": "vpc-cidr-assoc-0ab2ffabcbe0548bc",
- "CidrBlock": "172.31.0.0/16",
- "CidrBlockState": {
- "State": "associated"
- }
- }
- ],
- "IsDefault": true,
- "Tags": []
- }
- }
- :::
-
- ::alert[ワークショップの後にデフォルト VPC を削除されたい場合は、上記の **VpcId** のメモを取ると削除時に確実に正しい VPC を削除できます。]{type="info"}
diff --git a/content/prerequisites/default-vpc/index.md b/content/prerequisites/default-vpc/index.md
deleted file mode 100644
index a77b36ac6..000000000
--- a/content/prerequisites/default-vpc/index.md
+++ /dev/null
@@ -1,67 +0,0 @@
----
-title: "Default VPC"
-weight: 400
----
-A default VPC is suitable for getting started quickly, and for launching public instances such as a blog or simple website.
-
-**[Basics](../../Basics)** part of the workshop requires that a default VPC is available in the region you will be deploying CloudFormation templates to.
-
-You will have a default VPC unless you have removed it. If you are unsure, follow the instructions below to check.
-
-If you have deleted your default VPC, you can create a new one by following one of the options below.
-
-### 1. Create a default VPC using the Amazon VPC console
-
-1. Open the Amazon VPC console at [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/).
-1. In the navigation pane, choose **Your VPCs**.
-1. Choose **Actions**, **Create Default VPC**.
-1. Choose **Create**. Close the confirmation screen.
-
-### 2. Create a default VPC using the command line
-
-First we will check if a default VPC is present or not. We will use the AWS CLI to list all existing VPCs in the region
-
-1. Copy the code below to your terminal. Make sure to change the `--region` flag to use a region that you are going to be deploying your CloudFormation to.
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 describe-vpcs --filters Name=isDefault,Values=true --query "Vpcs[].VpcId" --region eu-west-2
- :::
-
-If the default VPC exists, it will be included here. Assert that `IsDefault` key is `true` and [move to the next step](../../Basics). You can skip the remainder of this section.
-
-If the response is empty `[]` or the VPC is not **default** proceed to the next step. A default VPC does not exist in this region.
-
-1. Copy the code below to your terminal. Make sure to change the --region flag to use a region that you are going to be deploying your CloudFormation to.
-
- :::code{language=shell showLineNumbers=false showCopyAction=true}
- aws ec2 create-default-vpc --region eu-west-2
- :::
-
- The result will be a new default VPC created, and the response in the terminal will look like the sample below.
-
- :::code{language=json showLineNumbers=false showCopyAction=false}
- {
- "Vpc": {
- "CidrBlock": "172.31.0.0/16",
- "DhcpOptionsId": "dopt-c1422ea9",
- "State": "pending",
- "VpcId": "vpc-088b5ae6628fbf3ac",
- "OwnerId": "123456789012",
- "InstanceTenancy": "default",
- "Ipv6CidrBlockAssociationSet": [],
- "CidrBlockAssociationSet": [
- {
- "AssociationId": "vpc-cidr-assoc-0ab2ffabcbe0548bc",
- "CidrBlock": "172.31.0.0/16",
- "CidrBlockState": {
- "State": "associated"
- }
- }
- ],
- "IsDefault": true,
- "Tags": []
- }
- }
- :::
-
- ::alert[If you wish to delete the default VPC again at the end of this workshop you should make a note of the **VpcId** above so that you can be sure to know which one to delete later.]{type="info"}
diff --git a/content/prerequisites/index.ja.md b/content/prerequisites/index.ja.md
deleted file mode 100644
index eb979c097..000000000
--- a/content/prerequisites/index.ja.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "事前準備"
-weight: 20
----
-
-このワークショップを完了するには、開発環境をセットアップする必要があります。以下のオプションから選択してください。
-
-::children
-
-:::alert{type="info"}
-**AWS ホストイベントでの推奨:** [Code Editor セットアップ](/prerequisites/code-editor) をご利用ください。必要なツールがプリインストールされ、ワークショップのコードも既にクローンされているブラウザベースの IDE です。
-:::
-
-自分でこのワークショップを実行する場合、またはローカルでの作業をご希望の場合は、代わりに[ローカル開発セットアップ](/prerequisites/local-development)の手順をご参考ください。
-
-最初のステップに進むためには、Next をクリックしてください。
diff --git a/content/prerequisites/index.md b/content/prerequisites/index.md
deleted file mode 100644
index 48c3a0417..000000000
--- a/content/prerequisites/index.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "Prerequisites"
-weight: 20
----
-
-To complete this workshop, you will need to set up your development environment. Choose one of the following options:
-
-::children
-
-:::alert{type="info"}
-**Recommended for AWS-hosted events:** Use [Code Editor Setup](/prerequisites/code-editor) - a browser-based IDE with all tools pre-installed and the workshop code already cloned.
-:::
-
-If you are running this workshop on your own or prefer to work locally, follow the [Local Development Setup](/prerequisites/local-development) instead.
-
-Click on the arrow to the right to continue to the first step.
diff --git a/content/prerequisites/local-development/index.ja.md b/content/prerequisites/local-development/index.ja.md
deleted file mode 100644
index 54b5cb646..000000000
--- a/content/prerequisites/local-development/index.ja.md
+++ /dev/null
@@ -1,67 +0,0 @@
----
-title: "ローカル開発の設定"
-weight: 300
----
-
-_セットアップ時間 : 15分程度_
-
-:::alert{type="info"}
-こちらの手順は、ワークショップで Cloud9 IDE を使用していない場合にのみ必要です。使用している場合は、[デフォルト VPC](../default-vpc) に移行してください。
-:::
-
-このワークショップのローカル開発を行うには、いくつかの開発ツールが必要です。ワークショップを続行する前に、それらのツールインストールして、正しくインストールされていることを確認してください。
-
-### AWS CLI のインストール
-
-[AWS CLI](https://aws.amazon.com/jp/cli/) を使用すると、ターミナルセッションから AWS のサービスとやり取りができます。システムに AWS CLI の最新バージョンがインストールされていることを確認してください。
-
-[AWS CLI の最新バージョンを使用してインストールまたは更新を行う](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html) にてご使用のオペレーティングシステムのインストール手順のページをご参照ください。
-
-### 認証情報の設定
-
-ターミナルウィンドウを開き、`aws configure` を実行して環境を設定します。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws configure
-:::
-
-[前のステップ](/prerequisites/account) で作成した **access key ID** と **secret key** を入力し、デフォルトのリージョン (たとえば `us-east-1`) を指定します。できれば、リソースがまだデプロイされていないリージョンの使用をお勧めします。
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-AWS Access Key ID [None]: <ここに access key ID を入力>
-AWS Secret Access Key [None]: <ここに secret key を入力>
-Default region name [None]:
-Default output format [None]: <空白で大丈夫>
-:::
-
-### `git` を使ってラボのリソースをクローン
-
-リポジトリを作業ディレクトリにクローンします。
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-git clone https://github.com/aws-samples/cfn101-workshop
-:::
-
-### コードエディタのインストール
-
-[YAML](https://yaml.org/) の編集をサポートしている任意のコードエディターまたは IDE を使用できますが、このワークショップでは macOS、Linux、および Windows で動作する [Visual Studio Code](https://code.visualstudio.com/) の使用を前提としています。
-
-VS Code をインストールするには、オペレーティングシステムのパッケージマネージャーを使用するか (例 : macOS では `brew cask install visual-studio-code`)、[VS code の Web サイト](https://code.visualstudio.com/) の説明に従ってインストールしてください。
-
-### CloudFormation リンター
-
-[AWS CloudFormation Linter](https://github.com/aws-cloudformation/cfn-lint) のインストールをお勧めします。
-[linter](https://en.wikipedia.org/wiki/Lint_(software)) は、CloudFormation テンプレートをデプロイする前に、テンプレートの基本的なエラーを事前に検出してくれます。
-
-Visual Studio Code を使用している場合は、[cfn-lint](https://marketplace.visualstudio.com/items?itemName=kddejong.vscode-cfn-lint) プラグインをインストールする必要があります。
-
-:::alert{type="info"}
-Visual Studio Code の `cfn-lint` プラグインをインストールしても、`cfn-lint` が自動的にインストールされないことにご注意ください。[インストール手順](https://github.com/aws-cloudformation/cfn-lint#install) に従って個別にインストールしてください。
-:::
-
-### ワークショップのファイルを開く
-
-作業するテンプレートとコードは、**code** フォルダーにあります。
-ダウンロードしたファイルから **code** セクションをコードエディターで開きます。
-
-
diff --git a/content/prerequisites/local-development/index.md b/content/prerequisites/local-development/index.md
deleted file mode 100644
index 09018952c..000000000
--- a/content/prerequisites/local-development/index.md
+++ /dev/null
@@ -1,70 +0,0 @@
----
-title: "Local Development Setup"
-weight: 300
----
-
-_Setup Duration: ~15 minutes_
-
-:::alert{type="info"}
-This is only required if you are not using Cloud9 IDE for the workshop. Else you can skip to the [Default VPC](../default-vpc) section
-:::
-
-Local development for this workshop requires a number of development tools. Please install and verify these are installed correctly before proceeding with the workshop.
-
-### Install AWS CLI
-
-The [AWS CLI](https://aws.amazon.com/cli/) allows you to interact with AWS services from a terminal session.
-Make sure you have the latest version of the AWS CLI installed on your system.
-
-See the [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
-page for installation instructions for your operating system.
-
-### Configure your credentials
-
-Open a terminal window and run `aws configure` to set up your environment.
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-aws configure
-:::
-
-Type the **access key ID** and **secret key** you created in [the previous step](/prerequisites/account) and choose a default region (for example you can use `us-east-1`). Preferably use a region that doesn't have any resources already deployed into it.
-
-:::code{language=shell showLineNumbers=false showCopyAction=false}
-AWS Access Key ID [None]:
-AWS Secret Access Key [None]:
-Default region name [None]:
-Default output format [None]:
-:::
-
-### Clone lab resources using git
-Clone the repository to your working directory:
-
-:::code{language=shell showLineNumbers=false showCopyAction=true}
-git clone https://github.com/aws-samples/cfn101-workshop
-:::
-
-### Install Code Editor
-
-You may use any code editor or IDE of your choice that supports editing [YAML](https://yaml.org/) but for this workshop
-we will assume the use of [Visual Studio Code](https://code.visualstudio.com/) as it works well on macOS, Linux, and Windows.
-
-To install VS Code, use your operating system's package manager (e.g. `brew cask install visual-studio-code` on macOS)
-or follow [the instructions on the VS code website](https://code.visualstudio.com/).
-
-### CloudFormation Linter
-
-We recommend you install the [AWS CloudFormation Linter](https://github.com/aws-cloudformation/cfn-python-lint).
-A [linter](https://en.wikipedia.org/wiki/Lint_(software)) will proactively flag basic errors in your CloudFormation templates before you deploy them.
-
-If you are using Visual Studio Code, you should install the [cfn-lint](https://marketplace.visualstudio.com/items?itemName=kddejong.vscode-cfn-lint) plugin.
-
-:::alert{type="info"}
-Note that `cfn-lint` is not installed automatically with the Visual Studio Code `cfn-lint` extension.
-Install it separately following the [installation instructions](https://github.com/aws-cloudformation/cfn-python-lint#install)
-:::
-
-### Open workshop files
-The templates and the code you will work on are both located in the **code** folder.
-Open the **code** section from downloaded files in your code editor:
-
-
diff --git a/contentspec.yaml b/contentspec.yaml
deleted file mode 100644
index b8826a3f2..000000000
--- a/contentspec.yaml
+++ /dev/null
@@ -1,53 +0,0 @@
-version: 2.0
-
-defaultLocaleCode: en
-localeCodes:
-- en
-- ja
-
-params:
- author: AWS
- description: AWS CloudFormation Workshop
- disableAssetsBusting: true
- disableBreadcrumb: false
- disableInlineCopyToClipBoard: true
- disableLanguageSwitchingButton: false
- disableNextPrev: false
- disableSearch: false
- disableShortcutsTitle: true
- themeVariant: aws
-
-awsAccountConfig:
- accountSources:
- - WorkshopStudio
- - CustomerProvided
- regionConfiguration:
- deployableRegions:
- required:
- - us-east-1
- minAccessibleRegions: 1
- maxAccessibleRegions: 3
- accessibleRegions:
- required:
- - us-east-1
- - us-east-2
- - us-west-2
- participantRole:
- managedPolicies:
- - "arn:aws:iam::aws:policy/AdministratorAccess"
-
-infrastructure:
- cloudformationTemplates:
- - templateLocation: static/cfn/code-editor.yaml
- label: Code Editor
- participantVisibleStackOutputs:
- - URL
- parameters:
- - templateParameter: InstanceType
- defaultValue: t4g.medium
- - templateParameter: InstanceOperatingSystem
- defaultValue: AmazonLinux-2023
- - templateParameter: HomeFolder
- defaultValue: /cfn101-workshop
- - templateParameter: RepoUrl
- defaultValue: 'https://github.com/aws-samples/cfn101-workshop.git'
diff --git a/docs/LOCAL_DEVELOPMENT.md b/docs/LOCAL_DEVELOPMENT.md
deleted file mode 100644
index e0e7cd9b9..000000000
--- a/docs/LOCAL_DEVELOPMENT.md
+++ /dev/null
@@ -1,115 +0,0 @@
-## Local Development
-
-### Pre-Requisites
-The following dependencies must be installed. Please refer to your operating system, how to install them.
-
-> **Note:** For Windows 10, we recommend enabling Windows Subsystem for Linux (WSL) and installing Linux distribution of your choice,
-> for example, here are the instructions on how to install [Ubuntu](https://ubuntu.com/tutorials/ubuntu-on-windows).
-
-- Python >=3.8 and pip
-- VirtualEnv
-- Go
-- Ruby >=2.6 and gem
-- [cfn-nag](https://github.com/stelligent/cfn_nag)
-
-Here is an example how to install pre-requisites on macOS/Linux using [Homebrew](https://brew.sh/).
-```shell
-# install python3
-brew install python
-
-# install VirtualEnv
-pip3 install virtualenv
-
-# install go
-brew install go
-
-# install ruby, gem and cfn-nag
-brew install ruby brew-gem
-brew gem install cfn-nag
-```
-
-### Build local development environment
-Once you have installed pre-requisites, run commands below:
-
-#### Step 1 - Clone the repository (Required)
-In the first step, you will clone the repository.
-
-1. Clone the repository:
- ```shell
- $ git clone https://github.com/aws-samples/cfn101-workshop.git
- ```
-
-#### Step 2 - `make init` (Required)
-In the second step, you will use `make` to create a virtual environment.
-
-1. Initialize the local environment
- ```shell
- make init
- ```
-1. Activate `VirtualEnv` environment.
- ```shell
- source venv/bin/activate
- ```
-1. Run pre-commit tests for the first time to check the installation.
- ```shell
- make test
- ```
-
-#### Run the local development utility (AWS employees only)
-Follow the instructions for Local Development at Workshop Studio documentation.
-
-Once you download binaries, and run preview server, the preview will be available at `http://localhost:8080`
-
-### Testing(Automated and Manual)
-The repository has a GitHub actions set up which will run `cfn-lint` and `cfn-nag` tests on pull requests.
-
-Furthermore, pre-commit configuration file is provided to format the code and content. See below various tests you can
-run locally when developing the labs.
-
-* `make test` - will run pre-commit tests. Useful to run before committing changes.
-* `make lint` - will run cfn-lint test against CloudFormation templates in `/code/solutions directory`.
-* `make nag` - will run cfn-nag test against CloudFormation templates in `/code/solutions directory`.
-
-### Versioning and releasing (Repo admin only)
-The `bump2version` tool is used to take care of versioning including tagging a new versions.
-
-When ready to publish new release follow the steps below:
-```shell
-# checkout and update main branch
-git checkout main && git pull
-
-# checkout feature branch
-git checkout
-
-# merge main branch to feature branch
-git merge main
-
-# bump the version following semantic guide above part=patch|minor|major
-make version part=minor
-
-# push the new version tag to origin
-make release
-
-# merge the feature branch to main branch on github
-```
-
-Finally, create new release on [cfn101-workshop](https://github.com/aws-samples/cfn101-workshop/releases) release page
-
-* Select **Releases** and choose **Draft a new release**
-* Choose a tag version
-* Select **Auto-generate release notes**
-* **Publish release**
-
-## Troubleshooting
-If you get an error installing rain
-```shell
-[INFO] Installing environment for https://github.com/aws-cloudformation/rain.
-[INFO] Once installed this environment will be reused.
-[INFO] This may take a few minutes...
-An unexpected error has occurred: CalledProcessError: command:...
-```
-
-The default **proxy.golang.org** is blocked on your network. To fix it, run:
-```shell
-export GOPROXY=direct
-```
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 000000000..1dded23f6
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,22 @@
+[project]
+name = "cfn-workshop"
+version = "1.0.0"
+description = "AWS CloudFormation Workshop"
+requires-python = ">=3.12"
+dependencies = [
+ "awscli",
+ "boto3",
+ "bump2version",
+ "cfn-lint",
+ "pre-commit",
+]
+
+[build-system]
+requires = ["setuptools>=61.0"]
+build-backend = "setuptools.build_meta"
+
+[tool.setuptools]
+py-modules = []
+
+[dependency-groups]
+dev = []
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index d4e2acee3..000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-awscli
-boto3
-bump2version
-cfn_lint
-pre-commit
diff --git a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-apply-hook-filters.png b/static/advanced/hook/advanced-hook-create-a-hook-with-guard-apply-hook-filters.png
deleted file mode 100644
index 68f08dedb..000000000
Binary files a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-apply-hook-filters.png and /dev/null differ
diff --git a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-failed-stack-view-events-output-compliant.png b/static/advanced/hook/advanced-hook-create-a-hook-with-guard-failed-stack-view-events-output-compliant.png
deleted file mode 100644
index 649eef0de..000000000
Binary files a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-failed-stack-view-events-output-compliant.png and /dev/null differ
diff --git a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-failed-stack-view-events-output-noncomliant.png b/static/advanced/hook/advanced-hook-create-a-hook-with-guard-failed-stack-view-events-output-noncomliant.png
deleted file mode 100644
index 7ea555136..000000000
Binary files a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-failed-stack-view-events-output-noncomliant.png and /dev/null differ
diff --git a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-failed-stack-view-ui-noncomliant-stack.png b/static/advanced/hook/advanced-hook-create-a-hook-with-guard-failed-stack-view-ui-noncomliant-stack.png
deleted file mode 100644
index 20b36ab2e..000000000
Binary files a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-failed-stack-view-ui-noncomliant-stack.png and /dev/null differ
diff --git a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-hook-details-and-settings.png b/static/advanced/hook/advanced-hook-create-a-hook-with-guard-hook-details-and-settings.png
deleted file mode 100644
index 9972cdb26..000000000
Binary files a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-hook-details-and-settings.png and /dev/null differ
diff --git a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-provide-your-guard-rules.png b/static/advanced/hook/advanced-hook-create-a-hook-with-guard-provide-your-guard-rules.png
deleted file mode 100644
index bfe202d18..000000000
Binary files a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-provide-your-guard-rules.png and /dev/null differ
diff --git a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-review-and-activate.png b/static/advanced/hook/advanced-hook-create-a-hook-with-guard-review-and-activate.png
deleted file mode 100644
index d30e45fe8..000000000
Binary files a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-review-and-activate.png and /dev/null differ
diff --git a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-start-dropdown-option.png b/static/advanced/hook/advanced-hook-create-a-hook-with-guard-start-dropdown-option.png
deleted file mode 100644
index 2dc22a1b7..000000000
Binary files a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-start-dropdown-option.png and /dev/null differ
diff --git a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-successful-creation.png b/static/advanced/hook/advanced-hook-create-a-hook-with-guard-successful-creation.png
deleted file mode 100644
index 3d6a55730..000000000
Binary files a/static/advanced/hook/advanced-hook-create-a-hook-with-guard-successful-creation.png and /dev/null differ
diff --git a/static/advanced/hook/cloudwatch-hook-fail.png b/static/advanced/hook/cloudwatch-hook-fail.png
deleted file mode 100644
index 7ea9bb870..000000000
Binary files a/static/advanced/hook/cloudwatch-hook-fail.png and /dev/null differ
diff --git a/static/advanced/hook/cloudwatch-hook-success.png b/static/advanced/hook/cloudwatch-hook-success.png
deleted file mode 100644
index 8893d9264..000000000
Binary files a/static/advanced/hook/cloudwatch-hook-success.png and /dev/null differ
diff --git a/static/advanced/hook/hook-activate-after-creation.png b/static/advanced/hook/hook-activate-after-creation.png
deleted file mode 100644
index 690dadd14..000000000
Binary files a/static/advanced/hook/hook-activate-after-creation.png and /dev/null differ
diff --git a/static/advanced/hook/hook-detail.png b/static/advanced/hook/hook-detail.png
deleted file mode 100644
index 0a012ced4..000000000
Binary files a/static/advanced/hook/hook-detail.png and /dev/null differ
diff --git a/static/advanced/hook/hook-filters.png b/static/advanced/hook/hook-filters.png
deleted file mode 100644
index c88876c69..000000000
Binary files a/static/advanced/hook/hook-filters.png and /dev/null differ
diff --git a/static/advanced/hook/hook-review.png b/static/advanced/hook/hook-review.png
deleted file mode 100644
index 2d53f7e51..000000000
Binary files a/static/advanced/hook/hook-review.png and /dev/null differ
diff --git a/static/advanced/hook/hook-role.png b/static/advanced/hook/hook-role.png
deleted file mode 100644
index 70870ef53..000000000
Binary files a/static/advanced/hook/hook-role.png and /dev/null differ
diff --git a/static/advanced/hook/hook-test-compliant-stack-log.png b/static/advanced/hook/hook-test-compliant-stack-log.png
deleted file mode 100644
index 71123b23b..000000000
Binary files a/static/advanced/hook/hook-test-compliant-stack-log.png and /dev/null differ
diff --git a/static/advanced/hook/hook-test-compliant-stack.png b/static/advanced/hook/hook-test-compliant-stack.png
deleted file mode 100644
index c7f7a6762..000000000
Binary files a/static/advanced/hook/hook-test-compliant-stack.png and /dev/null differ
diff --git a/static/advanced/hook/hook-test-noncompliant-stack-log.png b/static/advanced/hook/hook-test-noncompliant-stack-log.png
deleted file mode 100644
index cc931d672..000000000
Binary files a/static/advanced/hook/hook-test-noncompliant-stack-log.png and /dev/null differ
diff --git a/static/advanced/hook/hook-test-noncompliant-stack.png b/static/advanced/hook/hook-test-noncompliant-stack.png
deleted file mode 100644
index 8ee0f8677..000000000
Binary files a/static/advanced/hook/hook-test-noncompliant-stack.png and /dev/null differ
diff --git a/static/advanced/hook/lambda-creation.png b/static/advanced/hook/lambda-creation.png
deleted file mode 100644
index f5cb329f6..000000000
Binary files a/static/advanced/hook/lambda-creation.png and /dev/null differ
diff --git a/static/advanced/hook/lambda-deploy.png b/static/advanced/hook/lambda-deploy.png
deleted file mode 100644
index 28a4df40d..000000000
Binary files a/static/advanced/hook/lambda-deploy.png and /dev/null differ
diff --git a/static/advanced/hook/lambda-test-2.png b/static/advanced/hook/lambda-test-2.png
deleted file mode 100644
index ce0f28f65..000000000
Binary files a/static/advanced/hook/lambda-test-2.png and /dev/null differ
diff --git a/static/advanced/hook/lambda-test-fail.png b/static/advanced/hook/lambda-test-fail.png
deleted file mode 100644
index 84e4aa894..000000000
Binary files a/static/advanced/hook/lambda-test-fail.png and /dev/null differ
diff --git a/static/advanced/hook/lambda-test-success.png b/static/advanced/hook/lambda-test-success.png
deleted file mode 100644
index 0a01087bb..000000000
Binary files a/static/advanced/hook/lambda-test-success.png and /dev/null differ
diff --git a/static/advanced/hook/lambda-test.png b/static/advanced/hook/lambda-test.png
deleted file mode 100644
index 6fcc6ebfd..000000000
Binary files a/static/advanced/hook/lambda-test.png and /dev/null differ
diff --git a/static/advanced/modules/ActivatedExtensions.ja.png b/static/advanced/modules/ActivatedExtensions.ja.png
deleted file mode 100644
index f519c514a..000000000
Binary files a/static/advanced/modules/ActivatedExtensions.ja.png and /dev/null differ
diff --git a/static/advanced/modules/ActivatedExtensions.png b/static/advanced/modules/ActivatedExtensions.png
deleted file mode 100644
index f0d10deed..000000000
Binary files a/static/advanced/modules/ActivatedExtensions.png and /dev/null differ
diff --git a/static/advanced/modules/StackResources.ja.png b/static/advanced/modules/StackResources.ja.png
deleted file mode 100644
index 9e06fe184..000000000
Binary files a/static/advanced/modules/StackResources.ja.png and /dev/null differ
diff --git a/static/advanced/modules/StackResources.png b/static/advanced/modules/StackResources.png
deleted file mode 100644
index fe5223a09..000000000
Binary files a/static/advanced/modules/StackResources.png and /dev/null differ
diff --git a/static/advanced/modules/StackTemplate.ja.png b/static/advanced/modules/StackTemplate.ja.png
deleted file mode 100644
index 09c8896c5..000000000
Binary files a/static/advanced/modules/StackTemplate.ja.png and /dev/null differ
diff --git a/static/advanced/modules/StackTemplate.png b/static/advanced/modules/StackTemplate.png
deleted file mode 100644
index 162e63f54..000000000
Binary files a/static/advanced/modules/StackTemplate.png and /dev/null differ
diff --git a/static/advanced/modules/vpc.drawio b/static/advanced/modules/vpc.drawio
deleted file mode 100644
index 1a1e43821..000000000
--- a/static/advanced/modules/vpc.drawio
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/static/advanced/modules/vpc.png b/static/advanced/modules/vpc.png
deleted file mode 100644
index c4f88bad5..000000000
Binary files a/static/advanced/modules/vpc.png and /dev/null differ
diff --git a/static/aws-cloudformation.png b/static/aws-cloudformation.png
deleted file mode 100644
index c127b78cb..000000000
Binary files a/static/aws-cloudformation.png and /dev/null differ
diff --git a/static/basics/operations/ec2-1.png b/static/basics/operations/ec2-1.png
deleted file mode 100644
index 1d39ac649..000000000
Binary files a/static/basics/operations/ec2-1.png and /dev/null differ
diff --git a/static/basics/operations/helper-scripts/ami-id-1.png b/static/basics/operations/helper-scripts/ami-id-1.png
deleted file mode 100644
index c09abb834..000000000
Binary files a/static/basics/operations/helper-scripts/ami-id-1.png and /dev/null differ
diff --git a/static/basics/operations/multi-region-latest-ami/new-region-1.gif b/static/basics/operations/multi-region-latest-ami/new-region-1.gif
deleted file mode 100644
index 3a4205fac..000000000
Binary files a/static/basics/operations/multi-region-latest-ami/new-region-1.gif and /dev/null differ
diff --git a/static/basics/operations/session-manager/ssm-sm-1.gif b/static/basics/operations/session-manager/ssm-sm-1.gif
deleted file mode 100644
index 4d844baed..000000000
Binary files a/static/basics/operations/session-manager/ssm-sm-1.gif and /dev/null differ
diff --git a/static/basics/operations/session-manager/ssm-sm-1.png b/static/basics/operations/session-manager/ssm-sm-1.png
deleted file mode 100644
index 1c98864e7..000000000
Binary files a/static/basics/operations/session-manager/ssm-sm-1.png and /dev/null differ
diff --git a/static/basics/operations/ssm-1.png b/static/basics/operations/ssm-1.png
deleted file mode 100644
index cbea768e7..000000000
Binary files a/static/basics/operations/ssm-1.png and /dev/null differ
diff --git a/static/basics/operations/troubleshooting-provisioning-errors/stack-rollback-paused.ja.png b/static/basics/operations/troubleshooting-provisioning-errors/stack-rollback-paused.ja.png
deleted file mode 100644
index 1082c7426..000000000
Binary files a/static/basics/operations/troubleshooting-provisioning-errors/stack-rollback-paused.ja.png and /dev/null differ
diff --git a/static/basics/operations/troubleshooting-provisioning-errors/stack-rollback-paused.png b/static/basics/operations/troubleshooting-provisioning-errors/stack-rollback-paused.png
deleted file mode 100644
index 4611454a5..000000000
Binary files a/static/basics/operations/troubleshooting-provisioning-errors/stack-rollback-paused.png and /dev/null differ
diff --git a/static/basics/operations/user-data/outputs-1.ja.png b/static/basics/operations/user-data/outputs-1.ja.png
deleted file mode 100644
index a9063f4ed..000000000
Binary files a/static/basics/operations/user-data/outputs-1.ja.png and /dev/null differ
diff --git a/static/basics/operations/user-data/outputs-1.png b/static/basics/operations/user-data/outputs-1.png
deleted file mode 100644
index 430904b4b..000000000
Binary files a/static/basics/operations/user-data/outputs-1.png and /dev/null differ
diff --git a/static/basics/operations/user-data/php.png b/static/basics/operations/user-data/php.png
deleted file mode 100644
index 2b8991cd9..000000000
Binary files a/static/basics/operations/user-data/php.png and /dev/null differ
diff --git a/static/basics/operations/user-data/userdata.png b/static/basics/operations/user-data/userdata.png
deleted file mode 100644
index f4a104b22..000000000
Binary files a/static/basics/operations/user-data/userdata.png and /dev/null differ
diff --git a/static/basics/templates/cfn-1.png b/static/basics/templates/cfn-1.png
deleted file mode 100644
index 9bd53eebe..000000000
Binary files a/static/basics/templates/cfn-1.png and /dev/null differ
diff --git a/static/basics/templates/intrinsic-functions/tags.ja.png b/static/basics/templates/intrinsic-functions/tags.ja.png
deleted file mode 100644
index 0f403d990..000000000
Binary files a/static/basics/templates/intrinsic-functions/tags.ja.png and /dev/null differ
diff --git a/static/basics/templates/intrinsic-functions/tags.png b/static/basics/templates/intrinsic-functions/tags.png
deleted file mode 100644
index 934e996df..000000000
Binary files a/static/basics/templates/intrinsic-functions/tags.png and /dev/null differ
diff --git a/static/basics/templates/mappings/mapping.png b/static/basics/templates/mappings/mapping.png
deleted file mode 100644
index abf1746e1..000000000
Binary files a/static/basics/templates/mappings/mapping.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/lambda-test.ja.png b/static/basics/templates/pseudo-parameters/lambda-test.ja.png
deleted file mode 100644
index 84db654dc..000000000
Binary files a/static/basics/templates/pseudo-parameters/lambda-test.ja.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/lambda-test.png b/static/basics/templates/pseudo-parameters/lambda-test.png
deleted file mode 100644
index 9bde284c5..000000000
Binary files a/static/basics/templates/pseudo-parameters/lambda-test.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/lambda.ja.png b/static/basics/templates/pseudo-parameters/lambda.ja.png
deleted file mode 100644
index fed14e320..000000000
Binary files a/static/basics/templates/pseudo-parameters/lambda.ja.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/lambda.png b/static/basics/templates/pseudo-parameters/lambda.png
deleted file mode 100644
index 7b53d349c..000000000
Binary files a/static/basics/templates/pseudo-parameters/lambda.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/policy.ja.png b/static/basics/templates/pseudo-parameters/policy.ja.png
deleted file mode 100644
index c31724e53..000000000
Binary files a/static/basics/templates/pseudo-parameters/policy.ja.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/policy.png b/static/basics/templates/pseudo-parameters/policy.png
deleted file mode 100644
index 2817c3228..000000000
Binary files a/static/basics/templates/pseudo-parameters/policy.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/resources.ja.png b/static/basics/templates/pseudo-parameters/resources.ja.png
deleted file mode 100644
index 5b70348d9..000000000
Binary files a/static/basics/templates/pseudo-parameters/resources.ja.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/resources.png b/static/basics/templates/pseudo-parameters/resources.png
deleted file mode 100644
index 183202a41..000000000
Binary files a/static/basics/templates/pseudo-parameters/resources.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/role.ja.png b/static/basics/templates/pseudo-parameters/role.ja.png
deleted file mode 100644
index f8baf6b43..000000000
Binary files a/static/basics/templates/pseudo-parameters/role.ja.png and /dev/null differ
diff --git a/static/basics/templates/pseudo-parameters/role.png b/static/basics/templates/pseudo-parameters/role.png
deleted file mode 100644
index 4b4d600d4..000000000
Binary files a/static/basics/templates/pseudo-parameters/role.png and /dev/null differ
diff --git a/static/basics/templates/resource-return-values/resource-return-values.ja.png b/static/basics/templates/resource-return-values/resource-return-values.ja.png
deleted file mode 100644
index dbeb416ee..000000000
Binary files a/static/basics/templates/resource-return-values/resource-return-values.ja.png and /dev/null differ
diff --git a/static/basics/templates/resource-return-values/resource-return-values.png b/static/basics/templates/resource-return-values/resource-return-values.png
deleted file mode 100644
index d859109b8..000000000
Binary files a/static/basics/templates/resource-return-values/resource-return-values.png and /dev/null differ
diff --git a/static/basics/templates/resources/ami-id.gif b/static/basics/templates/resources/ami-id.gif
deleted file mode 100644
index c312dfcc1..000000000
Binary files a/static/basics/templates/resources/ami-id.gif and /dev/null differ
diff --git a/static/basics/templates/template-1.png b/static/basics/templates/template-1.png
deleted file mode 100644
index 293e705cc..000000000
Binary files a/static/basics/templates/template-1.png and /dev/null differ
diff --git a/static/basics/templates/template-anatomy/cfn-stack.png b/static/basics/templates/template-anatomy/cfn-stack.png
deleted file mode 100644
index eb7cde88e..000000000
Binary files a/static/basics/templates/template-anatomy/cfn-stack.png and /dev/null differ
diff --git a/static/cfn/code-editor.yaml b/static/cfn/code-editor.yaml
deleted file mode 100644
index 3a7734245..000000000
--- a/static/cfn/code-editor.yaml
+++ /dev/null
@@ -1,1351 +0,0 @@
-Description: Create a Code Editor instance with an Amazon CloudFront distribution for use in Workshop Studio. Version 1.4.0
-
-Parameters:
- CodeEditorUser:
- Type: String
- Description: UserName for Code Editor
- Default: participant
- InstanceName:
- Type: String
- Description: Code Editor EC2 instance name
- Default: CodeEditor
- InstanceVolumeSize:
- Type: Number
- Description: Code Editor EC2 instance volume size in GB
- Default: 40
- InstanceType:
- Description: Code Editor EC2 instance type
- Type: String
- Default: t4g.medium
- InstanceOperatingSystem:
- Description: Code Editor EC2 operating system
- Type: String
- Default: AmazonLinux-2023
- AllowedValues: ['AmazonLinux-2023', 'Ubuntu-22', 'Ubuntu-24']
- HomeFolder:
- Type: String
- Description: Folder to open in Code Editor
- Default: /workshop
- DevServerBasePath:
- Type: String
- Description: Base path for the application to be added to Nginx sites-available list
- Default: ''
- DevServerPort:
- Type: Number
- Description: Port for the DevServer
- Default: 8081
- RepoUrl:
- Description: Remote repo URL to clone. To not clone a remote repo, leave blank
- Type: String
- Default: ''
- AssetZipS3Path:
- Description: S3 path holding the asset zip file to be copied into the home folder. To not include any assets, leave blank
- Type: String
- Default: ''
- BranchZipS3Path:
- Description: S3 path holding the branches zip file to be checked into the git repo, with each folder being a branch. The content of each folder will added as under a branch, with the folder name being used as the branch name. To leave the empty, leave blank
- Type: String
- Default: ''
- FolderZipS3Path:
- Description: S3 path holding the folder zip file, with each folder being a subfolder of the home directory. Each folder will have its own local git repo. To not include any folders, leave blank
- Type: String
- Default: ''
-
-Conditions:
- IsAL2023: !Equals [!Ref InstanceOperatingSystem, 'AmazonLinux-2023']
- IsGraviton: !Not [
- !Equals [
- !Select [0, !Split ['g', !Select [0, !Split ['.', !Ref InstanceType]]]],
- !Select [0, !Split ['.', !Ref InstanceType]]
- ]
- ]
-
-Metadata:
- AWS::CloudFormation::Interface:
- ParameterGroups:
- - Label:
- default: Instance Configuration
- Parameters:
- - InstanceName
- - InstanceVolumeSize
- - InstanceType
- - InstanceOperatingSystem
- - Label:
- default: Code Editor Configuration
- Parameters:
- - CodeEditorUser
- - HomeFolder
- - DevServerBasePath
- - DevServerPort
- - RepoUrl
- - AssetZipS3Path
- - BranchZipS3Path
- - FolderZipS3Path
- ParameterLabels:
- CodeEditorUser:
- default: Code Editor user name
- InstanceName:
- default: Instance name
- InstanceVolumeSize:
- default: Instance volume size
- InstanceType:
- default: Instance type
- InstanceOperatingSystem:
- default: Instance operating system
- HomeFolder:
- default: Code Editor home folder
- DevServerBasePath:
- default: Application base path
- DevServerPort:
- default: Application port
- RepoUrl:
- default: Git repo URL
- AssetZipS3Path:
- default: Asset file S3 path
- BranchZipS3Path:
- default: Branch file S3 path
- FolderZipS3Path:
- default: Folder file S3 path
-
-Mappings:
- ArmImage:
- # aws ssm get-parameters-by-path --path "/aws/service/canonical/ubuntu/" --recursive --query "Parameters[*].Name" > canonical-ami.txt
- # aws ssm get-parameters-by-path --path "/aws/service/ami-amazon-linux-latest/" --recursive --query "Parameters[*].Name" > amazon-ami.txt
- Ubuntu-22:
- ImageId: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/jammy/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
- Ubuntu-24:
- ImageId: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/noble/stable/current/arm64/hvm/ebs-gp3/ami-id}}'
- AmazonLinux-2023:
- ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64}}'
- AmdImage:
- Ubuntu-22:
- ImageId: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/jammy/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
- Ubuntu-24:
- ImageId: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/noble/stable/current/amd64/hvm/ebs-gp3/ami-id}}'
- AmazonLinux-2023:
- ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64}}'
- AWSRegionsPrefixListID:
- # aws ec2 describe-managed-prefix-lists --region | jq -r '.PrefixLists[] | select (.PrefixListName == "com.amazonaws.global.cloudfront.origin-facing") | .PrefixListId'
- ap-northeast-1:
- PrefixList: pl-58a04531
- ap-northeast-2:
- PrefixList: pl-22a6434b
- ap-south-1:
- PrefixList: pl-9aa247f3
- ap-southeast-1:
- PrefixList: pl-31a34658
- ap-southeast-2:
- PrefixList: pl-b8a742d1
- ca-central-1:
- PrefixList: pl-38a64351
- eu-central-1:
- PrefixList: pl-a3a144ca
- eu-north-1:
- PrefixList: pl-fab65393
- eu-west-1:
- PrefixList: pl-4fa04526
- eu-west-2:
- PrefixList: pl-93a247fa
- eu-west-3:
- PrefixList: pl-75b1541c
- sa-east-1:
- PrefixList: pl-5da64334
- us-east-1:
- PrefixList: pl-3b927c52
- us-east-2:
- PrefixList: pl-b6a144df
- us-west-1:
- PrefixList: pl-4ea04527
- us-west-2:
- PrefixList: pl-82a045eb
-
-Resources:
- CodeEditorSecret:
- Type: AWS::SecretsManager::Secret
- Metadata:
- cfn_nag:
- rules_to_suppress:
- - id: W77
- reason: The default KMS Key used by Secrets Manager is appropriate for this password which will be used to log into Code Editor, which has very limited permissions. In addition this secret will not be required to be shared across accounts
- DeletionPolicy: Delete
- UpdateReplacePolicy: Delete
- Properties:
- Name: !Sub
- - ${InstanceName}-${RandomGUID}
- - RandomGUID: !Select [0, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId ]]]]
- Description: Code Editor user details
- GenerateSecretString:
- PasswordLength: 16
- SecretStringTemplate: !Sub '{"username":"${CodeEditorUser}"}'
- GenerateStringKey: 'password'
- ExcludePunctuation: true
-
- SecretPlaintextLambdaRole:
- Type: AWS::IAM::Role
- Properties:
- AssumeRolePolicyDocument:
- Version: 2012-10-17
- Statement:
- - Effect: Allow
- Principal:
- Service: !Sub lambda.${AWS::URLSuffix}
- Action: sts:AssumeRole
- ManagedPolicyArns:
- - !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- Policies:
- - PolicyName: AwsSecretsManager
- PolicyDocument:
- Version: 2012-10-17
- Statement:
- - Effect: Allow
- Action:
- - secretsmanager:GetSecretValue
- Resource: !Ref CodeEditorSecret
-
- SecretPlaintextLambda:
- Type: AWS::Lambda::Function
- Metadata:
- cfn_nag:
- rules_to_suppress:
- - id: W58
- reason: Warning incorrectly reported. The role associated with the Lambda function has the AWSLambdaBasicExecutionRole managed policy attached, which includes permission to write CloudWatch Logs. See https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaBasicExecutionRole.html
- - id: W89
- reason: CloudFormation custom function does not need the scaffolding of a VPC, to do so would add unnecessary complexity
- - id: W92
- reason: CloudFormation custom function does not need reserved concurrent executions, to do so would add unnecessary complexity
- Properties:
- Description: Return the value of the secret
- Handler: index.lambda_handler
- Runtime: python3.13
- MemorySize: 128
- Timeout: 10
- Architectures:
- - arm64
- Role: !GetAtt SecretPlaintextLambdaRole.Arn
- Code:
- ZipFile: |
- import boto3
- import json
- import cfnresponse
- import logging
-
- logger = logging.getLogger()
- logger.setLevel(logging.INFO)
-
- def is_valid_json(json_string):
- logger.debug(f'Calling is_valid_json:{json_string}')
- try:
- json.loads(json_string)
- logger.info(f'Secret is in json format')
- return True
- except json.JSONDecodeError:
- logger.info(f'Secret is in string format')
- return False
-
- def lambda_handler(event, context):
- logger.debug(f'event: {event}')
- logger.debug(f'context: {context}')
- try:
- if event['RequestType'] == 'Delete':
- cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}, reason='No action to take')
- else:
- resource_properties = event['ResourceProperties']
- secret_name = resource_properties['SecretArn']
- secrets_mgr = boto3.client('secretsmanager')
-
- logger.info(f'Getting secret from {secret_name}')
-
- secret = secrets_mgr.get_secret_value(SecretId = secret_name)
- logger.debug(f'secret: {secret}')
- secret_value = secret['SecretString']
-
- responseData = {}
- if is_valid_json(secret_value):
- responseData = secret_value
- else:
- responseData = {'secret': secret_value}
- logger.debug(f'responseData: {responseData}')
- logger.debug(f'type(responseData): {type(responseData)}')
- cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData=json.loads(responseData), reason='OK', noEcho=True)
- except Exception as e:
- logger.error(e)
- cfnresponse.send(event, context, cfnresponse.FAILED, responseData={}, reason=str(e))
-
- SecretPlaintext:
- Type: Custom::SecretPlaintextLambda
- Properties:
- ServiceToken: !GetAtt SecretPlaintextLambda.Arn
- ServiceTimeout: 15
- SecretArn: !Ref CodeEditorSecret
-
- CodeEditorSSMDoc:
- Type: AWS::SSM::Document
- Properties:
- DocumentType: Command
- Content:
- schemaVersion: '2.2'
- description: Bootstrap Code Editor instance
- parameters:
- LinuxFlavor:
- type: String
- default: 'al2023'
- CodeEditorPassword:
- type: String
- default: !Ref AWS::StackId
- # all mainSteps scripts are in in /var/lib/amazon/ssm//document/orchestration///_script.sh
- mainSteps:
- - name: InstallCloudWatchAgent
- action: aws:configurePackage
- inputs:
- name: AmazonCloudWatchAgent
- action: Install
- - name: ConfigureCloudWatchAgent
- action: aws:runDocument
- inputs:
- documentType: SSMDocument
- documentPath: AmazonCloudWatch-ManageAgent
- documentParameters:
- action: configure
- mode: ec2
- optionalConfigurationSource: default
- optionalRestart: 'yes'
- - name: InstallAptPackagesApt
- action: aws:runShellScript
- precondition:
- StringEquals:
- - '{{ LinuxFlavor }}'
- - ubuntu
- inputs:
- timeoutSeconds: 300
- runCommand:
- - '#!/bin/bash'
- - set -euo pipefail
- - dpkg --configure -a
- - apt-get -q update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q apt-utils
- - apt-get -q update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q needrestart unattended-upgrades
- - sed -i 's/#$nrconf{kernelhints} = -1;/$nrconf{kernelhints} = 0;/' /etc/needrestart/needrestart.conf
- - sed -i 's/#$nrconf{verbosity} = 2;/$nrconf{verbosity} = 0;/' /etc/needrestart/needrestart.conf
- - sed -i "s/#\$nrconf{restart} = 'i';/\$nrconf{restart} = 'a';/" /etc/needrestart/needrestart.conf
- - echo "Apt helper packages added. Checking configuration"
- - cat /etc/needrestart/needrestart.conf
- - name: InstallBasePackagesDnf
- action: aws:runShellScript
- precondition:
- StringEquals:
- - '{{ LinuxFlavor }}'
- - al2023
- inputs:
- timeoutSeconds: 300
- runCommand:
- - '#!/bin/bash'
- - set -euo pipefail
- - dnf install -y --allowerasing curl gnupg whois argon2 unzip nginx openssl jq
- - name: InstallBasePackagesApt
- action: aws:runShellScript
- precondition:
- StringEquals:
- - '{{ LinuxFlavor }}'
- - ubuntu
- inputs:
- timeoutSeconds: 300
- runCommand:
- - '#!/bin/bash'
- - set -euo pipefail
- - dpkg --configure -a
- - apt-get -q update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl gnupg whois argon2 unzip nginx openssl locales locales-all apt-transport-https ca-certificates software-properties-common jq
- - name: AddUserDnf
- action: aws:runShellScript
- precondition:
- StringEquals:
- - '{{ LinuxFlavor }}'
- - al2023
- inputs:
- timeoutSeconds: 300
- runCommand:
- - '#!/bin/bash'
- - !Sub |
- echo 'Adding user: ${CodeEditorUser}'
- adduser -c '' ${CodeEditorUser}
- passwd -l ${CodeEditorUser}
- echo "${CodeEditorUser}:{{ CodeEditorPassword }}" | chpasswd
- usermod -aG wheel ${CodeEditorUser}
- sed -i 's/# %wheel/%wheel/g' /etc/sudoers
- - echo "User added. Checking configuration"
- - !Sub getent passwd ${CodeEditorUser}
- - name: AddUserApt
- action: aws:runShellScript
- precondition:
- StringEquals:
- - '{{ LinuxFlavor }}'
- - ubuntu
- inputs:
- timeoutSeconds: 300
- runCommand:
- - '#!/bin/bash'
- - dpkg --configure -a
- - !Sub |
- if [[ "${CodeEditorUser}" == "ubuntu" ]]
- then
- echo 'Using existing user: ${CodeEditorUser}'
- else
- echo 'Adding user: ${CodeEditorUser}'
- adduser --disabled-password --gecos '' ${CodeEditorUser}
- echo "${CodeEditorUser}:{{ CodeEditorPassword }}" | chpasswd
- usermod -aG sudo ${CodeEditorUser}
- fi
- - !Sub |
- tee /etc/sudoers.d/91-vscode-user <> /etc/environment
- - echo LC_ALL=en_US.UTF-8 >> /etc/environment
- - !Sub echo 'PATH=$PATH:/home/${CodeEditorUser}/.local/bin' >> /home/${CodeEditorUser}/.bashrc
- - !Sub echo 'export PATH' >> /home/${CodeEditorUser}/.bashrc
- - !Sub echo 'export AWS_REGION=${AWS::Region}' >> /home/${CodeEditorUser}/.bashrc
- - !Sub echo 'export AWS_ACCOUNTID=${AWS::AccountId}' >> /home/${CodeEditorUser}/.bashrc
- - !Sub echo 'export NEXT_TELEMETRY_DISABLED=1' >> /home/${CodeEditorUser}/.bashrc
- - !Sub echo "export PS1='\[\033[01;32m\]\u:\[\033[01;34m\]\w\[\033[00m\]\$ '" >> /home/${CodeEditorUser}/.bashrc
- - !Sub chown -R ${CodeEditorUser}:${CodeEditorUser} /home/${CodeEditorUser}
- - name: InstallAWSCLI
- action: aws:runShellScript
- inputs:
- timeoutSeconds: 300
- runCommand:
- - '#!/bin/bash'
- - set -euo pipefail
- - mkdir -p /tmp
- - curl -fsSL https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip -o /tmp/aws-cli.zip
- - !Sub chown -R ${CodeEditorUser}:${CodeEditorUser} /tmp/aws-cli.zip
- - unzip -q -d /tmp /tmp/aws-cli.zip
- - sudo /tmp/aws/install
- - rm -rf /tmp/aws
- - echo "AWS CLI installed. Checking configuration"
- - aws --version
- - name: InstallGitDnf
- action: aws:runShellScript
- precondition:
- StringEquals:
- - '{{ LinuxFlavor }}'
- - al2023
- inputs:
- timeoutSeconds: 300
- runCommand:
- - '#!/bin/bash'
- - set -euo pipefail
- - dnf install -y git
- - !Sub sudo -u ${CodeEditorUser} git config --global user.email "participant@example.com"
- - !Sub sudo -u ${CodeEditorUser} git config --global user.name "Workshop Participant"
- - !Sub sudo -u ${CodeEditorUser} git config --global init.defaultBranch "main"
- - echo "Git installed. Checking configuration"
- - git --version
- - name: InstallGitApt
- action: aws:runShellScript
- precondition:
- StringEquals:
- - '{{ LinuxFlavor }}'
- - ubuntu
- inputs:
- timeoutSeconds: 300
- runCommand:
- - '#!/bin/bash'
- - set -euo pipefail
- - dpkg --configure -a
- - add-apt-repository ppa:git-core/ppa
- - apt-get -q update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q git
- - !Sub sudo -u ${CodeEditorUser} git config --global user.email "participant@example.com"
- - !Sub sudo -u ${CodeEditorUser} git config --global user.name "Workshop Participant"
- - !Sub sudo -u ${CodeEditorUser} git config --global init.defaultBranch "main"
- - echo "Git installed. Checking configuration"
- - git --version
- - name: CloneRepo
- action: aws:runShellScript
- inputs:
- timeoutSeconds: 600
- runCommand:
- - '#!/bin/bash'
- - !Sub |
- if [[ -z "${RepoUrl}" ]]
- then
- echo "No Repo"
- else
- mkdir -p ${HomeFolder} && chown -R ${CodeEditorUser}:${CodeEditorUser} ${HomeFolder}
- sudo -u ${CodeEditorUser} git clone ${RepoUrl} ${HomeFolder}
- echo "Repo ${RepoUrl} cloned. Checking configuration"
- ls -la ${HomeFolder}
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} remote -v
- fi
- - name: DownloadAssets
- action: aws:runShellScript
- inputs:
- timeoutSeconds: 600
- runCommand:
- - '#!/bin/bash'
- - !Sub |
- if [[ -z "${AssetZipS3Path}" ]]
- then
- echo "No assets"
- else
- mkdir -p ${HomeFolder} && chown -R ${CodeEditorUser}:${CodeEditorUser} ${HomeFolder}
- mkdir -p /tmp
- aws s3 cp s3://${AssetZipS3Path} /tmp/asset.zip
- chown -R ${CodeEditorUser}:${CodeEditorUser} /tmp/asset.zip
- unzip -o /tmp/asset.zip -d ${HomeFolder}
- chown -R ${CodeEditorUser}:${CodeEditorUser} ${HomeFolder}
- if [[ -d ${HomeFolder}/.git ]] # Indicates that a repo has been cloned
- then
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} add .
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} commit -m 'Workshop commit'
- else
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} init
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} add .
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} commit -m 'Initial commit'
- fi
- echo "Assets downloaded. Checking configuration: ${HomeFolder}"
- ls -la ${HomeFolder}
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} branch
- fi
- - name: DownloadFolders
- action: aws:runShellScript
- inputs:
- timeoutSeconds: 600
- runCommand:
- - '#!/bin/bash'
- - !Sub |
- if [[ -z "${FolderZipS3Path}" ]]
- then
- echo "No folders"
- else
- rm -rf /tmp/folder
- mkdir -p /tmp/folder && chown -R ${CodeEditorUser}:${CodeEditorUser} /tmp/folder
- aws s3 cp s3://${FolderZipS3Path} /tmp/asset-folder.zip
- chown -R ${CodeEditorUser}:${CodeEditorUser} /tmp/asset-folder.zip
- unzip -o /tmp/asset-folder.zip -d /tmp/folder
- chown -R ${CodeEditorUser}:${CodeEditorUser} /tmp/folder
- mkdir -p ${HomeFolder} && chown -R ${CodeEditorUser}:${CodeEditorUser} ${HomeFolder}
- cd "${HomeFolder}" && cd ..
- if [[ $(pwd) == "/" ]]
- then
- targetRootFolder=""
- else
- targetRootFolder=$(pwd)
- chown -R ${CodeEditorUser}:${CodeEditorUser} .
- fi
- find "/tmp/folder" -maxdepth 1 -mindepth 1 -type d | while read sourceFolder; do
- folder="$(basename $sourceFolder)"
- echo "Processing folder: $folder"
- targetFolder=$targetRootFolder/$folder
- if [[ $targetRootFolder == "" ]]
- then
- mv $sourceFolder /
- else
- mv $sourceFolder $targetRootFolder
- fi
- chown -R ${CodeEditorUser}:${CodeEditorUser} $targetFolder
- sudo -u ${CodeEditorUser} git -C $targetFolder init
- sudo -u ${CodeEditorUser} git -C $targetFolder add .
- sudo -u ${CodeEditorUser} git -C $targetFolder commit -m "Initial commit"
- echo "Folder downloaded. Checking configuration: $targetFolder"
- ls -la $targetFolder
- done
- rm -rf /tmp/folder
- fi
- - name: DownloadBranches
- action: aws:runShellScript
- inputs:
- timeoutSeconds: 600
- runCommand:
- - '#!/bin/bash'
- - !Sub |
- if [[ -z "${BranchZipS3Path}" ]]
- then
- echo "No branches"
- else
- rm -rf /tmp/branch
- rm -rf /tmp/git
- mkdir -p /tmp/branch && chown -R ${CodeEditorUser}:${CodeEditorUser} /tmp/branch
- mkdir -p /tmp/git && chown -R ${CodeEditorUser}:${CodeEditorUser} /tmp/git
- aws s3 cp s3://${BranchZipS3Path} /tmp/asset-branch.zip
- chown -R ${CodeEditorUser}:${CodeEditorUser} /tmp/asset-branch.zip
- unzip -o /tmp/asset-branch.zip -d /tmp/branch
- chown -R ${CodeEditorUser}:${CodeEditorUser} /tmp/branch
- mkdir -p ${HomeFolder} && chown -R ${CodeEditorUser}:${CodeEditorUser} ${HomeFolder}
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} init
- mv ${HomeFolder}/.git /tmp/git
- rm -rf ${HomeFolder}
- mkdir -p ${HomeFolder} && chown -R ${CodeEditorUser}:${CodeEditorUser} ${HomeFolder}
- mv /tmp/git/.git ${HomeFolder}
- find /tmp/branch -maxdepth 1 -mindepth 1 -type d | while read sourceFolder; do
- branch="$(basename $sourceFolder)"
- echo "Processing branch: $branch"
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} checkout -b $branch 2>&1
- cp -a $sourceFolder/. ${HomeFolder}
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} add .
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} commit -m "Initial commit $branch"
- mv ${HomeFolder}/.git /tmp/git
- rm -rf ${HomeFolder}
- mkdir ${HomeFolder} && chown -R ${CodeEditorUser}:${CodeEditorUser} ${HomeFolder}
- mv /tmp/git/.git ${HomeFolder}
- done
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} checkout main 2>&1
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} restore .
- rm -rf /tmp/branch
- rm -rf /tmp/git
- echo "Branches downloaded. Checking configuration: $HomeFolder"
- sudo -u ${CodeEditorUser} git -C ${HomeFolder} branch
- ls -la ${HomeFolder}
- fi
- - name: InstallCodeEditor
- action: aws:runShellScript
- inputs:
- timeoutSeconds: 600
- runCommand:
- - '#!/bin/bash'
- - set -euo pipefail
- - !Sub export CodeEditorUser=${CodeEditorUser}
- - curl -fsSL https://code-editor.amazonaws.com/content/code-editor-server/dist/aws-workshop-studio/install.sh | bash -s -- 2>&1 || { echo "Code Editor installation failed"; exit 1; }
- - name: ConfigureNginx
- action: aws:runShellScript
- inputs:
- timeoutSeconds: 600
- runCommand:
- - '#!/bin/bash'
- - set -euo pipefail
- - echo "Configuring nginx..."
- - !Sub |
- tee /etc/nginx/conf.d/code-editor.conf <&1
- - systemctl status nginx
- - name: ConfigureAuthToken
- action: aws:runShellScript
- inputs:
- timeoutSeconds: 600
- runCommand:
- - !Sub |
- sudo -u ${CodeEditorUser} --login mkdir -p /home/${CodeEditorUser}/.code-editor-server/data
- sudo -u ${CodeEditorUser} --login touch /home/${CodeEditorUser}/.code-editor-server/data/token
- # token format: /^[0-9A-Za-z_-]+$/
- echo -n "{{ CodeEditorPassword }}" > /home/${CodeEditorUser}/.code-editor-server/data/token
- - name: CreateCodeEditorSettings
- action: aws:runShellScript
- inputs:
- timeoutSeconds: 600
- runCommand:
- - !Sub sudo -u ${CodeEditorUser} --login mkdir -p /home/${CodeEditorUser}/.code-editor-server/data/User
- - !Sub sudo -u ${CodeEditorUser} --login touch /home/${CodeEditorUser}/.code-editor-server/data/User/settings.json
- - !Sub touch /home/${CodeEditorUser}/.hushlogin
- - !Sub mkdir -p ${HomeFolder} && chown -R ${CodeEditorUser}:${CodeEditorUser} ${HomeFolder}
- - !Sub |
- tee /home/${CodeEditorUser}/.code-editor-server/data/User/settings.json <&1; then
- echo "Failed to install $extension_name on attempt $((retry_count + 1))"
- fi
-
- if sudo -u ${CodeEditorUser} --login code-editor-server --list-extensions | grep -qi "$extension_name"; then
- echo "Successfully installed $extension_name"
- return
- else
- echo "Extension $extension_name not found in installed list"
- fi
-
- retry_count=$((retry_count + 1))
- if [ $retry_count -lt $max_retries ]; then
- echo "Retrying in 5 seconds..."
- sleep 5
- fi
- done
-
- echo "Failed to install $extension_name after $max_retries attempts"
- return
- }
- install_extension "AmazonWebServices.aws-toolkit-vscode"
- install_extension "AmazonWebServices.amazon-q-vscode"
- install_extension "ms-vscode.live-server"
- install_extension "synedra.auto-run-command"
- - !Sub chown -R ${CodeEditorUser}:${CodeEditorUser} /home/${CodeEditorUser}
- - echo "Code Editor installed. Checking configuration"
- - !Sub sudo -u ${CodeEditorUser} --login code-editor-server -v
- - !Sub systemctl status code-editor@${CodeEditorUser}
-# Install optional packages here - any of these blocks can be deleted if that software is not required for the workshop
-# Install Workshop specific packages here
-
- SSMDocLambdaRole:
- Type: AWS::IAM::Role
- Metadata:
- cfn_nag:
- rules_to_suppress:
- - id: W11
- reason: The Amazon EC2 ssm:*CommandInvocation API actions do not support resource-level permissions, so you cannot control which individual resources users can view in the console. Therefore, the * wildcard is necessary in the Resource element. See https://docs.aws.amazon.com/service-authorization/latest/reference/list_awssystemsmanager.html
- Properties:
- AssumeRolePolicyDocument:
- Version: 2012-10-17
- Statement:
- - Effect: Allow
- Principal:
- Service: !Sub lambda.${AWS::URLSuffix}
- Action: sts:AssumeRole
- ManagedPolicyArns:
- - !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- Policies:
- - PolicyName: SSMDocOnEC2
- PolicyDocument:
- Version: 2012-10-17
- Statement:
- - Effect: Allow
- Action:
- - ssm:SendCommand
- Resource:
- - !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:document/${CodeEditorSSMDoc}
- - !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:document/AmazonCloudWatch-ManageAgent
- - !Sub arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/${CodeEditorInstance}
- - Effect: Allow
- Action:
- - ssm:ListCommandInvocations
- - ssm:GetCommandInvocation
- Resource: '*'
-
- RunSSMDocLambda:
- Type: AWS::Lambda::Function
- Metadata:
- cfn_nag:
- rules_to_suppress:
- - id: W58
- reason: Warning incorrectly reported. The role associated with the Lambda function has the AWSLambdaBasicExecutionRole managed policy attached, which includes permission to write CloudWatch Logs. See https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaBasicExecutionRole.html
- - id: W89
- reason: CloudFormation custom function does not need the scaffolding of a VPC, to do so would add unnecessary complexity
- - id: W92
- reason: CloudFormation custom function does not need reserved concurrent executions, to do so would add unnecessary complexity
- Properties:
- Description: Run SSM document on EC2 instance
- Handler: index.lambda_handler
- Runtime: python3.13
- MemorySize: 128
- Timeout: 600
- Environment:
- Variables:
- RetrySleep: 2900
- AbortTimeRemaining: 3200
- Architectures:
- - arm64
- Role: !GetAtt SSMDocLambdaRole.Arn
- Code:
- ZipFile: |
- import boto3
- import cfnresponse
- import logging
- import time
- import os
-
- logger = logging.getLogger()
- logger.setLevel(logging.INFO)
-
- def lambda_handler(event, context):
- logger.debug(f'event: {event}')
- logger.debug(f'context: {context}')
-
- if event['RequestType'] != 'Create':
- cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}, reason='No action to take')
- else:
- sleep_ms = int(os.environ.get('RetrySleep'))
- abort_time_remaining_ms = int(os.environ.get('AbortTimeRemaining'))
- resource_properties = event['ResourceProperties']
- instance_id = resource_properties['InstanceId']
- document_name = resource_properties['DocumentName']
- cloudwatch_log_group_name = resource_properties['CloudWatchLogGroupName']
-
- logger.info(f'Running SSM Document {document_name} on EC2 instance {instance_id}. Logging to {cloudwatch_log_group_name}')
-
- del resource_properties['ServiceToken']
- if 'ServiceTimeout' in resource_properties:
- del resource_properties['ServiceTimeout']
- del resource_properties['InstanceId']
- del resource_properties['DocumentName']
- del resource_properties['CloudWatchLogGroupName']
- if 'PhysicalResourceId' in resource_properties:
- del resource_properties['PhysicalResourceId']
-
- logger.debug(f'resource_properties filtered: {resource_properties}')
-
- parameters = {}
- for key, value in resource_properties.items():
- parameters[key] = [value]
-
- logger.debug(f'parameters: {parameters}')
-
- retry = True
- attempt_no = 0
- time_remaining_ms = context.get_remaining_time_in_millis()
-
- ssm = boto3.client('ssm')
-
- while (retry == True):
- attempt_no += 1
- logger.info(f'Attempt: {attempt_no}. Time Remaining: {time_remaining_ms/1000}s')
- try:
- response = ssm.send_command(
- InstanceIds = [instance_id],
- DocumentName = document_name,
- CloudWatchOutputConfig = {'CloudWatchLogGroupName': cloudwatch_log_group_name, 'CloudWatchOutputEnabled': True},
- Parameters = parameters
- )
- logger.debug(f'response: {response}')
- command_id = response['Command']['CommandId']
- responseData = {'CommandId': command_id}
- cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, reason='OK')
- retry = False
-
- except ssm.exceptions.InvalidInstanceId as e:
- time_remaining_ms = context.get_remaining_time_in_millis()
- if (time_remaining_ms > abort_time_remaining_ms):
- logger.info(f'Instance {instance_id} not ready. Sleeping: {sleep_ms/1000}s')
- time.sleep(sleep_ms/1000)
- retry = True
- else:
- logger.info(f'Instance {instance_id} not ready, timed out. Time remaining {time_remaining_ms/1000}s < Abort time remaining {abort_time_remaining_ms/1000}s')
- logger.error(e, exc_info=True)
- cfnresponse.send(event, context, cfnresponse.FAILED, responseData={}, reason='Timed out. Time remaining: ' + str(time_remaining_ms/1000) + 's < Abort time remaining: ' + str(abort_time_remaining_ms/1000) + 's')
- retry = False
-
- except Exception as e:
- logger.error(e, exc_info=True)
- cfnresponse.send(event, context, cfnresponse.FAILED, responseData={}, reason=str(e))
- retry = False
-
- RunCodeEditorSSMDoc:
- Type: Custom::RunSSMDocLambda
- Properties:
- ServiceToken: !GetAtt RunSSMDocLambda.Arn
- ServiceTimeout: 305
- InstanceId: !Ref CodeEditorInstance
- DocumentName: !Ref CodeEditorSSMDoc
- CloudWatchLogGroupName: !Sub /aws/ssm/${CodeEditorSSMDoc}
- CodeEditorPassword: !GetAtt SecretPlaintext.password
- LinuxFlavor: !If [IsAL2023, 'al2023', 'ubuntu']
-
- CodeEditorInstanceBootstrapRole:
- Type: AWS::IAM::Role
- Properties:
- AssumeRolePolicyDocument:
- Version: 2012-10-17
- Statement:
- - Effect: Allow
- Principal:
- Service:
- - !Sub ec2.${AWS::URLSuffix}
- - !Sub ssm.${AWS::URLSuffix}
- Action: sts:AssumeRole
- ManagedPolicyArns:
- - !Sub arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore
- - !Sub arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy
- - !Sub arn:${AWS::Partition}:iam::aws:policy/AmazonQDeveloperAccess
- - !Sub arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess
-
- CodeEditorInstanceProfile:
- Type: AWS::IAM::InstanceProfile
- Properties:
- Roles:
- - !Ref CodeEditorInstanceBootstrapRole
-
- CodeEditorInstance:
- Type: AWS::EC2::Instance
- Properties:
- ImageId: !If
- - IsGraviton
- - !FindInMap [ArmImage, !Ref InstanceOperatingSystem, ImageId]
- - !FindInMap [AmdImage, !Ref InstanceOperatingSystem, ImageId]
- InstanceType: !Ref InstanceType
- BlockDeviceMappings:
- - DeviceName: !If [IsAL2023, /dev/xvda, /dev/sda1]
- Ebs:
- VolumeSize: !Ref InstanceVolumeSize
- VolumeType: gp3
- DeleteOnTermination: true
- Encrypted: true
- Monitoring: true
- SecurityGroupIds:
- - !Ref SecurityGroup
- IamInstanceProfile: !Ref CodeEditorInstanceProfile
- UserData:
- Fn::Base64: !Sub |
- #cloud-config
- hostname: ${InstanceName}
- runcmd:
- - mkdir -p ${HomeFolder} && chown -R ${CodeEditorUser}:${CodeEditorUser} ${HomeFolder}
- Tags:
- - Key: Name
- Value: !Ref InstanceName
-
- CodeEditorInstanceEIP:
- Type: AWS::EC2::EIP
- Properties:
- Domain: vpc
-
- ElasticIPAssociation:
- Type: AWS::EC2::EIPAssociation
- Properties:
- AllocationId: !GetAtt CodeEditorInstanceEIP.AllocationId
- InstanceId: !Ref CodeEditorInstance
-
- CodeEditorInstanceCachePolicy:
- Type: AWS::CloudFront::CachePolicy
- Properties:
- CachePolicyConfig:
- DefaultTTL: 86400
- MaxTTL: 31536000
- MinTTL: 1
- Name: !Sub
- - ${InstanceName}-${RandomGUID}
- - RandomGUID: !Select [0, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId ]]]]
- ParametersInCacheKeyAndForwardedToOrigin:
- CookiesConfig:
- CookieBehavior: all
- EnableAcceptEncodingGzip: False
- HeadersConfig:
- HeaderBehavior: whitelist
- Headers:
- - Accept-Charset
- - Authorization
- - Origin
- - Accept
- - Referer
- - Host
- - Accept-Language
- - Accept-Encoding
- - Accept-Datetime
- QueryStringsConfig:
- QueryStringBehavior: all
-
- CloudFrontDistribution:
- Type: AWS::CloudFront::Distribution
- DependsOn: ElasticIPAssociation
- Metadata:
- cfn_nag:
- rules_to_suppress:
- - id: W10
- reason: CloudFront Distribution access logging would require setup of an S3 bucket and changes in IAM, which add unnecessary complexity to the template
- - id: W70
- reason: Workshop Studio does not include a domain that can be used to provision a certificate, so it is not possible to setup TLS. See PFR EE-6016
- Properties:
- DistributionConfig:
- Enabled: True
- HttpVersion: http2and3
- CacheBehaviors:
- - AllowedMethods:
- - GET
- - HEAD
- - OPTIONS
- - PUT
- - PATCH
- - POST
- - DELETE
- CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html#managed-cache-policy-caching-disabled
- Compress: False
- OriginRequestPolicyId: 216adef6-5c7f-47e4-b989-5492eafa07d3 # Managed-AllViewer - see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#:~:text=When%20using%20AWS,47e4%2Db989%2D5492eafa07d3
- TargetOriginId: !Sub CloudFront-${AWS::StackName}
- ViewerProtocolPolicy: allow-all
- PathPattern: '/proxy/*'
- DefaultCacheBehavior:
- AllowedMethods:
- - GET
- - HEAD
- - OPTIONS
- - PUT
- - PATCH
- - POST
- - DELETE
- CachePolicyId: !Ref CodeEditorInstanceCachePolicy
- OriginRequestPolicyId: 216adef6-5c7f-47e4-b989-5492eafa07d3 # Managed-AllViewer - see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#:~:text=When%20using%20AWS,47e4%2Db989%2D5492eafa07d3
- TargetOriginId: !Sub CloudFront-${AWS::StackName}
- ViewerProtocolPolicy: allow-all
- Origins:
- - DomainName: !GetAtt CodeEditorInstance.PublicDnsName
- Id: !Sub CloudFront-${AWS::StackName}
- CustomOriginConfig:
- OriginProtocolPolicy: http-only
-
- SecurityGroup:
- Type: AWS::EC2::SecurityGroup
- Metadata:
- cfn_nag:
- rules_to_suppress:
- - id: F1000
- reason: All outbound traffic should be allowed from this instance. The EC2 instance is provisioned in the default VPC, which already has this egress rule, and it is not possible to duplicate this egress rule in the default VPC
- Properties:
- GroupDescription: Security Group for Code Editor - only allow CloudFront ingress
- SecurityGroupIngress:
- - Description: Allow HTTP from com.amazonaws.global.cloudfront.origin-facing
- IpProtocol: tcp
- FromPort: 80
- ToPort: 80
- SourcePrefixListId: !FindInMap [AWSRegionsPrefixListID, !Ref 'AWS::Region', PrefixList]
-
- CodeEditorHealthCheckLambdaRole:
- Type: AWS::IAM::Role
- Properties:
- AssumeRolePolicyDocument:
- Version: 2012-10-17
- Statement:
- - Effect: Allow
- Principal:
- Service: !Sub lambda.${AWS::URLSuffix}
- Action: sts:AssumeRole
- ManagedPolicyArns:
- - !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
-
- CodeEditorHealthCheckLambda:
- Type: AWS::Lambda::Function
- Metadata:
- cfn_nag:
- rules_to_suppress:
- - id: W58
- reason: Warning incorrectly reported. The role associated with the Lambda function has the AWSLambdaBasicExecutionRole managed policy attached, which includes permission to write CloudWatch Logs. See https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaBasicExecutionRole.html
- - id: W89
- reason: CloudFormation custom function does not need the scaffolding of a VPC, to do so would add unnecessary complexity
- - id: W92
- reason: CloudFormation custom function does not need reserved concurrent executions, to do so would add unnecessary complexity
- Properties:
- Description: Run health check on Code Editor instance
- Handler: index.lambda_handler
- Runtime: python3.13
- MemorySize: 128
- Timeout: 600
- Environment:
- Variables:
- RetrySleep: 2900
- AbortTimeRemaining: 5000
- Architectures:
- - arm64
- Role: !GetAtt CodeEditorHealthCheckLambdaRole.Arn
- Code:
- ZipFile: |
- import json
- import cfnresponse
- import logging
- import time
- import os
- import http.client
- from urllib.parse import urlparse
-
- logger = logging.getLogger()
- logger.setLevel(logging.INFO)
-
- def healthURLOk(url):
- # Using try block to catch connection errors and JSON conversion errors
- try:
- logger.debug(f'url: {url}')
- parsed_url = urlparse(url)
- if parsed_url.scheme == 'https':
- logger.debug(f'Trying https: {parsed_url.netloc}. Parsed_url: {parsed_url}')
- conn = http.client.HTTPSConnection(parsed_url.netloc)
- else:
- logger.debug(f'Trying http: {parsed_url.netloc}. Parsed_url: {parsed_url}')
- conn = http.client.HTTPConnection(parsed_url.netloc)
- conn.request("GET", parsed_url.path or "/")
- response = conn.getresponse()
- logger.debug(f'response: {response}')
- logger.debug(f'response.status: {response.status}')
- content = response.read()
- logger.debug(f'content: {content}')
- # This will be true for any return code below 4xx (so 3xx and 2xx)
- if 200 <= response.status < 400:
- response_dict = json.loads(content.decode('utf-8'))
- logger.debug(f'response_dict: {response_dict}')
- # Checking for expected keys and if the key has the expected value
- if 'hasActiveConnections' in response_dict:
- # Response code 200 and correct JSON returned
- logger.info('Health check OK.')
- return True
- else:
- # Response code 200 but the 'hasActiveConnections' key is not present
- logger.info(f'Health check failed. Response: {response_dict}')
- return False
- else:
- # Response was not ok (error 4xx or 5xx)
- logger.info(f'Healthcheck failed. Return code: {response.status}')
- return False
-
- except http.client.HTTPException as e:
- # URL malformed or endpoint not ready yet, this should only happen if we can not DNS resolve the URL
- logger.error(e, exc_info=True)
- logger.error(f'Healthcheck failed: HTTP Exception. URL invalid and/or endpoint not ready yet')
- return False
-
- except json.decoder.JSONDecodeError as e:
- # The response we got was not a properly formatted JSON
- logger.error(e, exc_info=True)
- logger.info(f'Healthcheck failed: Did not get JSON object from URL as expected')
- return False
-
- except Exception as e:
- logger.error(e, exc_info=True)
- logger.info(f'Healthcheck failed: General error')
- return False
-
- finally:
- if 'conn' in locals():
- conn.close()
-
- def is_valid_json(json_string):
- try:
- json.loads(json_string)
- return True
- except ValueError:
- return False
-
- def lambda_handler(event, context):
- logger.debug(f'event: {event}')
- logger.debug(f'context: {context}')
- try:
- if event['RequestType'] != 'Create':
- cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}, reason='No action to take')
- else:
- sleep_ms = int(os.environ.get('RetrySleep'))
- abort_time_remaining_ms = int(os.environ.get('AbortTimeRemaining'))
- resource_properties = event['ResourceProperties']
- url = resource_properties['Url']
-
- logger.info(f'Testing url: {url}')
-
- time_remaining_ms = context.get_remaining_time_in_millis()
- attempt_no = 0
- health_check = False
- while (attempt_no == 0 or (time_remaining_ms > abort_time_remaining_ms and not health_check)):
- attempt_no += 1
- logger.info(f'Attempt: {attempt_no}. Time Remaining: {time_remaining_ms/1000}s')
- health_check = healthURLOk(url)
- if not health_check:
- logger.debug(f'Healthcheck failed. Sleeping: {sleep_ms/1000}s')
- time.sleep(sleep_ms/1000)
- time_remaining_ms = context.get_remaining_time_in_millis()
- if health_check:
- logger.info(f'Health check successful. Attempts: {attempt_no}. Time Remaining: {time_remaining_ms/1000}s')
- cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}, reason='Code Editor healthcheck successful')
- else:
- logger.info(f'Health check failed. Timed out. Attempts: {attempt_no}. Time remaining {time_remaining_ms/1000}s < Abort time remaining {abort_time_remaining_ms/1000}s')
- cfnresponse.send(event, context, cfnresponse.FAILED, responseData={}, reason='Code Editor healthcheck failed. Timed out after ' + str(attempt_no) + ' attempts')
- logger.info(f'Response sent')
-
- except Exception as e:
- logger.error(e, exc_info=True)
- logger.info(f'Health check failed. General exception')
- cfnresponse.send(event, context, cfnresponse.FAILED, responseData={}, reason=str(e))
-
- Healthcheck:
- Type: Custom::CodeEditorHealthCheckLambda
- Properties:
- ServiceToken: !GetAtt CodeEditorHealthCheckLambda.Arn
- ServiceTimeout: 610
- Url: !Sub https://${CloudFrontDistribution.DomainName}/healthz
-
- CheckSSMDocLambda:
- Type: AWS::Lambda::Function
- Metadata:
- cfn_nag:
- rules_to_suppress:
- - id: W58
- reason: Warning incorrectly reported. The role associated with the Lambda function has the AWSLambdaBasicExecutionRole managed policy attached, which includes permission to write CloudWatch Logs. See https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaBasicExecutionRole.html
- - id: W89
- reason: CloudFormation custom function does not need the scaffolding of a VPC, to do so would add unnecessary complexity
- - id: W92
- reason: CloudFormation custom function does not need reserved concurrent executions, to do so would add unnecessary complexity
- Properties:
- Description: Check SSM document on EC2 instance
- Handler: index.lambda_handler
- Runtime: python3.13
- MemorySize: 128
- Timeout: 600
- Environment:
- Variables:
- RetrySleep: 2900
- AbortTimeRemaining: 5000
- Architectures:
- - arm64
- Role: !GetAtt SSMDocLambdaRole.Arn
- Code:
- ZipFile: |
- import boto3
- import cfnresponse
- import logging
- import time
- import os
-
- logger = logging.getLogger()
- logger.setLevel(logging.INFO)
-
- def lambda_handler(event, context):
- logger.debug(f'event: {event}')
- logger.debug(f'context: {context}')
-
- if event['RequestType'] != 'Create':
- cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}, reason='No action to take')
- else:
- sleep_ms = int(os.environ.get('RetrySleep'))
- abort_time_remaining_ms = int(os.environ.get('AbortTimeRemaining'))
- resource_properties = event['ResourceProperties']
- instance_id = resource_properties['InstanceId']
- document_name = resource_properties['DocumentName']
-
- logger.info(f'Checking SSM Document {document_name} on EC2 instance {instance_id}')
-
- retry = True
- attempt_no = 0
- time_remaining_ms = context.get_remaining_time_in_millis()
-
- ssm = boto3.client('ssm')
-
- while (retry == True):
- attempt_no += 1
- logger.info(f'Attempt: {attempt_no}. Time Remaining: {time_remaining_ms/1000}s')
- try:
- # check to see if document has completed running on instance
- response = ssm.list_command_invocations(
- InstanceId=instance_id,
- Details=True
- )
- logger.debug(f'Response: {response}')
- for invocation in response['CommandInvocations']:
- if invocation['DocumentName'] == document_name:
- invocation_status = invocation['Status']
- if invocation_status == 'Success':
- logger.info(f'SSM Document {document_name} on EC2 instance {instance_id} complete. Status: {invocation_status}')
- cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}, reason='OK')
- retry = False
- elif invocation_status == 'Failed' or invocation_status == 'Cancelled' or invocation_status == 'TimedOut':
- logger.info(f'SSM Document {document_name} on EC2 instance {instance_id} failed. Status: {invocation_status}')
- reason = ''
- # Get information on step that failed, otherwise it's cancelled or timeout
- for step in invocation['CommandPlugins']:
- step_name = step['Name']
- step_status = step['Status']
- step_output = step['Output']
- logger.debug(f'Step {step_name} {step_status}: {step_output}')
- if step_status != 'Success':
- try:
- response_step = ssm.get_command_invocation(
- CommandId=invocation['CommandId'],
- InstanceId=instance_id,
- PluginName=step_name
- )
- logger.debug(f'Step details: {response_step}')
- step_output = response_step['StandardErrorContent']
- except Exception as e:
- logger.error(e, exc_info=True)
- logger.info(f'Step {step_name} {step_status}: {step_output}')
- if reason == '':
- reason = f'Step {step_name} {step_status}: {step_output}'
- else:
- reason += f'\nStep {step_name} {step_status}: {step_output}'
- if reason == '':
- reason = f'SSM Document {document_name} on EC2 instance {instance_id} failed. Status: {invocation_status}'
- logger.info(f'{reason}')
- cfnresponse.send(event, context, cfnresponse.FAILED, responseData={}, reason=reason)
- retry = False
- else:
- logger.info(f'SSM Document {document_name} on EC2 instance {instance_id} not yet complete. Status: {invocation_status}')
- retry = True
- if retry == True:
- if (time_remaining_ms > abort_time_remaining_ms):
- logger.info(f'Sleeping: {sleep_ms/1000}s')
- time.sleep(sleep_ms/1000)
- time_remaining_ms = context.get_remaining_time_in_millis()
- else:
- logger.info(f'Time remaining {time_remaining_ms/1000}s < Abort time remaining {abort_time_remaining_ms/1000}s')
- logger.info(f'Aborting check as time remaining {time_remaining_ms/1000}s < Abort time remaining {abort_time_remaining_ms/1000}s')
- cfnresponse.send(event, context, cfnresponse.FAILED, responseData={}, reason='Timed out. Time remaining: ' + str(time_remaining_ms/1000) + 's < Abort time remaining: ' + str(abort_time_remaining_ms/1000) + 's')
- retry = False
- except Exception as e:
- logger.error(e, exc_info=True)
- cfnresponse.send(event, context, cfnresponse.FAILED, responseData={}, reason=str(e))
- retry = False
-
- CheckCodeEditorSSMDoc:
- Type: Custom::CheckSSMDocLambda
- DependsOn: Healthcheck
- Properties:
- ServiceToken: !GetAtt CheckSSMDocLambda.Arn
- ServiceTimeout: 610
- InstanceId: !Ref CodeEditorInstance
- DocumentName: !Ref CodeEditorSSMDoc
-
-Outputs:
- URL:
- Description: Code Editor URL
- Value: !Sub https://${CloudFrontDistribution.DomainName}/?folder=${HomeFolder}&tkn=${SecretPlaintext.password}
diff --git a/static/images/apn-logo.jpg b/static/images/apn-logo.jpg
deleted file mode 100644
index ed7c4292a..000000000
Binary files a/static/images/apn-logo.jpg and /dev/null differ
diff --git a/static/images/aws-open-source.jpg b/static/images/aws-open-source.jpg
deleted file mode 100644
index c1759f391..000000000
Binary files a/static/images/aws-open-source.jpg and /dev/null differ
diff --git a/static/images/chapter.en.png b/static/images/chapter.en.png
deleted file mode 100644
index beab78960..000000000
Binary files a/static/images/chapter.en.png and /dev/null differ
diff --git a/static/intermediate/operations/stack.png b/static/intermediate/operations/stack.png
deleted file mode 100644
index 7bb2b978f..000000000
Binary files a/static/intermediate/operations/stack.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/createstacksetcompletion.ja.png b/static/intermediate/operations/stacksets/createstacksetcompletion.ja.png
deleted file mode 100644
index dd5aff1b7..000000000
Binary files a/static/intermediate/operations/stacksets/createstacksetcompletion.ja.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/createstacksetcompletion.png b/static/intermediate/operations/stacksets/createstacksetcompletion.png
deleted file mode 100644
index e6b4e0605..000000000
Binary files a/static/intermediate/operations/stacksets/createstacksetcompletion.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/exports.ja.png b/static/intermediate/operations/stacksets/exports.ja.png
deleted file mode 100644
index 88fd058be..000000000
Binary files a/static/intermediate/operations/stacksets/exports.ja.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/exports.png b/static/intermediate/operations/stacksets/exports.png
deleted file mode 100644
index 80eba05b3..000000000
Binary files a/static/intermediate/operations/stacksets/exports.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/exportssecuritygroup.ja.png b/static/intermediate/operations/stacksets/exportssecuritygroup.ja.png
deleted file mode 100644
index 6b2ba250f..000000000
Binary files a/static/intermediate/operations/stacksets/exportssecuritygroup.ja.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/exportssecuritygroup.png b/static/intermediate/operations/stacksets/exportssecuritygroup.png
deleted file mode 100644
index 6f70db010..000000000
Binary files a/static/intermediate/operations/stacksets/exportssecuritygroup.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/stackinstances.ja.png b/static/intermediate/operations/stacksets/stackinstances.ja.png
deleted file mode 100644
index bc0424251..000000000
Binary files a/static/intermediate/operations/stacksets/stackinstances.ja.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/stackinstances.png b/static/intermediate/operations/stacksets/stackinstances.png
deleted file mode 100644
index 3795b2a31..000000000
Binary files a/static/intermediate/operations/stacksets/stackinstances.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/stacksetsdeploymentoptions.ja.png b/static/intermediate/operations/stacksets/stacksetsdeploymentoptions.ja.png
deleted file mode 100644
index 372614645..000000000
Binary files a/static/intermediate/operations/stacksets/stacksetsdeploymentoptions.ja.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/stacksetsdeploymentoptions.png b/static/intermediate/operations/stacksets/stacksetsdeploymentoptions.png
deleted file mode 100644
index 50cc2d468..000000000
Binary files a/static/intermediate/operations/stacksets/stacksetsdeploymentoptions.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/stacksetsec2instance.png b/static/intermediate/operations/stacksets/stacksetsec2instance.png
deleted file mode 100644
index 004d0cc2e..000000000
Binary files a/static/intermediate/operations/stacksets/stacksetsec2instance.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/stacksetsecuritygroup.png b/static/intermediate/operations/stacksets/stacksetsecuritygroup.png
deleted file mode 100644
index 0c53c7a43..000000000
Binary files a/static/intermediate/operations/stacksets/stacksetsecuritygroup.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/stacksetsnetworkstack.png b/static/intermediate/operations/stacksets/stacksetsnetworkstack.png
deleted file mode 100644
index d729f9e0f..000000000
Binary files a/static/intermediate/operations/stacksets/stacksetsnetworkstack.png and /dev/null differ
diff --git a/static/intermediate/operations/stacksets/stacksetsoverview.png b/static/intermediate/operations/stacksets/stacksetsoverview.png
deleted file mode 100644
index 0d048b5f7..000000000
Binary files a/static/intermediate/operations/stacksets/stacksetsoverview.png and /dev/null differ
diff --git a/static/intermediate/templates/architecting-templates/architecting-templates-blue-green-diagram.png b/static/intermediate/templates/architecting-templates/architecting-templates-blue-green-diagram.png
deleted file mode 100644
index 2650f46d9..000000000
Binary files a/static/intermediate/templates/architecting-templates/architecting-templates-blue-green-diagram.png and /dev/null differ
diff --git a/static/intermediate/templates/architecting-templates/architecting-templates-infrastructure-diagram.png b/static/intermediate/templates/architecting-templates/architecting-templates-infrastructure-diagram.png
deleted file mode 100644
index 45ed06253..000000000
Binary files a/static/intermediate/templates/architecting-templates/architecting-templates-infrastructure-diagram.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/condition-prod-update.ja.png b/static/intermediate/templates/conditions/condition-prod-update.ja.png
deleted file mode 100644
index 0a0530036..000000000
Binary files a/static/intermediate/templates/conditions/condition-prod-update.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/condition-prod-update.png b/static/intermediate/templates/conditions/condition-prod-update.png
deleted file mode 100644
index 7e0152564..000000000
Binary files a/static/intermediate/templates/conditions/condition-prod-update.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/condition-prod.ja.png b/static/intermediate/templates/conditions/condition-prod.ja.png
deleted file mode 100644
index de514ec4c..000000000
Binary files a/static/intermediate/templates/conditions/condition-prod.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/condition-prod.png b/static/intermediate/templates/conditions/condition-prod.png
deleted file mode 100644
index 60b1887a0..000000000
Binary files a/static/intermediate/templates/conditions/condition-prod.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/condition-test-property.ja.png b/static/intermediate/templates/conditions/condition-test-property.ja.png
deleted file mode 100644
index 16cbb3938..000000000
Binary files a/static/intermediate/templates/conditions/condition-test-property.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/condition-test-property.png b/static/intermediate/templates/conditions/condition-test-property.png
deleted file mode 100644
index b92dc9a8c..000000000
Binary files a/static/intermediate/templates/conditions/condition-test-property.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/condition-test.ja.png b/static/intermediate/templates/conditions/condition-test.ja.png
deleted file mode 100644
index 9b2b11ab5..000000000
Binary files a/static/intermediate/templates/conditions/condition-test.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/condition-test.png b/static/intermediate/templates/conditions/condition-test.png
deleted file mode 100644
index e9c9331d1..000000000
Binary files a/static/intermediate/templates/conditions/condition-test.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/ec2-instance.ja.png b/static/intermediate/templates/conditions/ec2-instance.ja.png
deleted file mode 100644
index 0cb72386a..000000000
Binary files a/static/intermediate/templates/conditions/ec2-instance.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/conditions/ec2-instance.png b/static/intermediate/templates/conditions/ec2-instance.png
deleted file mode 100644
index 37b15d27b..000000000
Binary files a/static/intermediate/templates/conditions/ec2-instance.png and /dev/null differ
diff --git a/static/intermediate/templates/cross-stacks/ami-id-1.ja.png b/static/intermediate/templates/cross-stacks/ami-id-1.ja.png
deleted file mode 100644
index 8023138c8..000000000
Binary files a/static/intermediate/templates/cross-stacks/ami-id-1.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/cross-stacks/ami-id-1.png b/static/intermediate/templates/cross-stacks/ami-id-1.png
deleted file mode 100644
index d0fd06b9e..000000000
Binary files a/static/intermediate/templates/cross-stacks/ami-id-1.png and /dev/null differ
diff --git a/static/intermediate/templates/cross-stacks/cross-stack-hierarchy.ja.png b/static/intermediate/templates/cross-stacks/cross-stack-hierarchy.ja.png
deleted file mode 100644
index 3f1fb43da..000000000
Binary files a/static/intermediate/templates/cross-stacks/cross-stack-hierarchy.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/cross-stacks/cross-stack-hierarchy.png b/static/intermediate/templates/cross-stacks/cross-stack-hierarchy.png
deleted file mode 100644
index 5b0dea71b..000000000
Binary files a/static/intermediate/templates/cross-stacks/cross-stack-hierarchy.png and /dev/null differ
diff --git a/static/intermediate/templates/cross-stacks/delete-export-before-import.ja.png b/static/intermediate/templates/cross-stacks/delete-export-before-import.ja.png
deleted file mode 100644
index 526f238d3..000000000
Binary files a/static/intermediate/templates/cross-stacks/delete-export-before-import.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/cross-stacks/delete-export-before-import.png b/static/intermediate/templates/cross-stacks/delete-export-before-import.png
deleted file mode 100644
index 65cc3a1e2..000000000
Binary files a/static/intermediate/templates/cross-stacks/delete-export-before-import.png and /dev/null differ
diff --git a/static/intermediate/templates/cross-stacks/ls-architecture.png b/static/intermediate/templates/cross-stacks/ls-architecture.png
deleted file mode 100644
index 537ee89ce..000000000
Binary files a/static/intermediate/templates/cross-stacks/ls-architecture.png and /dev/null differ
diff --git a/static/intermediate/templates/dynamic-references/ec2-console-ami-picker.ja.png b/static/intermediate/templates/dynamic-references/ec2-console-ami-picker.ja.png
deleted file mode 100644
index 62909318b..000000000
Binary files a/static/intermediate/templates/dynamic-references/ec2-console-ami-picker.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/dynamic-references/ec2-console-ami-picker.png b/static/intermediate/templates/dynamic-references/ec2-console-ami-picker.png
deleted file mode 100644
index 04ab85ff9..000000000
Binary files a/static/intermediate/templates/dynamic-references/ec2-console-ami-picker.png and /dev/null differ
diff --git a/static/intermediate/templates/dynamic-references/iam-capability.ja.png b/static/intermediate/templates/dynamic-references/iam-capability.ja.png
deleted file mode 100644
index 51c378d52..000000000
Binary files a/static/intermediate/templates/dynamic-references/iam-capability.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/nested-stacks/ami-id-1.ja.png b/static/intermediate/templates/nested-stacks/ami-id-1.ja.png
deleted file mode 100644
index e9b718fcc..000000000
Binary files a/static/intermediate/templates/nested-stacks/ami-id-1.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/nested-stacks/ami-id-1.png b/static/intermediate/templates/nested-stacks/ami-id-1.png
deleted file mode 100644
index c905e9e10..000000000
Binary files a/static/intermediate/templates/nested-stacks/ami-id-1.png and /dev/null differ
diff --git a/static/intermediate/templates/nested-stacks/iam-capabilities.ja.png b/static/intermediate/templates/nested-stacks/iam-capabilities.ja.png
deleted file mode 100644
index 1a23e905d..000000000
Binary files a/static/intermediate/templates/nested-stacks/iam-capabilities.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/nested-stacks/iam-capabilities.png b/static/intermediate/templates/nested-stacks/iam-capabilities.png
deleted file mode 100644
index ffd04e530..000000000
Binary files a/static/intermediate/templates/nested-stacks/iam-capabilities.png and /dev/null differ
diff --git a/static/intermediate/templates/nested-stacks/nested-stack-hierarchy.ja.png b/static/intermediate/templates/nested-stacks/nested-stack-hierarchy.ja.png
deleted file mode 100644
index 9e6d24dc7..000000000
Binary files a/static/intermediate/templates/nested-stacks/nested-stack-hierarchy.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/nested-stacks/nested-stack-hierarchy.png b/static/intermediate/templates/nested-stacks/nested-stack-hierarchy.png
deleted file mode 100644
index 38bbd07f7..000000000
Binary files a/static/intermediate/templates/nested-stacks/nested-stack-hierarchy.png and /dev/null differ
diff --git a/static/intermediate/templates/nested-stacks/ns-architecture.png b/static/intermediate/templates/nested-stacks/ns-architecture.png
deleted file mode 100644
index 537ee89ce..000000000
Binary files a/static/intermediate/templates/nested-stacks/ns-architecture.png and /dev/null differ
diff --git a/static/intermediate/templates/nested-stacks/website-url-output.ja.png b/static/intermediate/templates/nested-stacks/website-url-output.ja.png
deleted file mode 100644
index 7bd230d6b..000000000
Binary files a/static/intermediate/templates/nested-stacks/website-url-output.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/nested-stacks/website-url-output.png b/static/intermediate/templates/nested-stacks/website-url-output.png
deleted file mode 100644
index 11bc07578..000000000
Binary files a/static/intermediate/templates/nested-stacks/website-url-output.png and /dev/null differ
diff --git a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-dependson.ja.png b/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-dependson.ja.png
deleted file mode 100644
index 027945e2c..000000000
Binary files a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-dependson.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-dependson.png b/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-dependson.png
deleted file mode 100644
index ee60dc46e..000000000
Binary files a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-dependson.png and /dev/null differ
diff --git a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-ref-getatt.ja.png b/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-ref-getatt.ja.png
deleted file mode 100644
index 4de9b8403..000000000
Binary files a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-ref-getatt.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-ref-getatt.png b/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-ref-getatt.png
deleted file mode 100644
index 524a81783..000000000
Binary files a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab-ref-getatt.png and /dev/null differ
diff --git a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab.ja.png b/static/intermediate/templates/resource-dependencies/resource-dependencies-lab.ja.png
deleted file mode 100644
index 0eaa71e8a..000000000
Binary files a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab.ja.png and /dev/null differ
diff --git a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab.png b/static/intermediate/templates/resource-dependencies/resource-dependencies-lab.png
deleted file mode 100644
index 899ab1e90..000000000
Binary files a/static/intermediate/templates/resource-dependencies/resource-dependencies-lab.png and /dev/null differ
diff --git a/static/intermediate/templates/stack.png b/static/intermediate/templates/stack.png
deleted file mode 100644
index 7bb2b978f..000000000
Binary files a/static/intermediate/templates/stack.png and /dev/null differ
diff --git a/static/next-steps/aws-quick-starts/aws-quickstarts.png b/static/next-steps/aws-quick-starts/aws-quickstarts.png
deleted file mode 100644
index 8efde6790..000000000
Binary files a/static/next-steps/aws-quick-starts/aws-quickstarts.png and /dev/null differ
diff --git a/static/prerequisites/account/new-user-1.ja.png b/static/prerequisites/account/new-user-1.ja.png
deleted file mode 100644
index 6982319f1..000000000
Binary files a/static/prerequisites/account/new-user-1.ja.png and /dev/null differ
diff --git a/static/prerequisites/account/new-user-1.png b/static/prerequisites/account/new-user-1.png
deleted file mode 100644
index 8a0ae7672..000000000
Binary files a/static/prerequisites/account/new-user-1.png and /dev/null differ
diff --git a/static/prerequisites/account/new-user-2.ja.png b/static/prerequisites/account/new-user-2.ja.png
deleted file mode 100644
index 041428c93..000000000
Binary files a/static/prerequisites/account/new-user-2.ja.png and /dev/null differ
diff --git a/static/prerequisites/account/new-user-2.png b/static/prerequisites/account/new-user-2.png
deleted file mode 100644
index 2ff0bc3d6..000000000
Binary files a/static/prerequisites/account/new-user-2.png and /dev/null differ
diff --git a/static/prerequisites/account/new-user-3.ja.png b/static/prerequisites/account/new-user-3.ja.png
deleted file mode 100644
index 19d6afa31..000000000
Binary files a/static/prerequisites/account/new-user-3.ja.png and /dev/null differ
diff --git a/static/prerequisites/account/new-user-3.png b/static/prerequisites/account/new-user-3.png
deleted file mode 100644
index c9f3c58b8..000000000
Binary files a/static/prerequisites/account/new-user-3.png and /dev/null differ
diff --git a/static/prerequisites/code-editor/code-editor-url.png b/static/prerequisites/code-editor/code-editor-url.png
deleted file mode 100644
index 138371ece..000000000
Binary files a/static/prerequisites/code-editor/code-editor-url.png and /dev/null differ
diff --git a/static/prerequisites/code-editor/code-server-welcome.png b/static/prerequisites/code-editor/code-server-welcome.png
deleted file mode 100644
index 2295db669..000000000
Binary files a/static/prerequisites/code-editor/code-server-welcome.png and /dev/null differ
diff --git a/static/prerequisites/code-editor/workshop-studio-account-access.png b/static/prerequisites/code-editor/workshop-studio-account-access.png
deleted file mode 100644
index 5d6097cd8..000000000
Binary files a/static/prerequisites/code-editor/workshop-studio-account-access.png and /dev/null differ
diff --git a/static/prerequisites/local-development/vscode.png b/static/prerequisites/local-development/vscode.png
deleted file mode 100644
index 496dc79ba..000000000
Binary files a/static/prerequisites/local-development/vscode.png and /dev/null differ