├── .editorconfig
├── .github
├── dependabot.yml
└── workflows
│ └── codeql-analysis.yml
├── .gitignore
├── .graphqlconfig.yml
├── LICENSE
├── Makefile
├── NOTICE.txt
├── README.md
├── Workshop
├── README.md
├── additional-steps.md
├── clean-up.md
├── images
│ ├── 0-resource-setup.png
│ ├── 0a-cfn-create-change-set.png
│ ├── 0a-cfn-execute-change-set.png
│ ├── 0b-cfn-create-change-set.png
│ ├── 0b-cfn-execute-change-set.png
│ ├── 0b-cfn-outputs.png
│ ├── 0b-code-pipeline.png
│ ├── 0b-webapp.png
│ ├── 1-auto-IAM-role.png
│ ├── 1a-step-easy-name.png
│ ├── 1a-step-lambda-details.png
│ ├── 1b-pick-state-role.png
│ ├── 1b-step-console-preview.png
│ ├── 1c-dashboard.png
│ ├── 1c-execution.png
│ ├── 1c-input-old.png
│ ├── 1c-input.png
│ ├── 1c-start-new-execution.png
│ ├── 1d-edit.png
│ ├── 1d-output-w-resultpath.png
│ ├── 1d-start-execution.png
│ ├── 1d-updated-new-execution.png
│ ├── 2-branching-logic-state-machine.png
│ ├── 2a-reimport-step-easy.png
│ ├── 2a-step-easy-Paralelldetails.png
│ ├── 2a-step-easy-canvas.png
│ ├── 2a-step-easy-choice-ImageTypeCheckChoicedetails.png
│ ├── 2a-step-easy-choice-ImageTypeCheckconfigurecondition.png
│ ├── 2a-step-easy-choice-ImageTypeCheckdetails.png
│ ├── 2a-step-easy-fail-notsupportedimage.png
│ ├── 2a-step-easy-fail-notsupportedimagecatchers.png
│ ├── 2a-step-easy-fail-notsupportedimagedetails.png
│ ├── 2b-step-console-update-preview.png
│ ├── 2c-test-catch-failed.png
│ ├── 2c-test-choice-test-failed.png
│ ├── 2c-test-choice-test-succeeded.png
│ ├── 3-create-statemachine-select-role.png
│ ├── 3-state-machine-parallel-with-output.png
│ ├── 3-state-machine-parallel.png
│ ├── 4-add-step.png
│ ├── 4-final-status.png
│ ├── 4b-step-console-preview.png
│ ├── 4c-ddb-imagemetadata-item.png
│ ├── 4c-ddb-imagemetadata.png
│ ├── 4c-test-choice-test-succeeded.png
│ ├── 5a-enviroment-variables.png
│ ├── 5a-state-machine-arn-new.png
│ ├── 5a-state-machine-arn-newer.png
│ ├── 5a-state-machine-arn.png
│ ├── 5b-s3-event-configuration.png
│ ├── 5b-s3-events.png
│ ├── 5b-s3-incoming-folder.png
│ ├── 5c-s3-object-metadata.png
│ ├── 5c-state-machine-execution.png
│ ├── additional-step-inappropiate.png
│ ├── bucket-sync-state-machine.png
│ ├── bulk-import-album1.png
│ ├── bulk-import-albumlist.png
│ ├── bulk-import-user.png
│ ├── cfn-launch-stack.png
│ ├── cloudwatch-state-machine-metrics.png
│ ├── dynamo-screenshot.png
│ ├── single-step-state-machine.png
│ ├── step-easy-intro.png
│ └── web-app-screenshot.png
├── step-0.md
├── step-1.md
├── step-2.md
├── step-3.md
├── step-4.md
├── step-5.md
└── step-6.md
├── amplify.yml
├── amplify
├── .config
│ └── project-config.json
├── README.md
├── backend
│ ├── api
│ │ └── photoshare
│ │ │ ├── parameters.json
│ │ │ ├── resolvers
│ │ │ ├── Mutation.startSfnExecution.req.vtl
│ │ │ ├── Mutation.startSfnExecution.res.vtl
│ │ │ ├── Query.checkSfnStatus.req.vtl
│ │ │ └── Query.checkSfnStatus.res.vtl
│ │ │ ├── schema.graphql
│ │ │ ├── stacks
│ │ │ └── CustomResources.json
│ │ │ └── transform.conf.json
│ ├── auth
│ │ └── photoshareb143529b
│ │ │ ├── parameters.json
│ │ │ └── photoshareb143529b-cloudformation-template.yml
│ ├── backend-config.json
│ ├── function
│ │ └── S3Trigger984fb593
│ │ │ ├── S3Trigger984fb593-cloudformation-template.json
│ │ │ ├── amplify.state
│ │ │ ├── function-parameters.json
│ │ │ ├── parameters.json
│ │ │ └── src
│ │ │ ├── event.json
│ │ │ ├── index.js
│ │ │ ├── package-lock.json
│ │ │ ├── package.json
│ │ │ └── reference-index.js
│ └── storage
│ │ └── photostorage
│ │ ├── parameters.json
│ │ ├── s3-cloudformation-template.json
│ │ └── storage-params.json
└── team-provider-info.json
├── cloudformation
├── image-processing.serverless.yaml
└── state-machine.asl.json
├── images
├── amplify-select-role.png
├── app-create-album.png
├── app-screenshot.png
├── app-signup-screenshot.png
├── example-album.png
├── example-analyzed.png
├── example-processing.png
├── photo-processing-backend-diagram.png
└── step-function-execution.png
├── lambda-functions
├── extract-image-metadata
│ ├── index.js
│ ├── lambda-sample-output.json
│ ├── local-testing.sh
│ ├── package-lock.json
│ ├── package.json
│ ├── step-sample-input.json
│ └── step-sample-output.json
├── rekognition
│ ├── index.js
│ ├── package-lock.json
│ ├── package.json
│ ├── step-sample-input.json
│ └── step-sample-output.json
├── store-image-metadata
│ ├── index.js
│ ├── package-lock.json
│ ├── package.json
│ └── step-sample-input.json
├── thumbnail
│ ├── index.js
│ ├── lambda-sample-input.json
│ ├── package-lock.json
│ └── package.json
└── transform-metadata
│ ├── index.js
│ ├── lambda-sample-input.json
│ ├── lambda-sample-output.json
│ ├── local-testing.sh
│ ├── package-lock.json
│ └── package.json
├── package-lock.json
└── src
└── react-frontend
├── .eslintcache
├── .gitignore
├── .graphqlconfig.yml
├── README.md
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
└── src
├── App.css
├── App.js
├── App.test.js
├── components
├── Album.js
├── AlbumDetail.js
└── PhotoList.js
├── graphql
├── mutations.js
├── queries.js
├── schema.json
└── subscriptions.js
├── index.css
├── index.js
├── logo.svg
├── serviceWorker.js
├── setupTests.js
└── utils.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | indent_size = 4
6 | charset = utf-8
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 |
10 | [amplify/**.json]
11 | indent_style = space
12 | indent_size = 2
13 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "npm"
4 | directory: "src/react-frontend"
5 | schedule:
6 | interval: "daily"
7 |
8 | - package-ecosystem: "npm"
9 | directory: "lambda-functions/extract-image-metadata"
10 | schedule:
11 | interval: "daily"
12 |
13 | - package-ecosystem: "npm"
14 | directory: "lambda-functions/rekognition"
15 | schedule:
16 | interval: "daily"
17 |
18 | - package-ecosystem: "npm"
19 | directory: "lambda-functions/store-image-metadata"
20 | schedule:
21 | interval: "daily"
22 |
23 | - package-ecosystem: "npm"
24 | directory: "lambda-functions/thumbnail"
25 | schedule:
26 | interval: "daily"
27 |
28 | - package-ecosystem: "npm"
29 | directory: "lambda-functions/transform-metadata"
30 | schedule:
31 | interval: "daily"
32 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ main ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ main ]
20 | schedule:
21 | - cron: '21 9 * * 0'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 |
28 | strategy:
29 | fail-fast: false
30 | matrix:
31 | language: [ 'javascript' ]
32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
33 | # Learn more:
34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
35 |
36 | steps:
37 | - name: Checkout repository
38 | uses: actions/checkout@v2
39 |
40 | # Initializes the CodeQL tools for scanning.
41 | - name: Initialize CodeQL
42 | uses: github/codeql-action/init@v1
43 | with:
44 | languages: ${{ matrix.language }}
45 | # If you wish to specify custom queries, you can do so here or in a config file.
46 | # By default, queries listed here will override any specified in a config file.
47 | # Prefix the list here with "+" to use these queries and those in the config file.
48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
49 |
50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
51 | # If this step fails, then you should remove it and run the build manually (see below)
52 | - name: Autobuild
53 | uses: github/codeql-action/autobuild@v1
54 |
55 | # ℹ️ Command-line programs to run using the OS shell.
56 | # 📚 https://git.io/JvXDl
57 |
58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
59 | # and modify them (or add more) to build your code if your project
60 | # uses a compiled language
61 |
62 | #- run: |
63 | # make bootstrap
64 | # make release
65 |
66 | - name: Perform CodeQL Analysis
67 | uses: github/codeql-action/analyze@v1
68 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Specifies files to intentionally ignore when using Git
2 | # http://git-scm.com/docs/gitignore
3 |
4 | .idea
5 | .DS_Store
6 |
7 | **/node_modules/
8 | */java/
9 | *.iml
10 |
11 | #amplify
12 | amplify/\#current-cloud-backend
13 | amplify/.config/local-*
14 | amplify/mock-data
15 | amplify/backend/amplify-meta.json
16 | amplify/backend/awscloudformation
17 | build/
18 | dist/
19 | node_modules/
20 | aws-exports.js
21 | awsconfiguration.json
22 | amplifyconfiguration.json
23 | amplify-build-config.json
24 | amplify-gradle-config.json
25 | amplifyxc.config
26 | .vscode/targets.log
27 | .vscode/dryrun.log
28 | .vscode/configurationCache.log
--------------------------------------------------------------------------------
/.graphqlconfig.yml:
--------------------------------------------------------------------------------
1 | projects:
2 | photoshare:
3 | schemaPath: src/react-frontend/src/graphql/schema.json
4 | includes:
5 | - src/graphql/**/*.js
6 | excludes:
7 | - ./amplify/**
8 | extensions:
9 | amplify:
10 | codeGenTarget: javascript
11 | generatedFileName: ''
12 | docsFilePath: src/react-frontend/src/graphql
13 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | AWS_BRANCH ?= dev
2 | STACK_NAME ?= photo-sharing
3 | GRAPHQL_API_ID ?= "UNDEFINED"
4 | APPSYNC_URL ?= "UNDEFINED"
5 | PHOTO_BUCKET ?= "UNDEFINED"
6 | TEMPLATE_NAME = image-processing
7 |
8 | target:
9 | $(info ${HELP_MESSAGE})
10 | @exit 0
11 |
12 | init: ##=> Install OS deps and dev tools
13 | $(info [*] Initializing...)
14 | @$(MAKE) _install_os_packages
15 |
16 |
17 | deploy: ##=> Deploy services
18 | $(info [*] Deploying backend...)
19 |
20 | # cd lambda-functions/thumbnail && npm install && \
21 | # cd ../extract-image-metadata && npm install && \
22 | # cd ../store-image-metadata && npm install && \
23 |
24 | cd cloudformation/ && \
25 | sam build --template ${TEMPLATE_NAME}.serverless.yaml && \
26 | sam package \
27 | --s3-bucket ${DEPLOYMENT_BUCKET_NAME} \
28 | --s3-prefix photo-sharing-app/lambda/ \
29 | --output-template-file packaged.yaml && \
30 | sam deploy \
31 | --template-file packaged.yaml \
32 | --stack-name ${STACK_NAME}-backend-${AWS_BRANCH} \
33 | --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \
34 | --parameter-overrides \
35 | PhotoRepoS3Bucket=${PHOTO_BUCKET} \
36 | GraphQLEndPoint=${APPSYNC_URL} \
37 | GraphQLAPIId=${GRAPHQL_API_ID} \
38 | Stage=${AWS_BRANCH} \
39 | --no-fail-on-empty-changeset
40 |
41 | #############
42 | # Helpers #
43 | #############
44 |
45 | _install_os_packages:
46 | $(info [*] Installing jq...)
47 | yum install jq -y
48 | $(info [*] Upgrading Python SAM CLI and CloudFormation linter to the latest version...)
49 | python3 -m pip install --upgrade --user cfn-lint aws-sam-cli
50 |
51 |
52 | define HELP_MESSAGE
53 |
54 | Environment variables:
55 |
56 | These variables are automatically filled at CI time except STRIPE_SECRET_KEY
57 | If doing a dirty/individual/non-ci deployment locally you'd need them to be set
58 |
59 | AWS_BRANCH: "dev"
60 | Description: Feature branch name used as part of stacks name; added by Amplify Console by default
61 | DEPLOYMENT_BUCKET_NAME: "a_valid_bucket_name"
62 | Description: S3 Bucket name used for deployment artifacts
63 | GRAPHQL_API_ID: "hnxochcn4vfdbgp6zaopgcxk2a"
64 | Description: AppSync GraphQL ID already deployed
65 | PHOTO_BUCKET: ""
66 |
67 | Common usage:
68 |
69 | ...::: Bootstraps environment with necessary tools like SAM CLI, cfn-lint, etc. :::...
70 | $ make init
71 |
72 | ...::: Deploy all SAM based services :::...
73 | $ make deploy
74 |
75 | ...::: Delete all SAM based services :::...
76 | $ make delete
77 |
78 | ...::: Export parameter and its value to System Manager Parameter Store :::...
79 | $ make export.parameter NAME="/env/service/amplify/api/id" VALUE="xzklsdio234"
80 | endef
81 |
--------------------------------------------------------------------------------
/NOTICE.txt:
--------------------------------------------------------------------------------
1 | AWS Serverless Reference Architecture: Image Recognition and Processing Backend
2 | Copyright 2017 Amazon Web Services, Inc. or its affiliates. All Rights Reserved.
3 |
4 | **********************
5 | THIRD PARTY COMPONENTS
6 | **********************
7 | The web app used React (https://reactjs.org/) which is under the MIT license.
8 |
9 |
10 | The licenses for these third party components are included in LICENSE
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Serverless Reference Architecture: Image Recognition and Processing Backend
2 |
3 | The Image Recognition and Processing Backend demonstrates how to use [AWS Step Functions](https://aws.amazon.com/step-functions/) to orchestrate a serverless processing workflow using [AWS Lambda](http://aws.amazon.com/lambda/), [Amazon S3](http://aws.amazon.com/s3/), [Amazon DynamoDB](http://aws.amazon.com/dynamodb/) and [Amazon Rekognition](https://aws.amazon.com/rekognition/). This workflow processes photos uploaded to Amazon S3 and extracts metadata from the image such as geolocation, size/format, time, etc. It then uses image recognition to tag objects in the photo. In parallel, it also produces a thumbnail of the photo.
4 |
5 | This repository contains sample code for all the Lambda functions depicted in the diagram below as well as an AWS CloudFormation template for creating the functions and related resources. There is also a test web app that you can run to interact with the backend.
6 |
7 | 
8 |
9 | ### Walkthrough of the architecture
10 | 1. An image is uploaded to the `PhotoRepo` S3 bucket under the `private/{userid}/uploads` prefix
11 | 2. The S3 upload event triggers the `S3Trigger` Lambda function, which kicks off an execution of the `ImageProcStateMachine` in AWS Step Functions, passing in the S3 bucket and object key as input parameters.
12 | 3. The `ImageProcStateMachine` has the following sub-steps:
13 | * Read the file from S3 and extract image metadata (format, EXIF data, size, etc.)
14 | * Based on output from previous step, validate if the file uploaded is a supported file format (png or jpg). If not, throw `NotSupportedImageType` error and end execution.
15 | * Store the extracted metadata in the `ImageMetadata` DynamoDB table
16 | * In parallel, kick off two processes simultaneously:
17 | * Call Amazon Rekognition to detect objects in the image file. If detected, store the tags in the `ImageMetadata` DynamoDB table
18 | * Generate a thumbnail and store it under the `private/{userid}/resized` prefix in the `PhotoRepo` S3 bucket
19 |
20 |
21 | ### How to deploy
22 | Follow these instructions to deploy the application (both backend and frontend):
23 |
24 | [](https://console.aws.amazon.com/amplify/home#/deploy?repo=https://github.com/aws-samples/lambda-refarch-imagerecognition)
25 |
26 | 1. Use **1-click deployment** button above. Amplify Console will fork this repository in your GitHub account, and deploy the backend and frontend application.
27 | - Note: If you forked and changed the repository first, you can use the Amplify console and select "**Connect App**" to connect to your forked repo.
28 | 1. For IAM Service Role, create one if you don't have one or select an existing role. (This is required because the Amplify Console needs permissions to deploy backend resources on your behalf. More [info](https://docs.aws.amazon.com/amplify/latest/userguide/how-to-service-role-amplify-console.html))
29 | 
30 | 1. Within your new app in Amplify Console, wait for deployment to complete (this may take a while)
31 | 1. Once the deployment is complete, you can test out the application!
32 |
33 | If you want to make changes to the code locally:
34 |
35 | 1. Clone the repo in your Github account that Amplify created
36 | 1. In the Amplify console, choose **Backend environments**, and toggle "Edit backend" on the environment with categories added
37 | 1. Under **Edit backend**, copy the `amplify pull --appId --envName ` command displayed
38 | - If you don't see this command and instead see `amplify init --appId`, try refreshing the backend environment tab after waiting a few minutes (cloudformation could still be provisioning resources)
39 | 1. Within your forked repository locally, run the command you copied and follow the instructions
40 |
41 | ```
42 | - This command synchronizes what's deployed to your local Amplify environment
43 | - Do you want to use an AWS profile: Yes
44 | - default
45 | - Choose your default editor: Visutal Studio Code
46 | - Choose the type of app that you're building: javascript
47 | - What javascript framework are you using: react
48 | - Source Directory Path: src/react-frontend/src
49 | - Distribution Directory Path: src/react-frontend/build
50 | - Build Command: npm.cmd run-script build
51 | - Start Command: npm.cmd run-script start
52 | - Do you plan on modifying this backend? (Yes)
53 | ```
54 |
55 | If at anytime you want to change these options. Look into `amplify/.config/project-config.json` and make your changes there.
56 |
57 | ### Using the test web app
58 |
59 | You can use the test web app to upload images and explore the image recognition and processing workflow.
60 | 
61 |
62 | #### Sign up and log in
63 |
64 | 1. Go to the URL of the Amplify app that was deployed
65 | 1. In the login page, click on "**Create account**"
66 | 1. Register an account by following the sign up instructions
67 |
68 |
69 |
70 | 1. After confirming the account, sign in
71 |
72 | ##### Album list
73 |
74 | 1. create albums using the "Add a new album"
75 | 
76 | 1. You may need to referresh
77 |
78 | ##### Photo gallery
79 |
80 | 1. Click into an album you created
81 | 1. Upload a photo
82 | 
83 | 1. You can follow the Step Functions execution link to review the details of the workflow execution
84 | Below is the diagram of the state machine being executed every time a new image is uploaded
85 | (you can explore this in the Step Functions [Console](https://console.aws.amazon.com/states/home)):
86 |
87 |
88 | 1. When the processing finishes, the photo and extracted information is added to the display
89 | 
90 |
91 | ## Cleaning Up the Application Resources
92 |
93 | To remove all resources created by this example, do the following:
94 | 1. Go to [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation/home), delete the 2 stacks with name "amplify-photoshare-"
95 | 1. Go to the [AWS Amplify console](https://console.aws.amazon.com/amplify/home) and delete the app.
96 |
97 | ## License
98 |
99 | This reference architecture sample is licensed under Apache 2.0.
100 |
101 |
102 |
--------------------------------------------------------------------------------
/Workshop/README.md:
--------------------------------------------------------------------------------
1 |
2 | # This workshop is not actively maintained.
3 |
4 | Refer to https://image-processing.serverlessworkshops.io/ for an active serverless workshop using Step Functions to address image processing use case
5 | Below is kept for archiving purposes only
6 |
7 | # [archived] Workshop: Serverless Image Processing Workflow with AWS Step Functions
8 |
9 | In this workshop, you will learn to build a serverless image processing workflow step-by-step using AWS Step Functions.
10 |
11 | As can be seen in the diagram below, this workflow processes photos uploaded to Amazon S3 and extracts metadata from the image such as geolocation, size/format, time, etc. It then uses image recognition to tag objects in the photo. In parallel, it also produces a thumbnail of the photo. AWS Step Functions acts as the orchestration to coordinate the various steps involved.
12 |
13 | 
14 |
15 | ## Pre-requisites
16 |
17 | - Administrative access to an AWS account
18 | - Code editor of choice (e.g. Sublime Text, PyCharm, etc...)
19 |
20 | ## Instructions
21 |
22 | * [Step 0: Set up resources](step-0.md)
23 | * [Step 1: Adding first Lambda step to a AWS Step Functions state machine](step-1.md)
24 | * [Step 2: Add branching logic to state machine](step-2.md)
25 | * [Step 3: Add parallel processing to the workflow](step-3.md)
26 | * [Step 4: Persisting labels and image metadata](step-4.md)
27 | * [Step 5: Start execution from an S3 event](step-5.md)
28 | * [Step 6: Build and Launch the web application](step-6.md)
29 | * [Extra credit options](additional-steps.md)
30 | * [Resource clean-up](clean-up.md)
31 |
--------------------------------------------------------------------------------
/Workshop/clean-up.md:
--------------------------------------------------------------------------------
1 | # Resource clean-up
2 |
3 | To clean up all the resources created in this workshop:
4 |
5 | * Go to [Step Functions Console](https://console.aws.amazon.com/states/home), delete the `ImageProcessing` Step Functions state machine
6 | * Go to [CloudFormation Console](https://console.aws.amazon.com/cloudformation/home), delete the `sfn-workshop-setup-webapp` CloudFormation stack
7 | * Delete the `sfn-workshop-setup` CloudFormation stack
--------------------------------------------------------------------------------
/Workshop/images/0-resource-setup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/0-resource-setup.png
--------------------------------------------------------------------------------
/Workshop/images/0a-cfn-create-change-set.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/0a-cfn-create-change-set.png
--------------------------------------------------------------------------------
/Workshop/images/0a-cfn-execute-change-set.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/0a-cfn-execute-change-set.png
--------------------------------------------------------------------------------
/Workshop/images/0b-cfn-create-change-set.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/0b-cfn-create-change-set.png
--------------------------------------------------------------------------------
/Workshop/images/0b-cfn-execute-change-set.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/0b-cfn-execute-change-set.png
--------------------------------------------------------------------------------
/Workshop/images/0b-cfn-outputs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/0b-cfn-outputs.png
--------------------------------------------------------------------------------
/Workshop/images/0b-code-pipeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/0b-code-pipeline.png
--------------------------------------------------------------------------------
/Workshop/images/0b-webapp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/0b-webapp.png
--------------------------------------------------------------------------------
/Workshop/images/1-auto-IAM-role.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1-auto-IAM-role.png
--------------------------------------------------------------------------------
/Workshop/images/1a-step-easy-name.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1a-step-easy-name.png
--------------------------------------------------------------------------------
/Workshop/images/1a-step-lambda-details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1a-step-lambda-details.png
--------------------------------------------------------------------------------
/Workshop/images/1b-pick-state-role.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1b-pick-state-role.png
--------------------------------------------------------------------------------
/Workshop/images/1b-step-console-preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1b-step-console-preview.png
--------------------------------------------------------------------------------
/Workshop/images/1c-dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1c-dashboard.png
--------------------------------------------------------------------------------
/Workshop/images/1c-execution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1c-execution.png
--------------------------------------------------------------------------------
/Workshop/images/1c-input-old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1c-input-old.png
--------------------------------------------------------------------------------
/Workshop/images/1c-input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1c-input.png
--------------------------------------------------------------------------------
/Workshop/images/1c-start-new-execution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1c-start-new-execution.png
--------------------------------------------------------------------------------
/Workshop/images/1d-edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1d-edit.png
--------------------------------------------------------------------------------
/Workshop/images/1d-output-w-resultpath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1d-output-w-resultpath.png
--------------------------------------------------------------------------------
/Workshop/images/1d-start-execution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1d-start-execution.png
--------------------------------------------------------------------------------
/Workshop/images/1d-updated-new-execution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/1d-updated-new-execution.png
--------------------------------------------------------------------------------
/Workshop/images/2-branching-logic-state-machine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2-branching-logic-state-machine.png
--------------------------------------------------------------------------------
/Workshop/images/2a-reimport-step-easy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2a-reimport-step-easy.png
--------------------------------------------------------------------------------
/Workshop/images/2a-step-easy-Paralelldetails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2a-step-easy-Paralelldetails.png
--------------------------------------------------------------------------------
/Workshop/images/2a-step-easy-canvas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2a-step-easy-canvas.png
--------------------------------------------------------------------------------
/Workshop/images/2a-step-easy-choice-ImageTypeCheckChoicedetails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2a-step-easy-choice-ImageTypeCheckChoicedetails.png
--------------------------------------------------------------------------------
/Workshop/images/2a-step-easy-choice-ImageTypeCheckconfigurecondition.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2a-step-easy-choice-ImageTypeCheckconfigurecondition.png
--------------------------------------------------------------------------------
/Workshop/images/2a-step-easy-choice-ImageTypeCheckdetails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2a-step-easy-choice-ImageTypeCheckdetails.png
--------------------------------------------------------------------------------
/Workshop/images/2a-step-easy-fail-notsupportedimage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2a-step-easy-fail-notsupportedimage.png
--------------------------------------------------------------------------------
/Workshop/images/2a-step-easy-fail-notsupportedimagecatchers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2a-step-easy-fail-notsupportedimagecatchers.png
--------------------------------------------------------------------------------
/Workshop/images/2a-step-easy-fail-notsupportedimagedetails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2a-step-easy-fail-notsupportedimagedetails.png
--------------------------------------------------------------------------------
/Workshop/images/2b-step-console-update-preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2b-step-console-update-preview.png
--------------------------------------------------------------------------------
/Workshop/images/2c-test-catch-failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2c-test-catch-failed.png
--------------------------------------------------------------------------------
/Workshop/images/2c-test-choice-test-failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2c-test-choice-test-failed.png
--------------------------------------------------------------------------------
/Workshop/images/2c-test-choice-test-succeeded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/2c-test-choice-test-succeeded.png
--------------------------------------------------------------------------------
/Workshop/images/3-create-statemachine-select-role.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/3-create-statemachine-select-role.png
--------------------------------------------------------------------------------
/Workshop/images/3-state-machine-parallel-with-output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/3-state-machine-parallel-with-output.png
--------------------------------------------------------------------------------
/Workshop/images/3-state-machine-parallel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/3-state-machine-parallel.png
--------------------------------------------------------------------------------
/Workshop/images/4-add-step.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/4-add-step.png
--------------------------------------------------------------------------------
/Workshop/images/4-final-status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/4-final-status.png
--------------------------------------------------------------------------------
/Workshop/images/4b-step-console-preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/4b-step-console-preview.png
--------------------------------------------------------------------------------
/Workshop/images/4c-ddb-imagemetadata-item.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/4c-ddb-imagemetadata-item.png
--------------------------------------------------------------------------------
/Workshop/images/4c-ddb-imagemetadata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/4c-ddb-imagemetadata.png
--------------------------------------------------------------------------------
/Workshop/images/4c-test-choice-test-succeeded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/4c-test-choice-test-succeeded.png
--------------------------------------------------------------------------------
/Workshop/images/5a-enviroment-variables.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/5a-enviroment-variables.png
--------------------------------------------------------------------------------
/Workshop/images/5a-state-machine-arn-new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/5a-state-machine-arn-new.png
--------------------------------------------------------------------------------
/Workshop/images/5a-state-machine-arn-newer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/5a-state-machine-arn-newer.png
--------------------------------------------------------------------------------
/Workshop/images/5a-state-machine-arn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/5a-state-machine-arn.png
--------------------------------------------------------------------------------
/Workshop/images/5b-s3-event-configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/5b-s3-event-configuration.png
--------------------------------------------------------------------------------
/Workshop/images/5b-s3-events.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/5b-s3-events.png
--------------------------------------------------------------------------------
/Workshop/images/5b-s3-incoming-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/5b-s3-incoming-folder.png
--------------------------------------------------------------------------------
/Workshop/images/5c-s3-object-metadata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/5c-s3-object-metadata.png
--------------------------------------------------------------------------------
/Workshop/images/5c-state-machine-execution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/5c-state-machine-execution.png
--------------------------------------------------------------------------------
/Workshop/images/additional-step-inappropiate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/additional-step-inappropiate.png
--------------------------------------------------------------------------------
/Workshop/images/bucket-sync-state-machine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/bucket-sync-state-machine.png
--------------------------------------------------------------------------------
/Workshop/images/bulk-import-album1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/bulk-import-album1.png
--------------------------------------------------------------------------------
/Workshop/images/bulk-import-albumlist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/bulk-import-albumlist.png
--------------------------------------------------------------------------------
/Workshop/images/bulk-import-user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/bulk-import-user.png
--------------------------------------------------------------------------------
/Workshop/images/cfn-launch-stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/cfn-launch-stack.png
--------------------------------------------------------------------------------
/Workshop/images/cloudwatch-state-machine-metrics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/cloudwatch-state-machine-metrics.png
--------------------------------------------------------------------------------
/Workshop/images/dynamo-screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/dynamo-screenshot.png
--------------------------------------------------------------------------------
/Workshop/images/single-step-state-machine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/single-step-state-machine.png
--------------------------------------------------------------------------------
/Workshop/images/step-easy-intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/step-easy-intro.png
--------------------------------------------------------------------------------
/Workshop/images/web-app-screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/lambda-refarch-imagerecognition/856a02a2c036a2e9f8222da10b1d79c45d5c5ed4/Workshop/images/web-app-screenshot.png
--------------------------------------------------------------------------------
/Workshop/step-0.md:
--------------------------------------------------------------------------------
1 | ## Step 0: Set up resources
2 |
3 | ### Step 0A: Set up Lambda functions and data stores
4 |
5 | The AWS Step Functions state machine you will create in this workshop coordinates a number of Lambda functions that implement the logic for each step. Some of those Lambda functions rely on the existance of AWS resources and data stores, such as an Amazon S3 bucket or an Amazon DynamoDB table.
6 |
7 | In this section, you will use a cloudformation template to provision the AWS Lambda functions plus all the resources that those require.
8 |
9 | To help you understand what resources are set up in this stage, refer to the diagram below. In this workshop, you will build a Step Functions state machine (greyed out in the middle) to orchestrate the lambda functions that does the processing work:
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Region| Code | Launch
18 | ------|------|-------
19 | US West (Oregon) | us-west-2 | [](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=sfn-workshop-setup&templateURL=https://s3-us-west-2.amazonaws.com/image-processing-step-functions-workshop-us-west-2/cloudformation/step0-sam.yaml)
20 |
21 |
22 |
23 | CloudFormation launch instructions (expand for details)
24 |
25 | 1. Click the **Launch Stack** link above for the region of your choice.
26 |
27 | 1. Click **Next** on the Select Template page.
28 |
29 | 1. On the ```Specify stack details``` page, leave all the defaults and click **Next**.
30 |
31 | 1. On the ```Configure stack options``` page, also leave all the defaults and click **Next**.
32 |
33 | 1. On the ```Review page```, check all the boxes to acknowledge that CloudFormation will create IAM resources and CAPABILITY_AUTO_EXPAND and click **Create Stack**.
34 |
35 | 
36 |
37 | This template creates a number of IAM roles to grant the Lambda fuctions proper permissions on the resources they have to deal with.
38 |
39 | 1. Wait for the `sfn-workshop-setup` stack to reach a status of `CREATE_COMPLETE` (you might need to click the refresh button to see the stack being created).
40 |
41 |
42 |
43 | ### Next step
44 | You are now ready to move on to [Step 1](step-1.md)!
45 |
--------------------------------------------------------------------------------
/Workshop/step-3.md:
--------------------------------------------------------------------------------
1 | ## Step 3: Add parallel processing to the workflow
2 |
3 | After extracting and checking the metadata, we are now ready to add a few more steps to our state machine: thumb-nailing, image recognition and persisting/indexing the metadata. Thumb-nailing and image recognition does not depend on each other and can happen in parallel, and we can use a [parallel state](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-parallel-state.html) in Step Functions.
4 |
5 |
6 |
7 | ### Step 3A: Update the state machine definition
8 |
9 | Now you acquired some experience with incrementally adding steps to the state machine, deploying, and testing it, give it a shot to add a parallel step to our current state machine (remember to export it or take it from the Final JSON of the last step) in step-easy that performs thumb-nailing and image recognition in parallel.
10 |
11 | Take a look at these documentation if you need help with the syntax:
12 |
13 | - [Parallel State](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-parallel-state.html)
14 | - [Task State](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-task-state.html)
15 | - [Amazon States Language Spec](https://states-language.net/spec.html)
16 |
17 | We suggest now to edit the JSON directly, so that links to the documentation referred above are easier to follow.
18 |
19 |
20 | Expand to get some hints
21 |
22 | - The first step is to change the type of the *Parallel* state from **Pass** to **Parallel**.
23 |
24 | - Parallel acitivies within a **Parallel** state are specified as an array of objects, each of one is, in turn, a self-contained state machine object.
25 |
26 | ```JSON
27 | "Parallel": {
28 | "Type": "Parallel",
29 | "Branches": [, ..., ],
30 | "End": true
31 | }
32 | ```
33 |
34 | - For each branch create a state machine object with one **Task** state that triggers the corresponding Lambda function:
35 | - ``sfn-workshop-setup-DetectLabel``, that leverages the deep learning-based image analyis [Amazon Rekognition](https://aws.amazon.com/rekognition/) service and, in particular, its [DetectLabels API](http://docs.aws.amazon.com/rekognition/latest/dg/API_DetectLabels.html), to obtain metadata about what objects and concepts appear on the processed image.
36 |
37 | - ``sfn-workshop-setup-Thumbnail``, that relies on [GraphicsMagick for node.js](http://aheckmann.github.io/gm/docs.html) library to generate the thumbnails
38 |
39 |
40 |
41 | Now is a good time to remember Step 1D, where we learned how to merge the input of a state with its output, so that both become available to states further down the line using the [AWS Step Functions Paths feature]((https://docs.aws.amazon.com/step-functions/latest/dg/awl-ref-paths.html)).
42 |
43 | In particular use **ResultPath** in the *Parallel* state to make sure the array of parallel state machine outputs are made available to downstream states. Use the `parallelResults` attribute for that.
44 |
45 |
46 | Expand to get some hints
57 |
58 |
59 | Now, test your state machine with the images you want!
60 |
61 | - Make sure that both labels detected by Amazon Rekognition and the S3 location of the thumbnails are available in the output.
62 |
63 |
64 |
65 | - Verify that the tumbnails are in the S3 bucket, under the **Thumbnail** folder
66 |
67 |
68 | ### Final JSON
69 |
70 | Expand to see JSON definition
148 |
149 | ### Next step
150 | You are now ready to move on to [Step 4](step-4.md)!
151 |
152 |
--------------------------------------------------------------------------------
/Workshop/step-4.md:
--------------------------------------------------------------------------------
1 | ## Step 4: Persisting labels and image metadata
2 |
3 | At this point, we should have our state machine generating Thumbnails and metadata, as well as detecting what objects and concepts are in the images (labels).
4 |
5 |
6 | ### Step 4A: Add a step to store the metadata in DynamoDB
7 |
8 | For this part we will again edit the JSON manually. Go to your editor of choice used previously and paste in the final JSON you ended up with on Step 3. From there add one more step to your state machine, to execute the Lambda function `sfn-workshop-setup-PersistDDB` that takes care of storing everything in DynamoDB.
9 |
10 | Take a look at this documentation if you need help with the syntax:
11 |
12 | - [Task State](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-task-state.html)
13 | - [Amazon States Language Spec](https://states-language.net/spec.html)
14 |
15 | > To find the ARN of the Lambda function, in the AWS CloudFormation Console, go to the **sfn-workshop-setup** stack and look in the Outputs section for **StoreImageMetadataFunction**
16 | >
17 | > It should look something like `arn:aws:lambda:us-west-2::function:sfn-workshop-setup-PersistDDB`
18 |
19 | 1. Make the new step you've just added, be the next step after the Parallel step.
20 |
21 | 1. Copy the produced JSON. If you're having trouble, you can find the JSON at the bottom of this page.
22 |
23 |
24 | ### Step 4B: Create an AWS Step Functions state machine to test the result
25 |
26 | 1. Go to [AWS Step Functions management console](http://console.aws.amazon.com/states/home).
27 |
28 | 1. Select the `ImageProcessing` state machine. Click on **Edit state machine**
29 |
30 | 1. Paste in the JSON from your editor produced in Step 4A
31 |
32 | 1. Click on the ↺ icon next to **Visual Workflow** to refresh the visual representation of the state machine:
33 |
34 |
35 |
36 | 1. Click **Update and start execution**
37 |
38 |
39 | ### Step 4C: Test the state machine execution
40 |
41 | 1. Use the following input you have been using so far to test the execution
42 |
43 | ```JSON
44 | {
45 | "s3Bucket": "FILL_IN_YOUR_VALUE",
46 | "s3Key": "tests/1_cactus.jpg"
47 | }
48 | ```
49 |
50 |
51 | 1. Verify that everything came out fine and the workflow succesfully executed all the steps:
52 |
53 |
54 |
55 | 1. You may also want to check what DynamoDB tables and items stored in them look like. Navigate to the [Amazon DynamoDB management console](https://console.aws.amazon.com/dynamodb/home?#tables:). You should see two tables there with names similar to the following ones:
56 |
57 | - `sfn-workshop-setup-AlbumMetadataDDBTable`
58 | - `sfn-workshop-setup-ImageMetadataDDBTable`
59 |
60 | 1. Click on the `sfn-workshop-setup-ImageMetadataDDBTable` and the click on the **Items** folder. Verify there is one entry for each sucessfully processed image:
61 |
62 |
63 |
64 |
65 | 1. Click on an item and have a look at its structure:
66 |
67 |
68 |
69 |
70 | ### Final JSON
71 |
72 | Expand to see JSON definition
154 |
155 | ### Next step
156 | You are now ready to move on to [Step 5](step-5.md)!
157 |
--------------------------------------------------------------------------------
/Workshop/step-5.md:
--------------------------------------------------------------------------------
1 | ## Step 5: Start execution from an S3 event
2 |
3 | Finally, we have our state machine up and running! It's time to automate its execution.
4 | As images are uploaded to the landing S3 bucket we want the state machine to be triggered.
5 |
6 | We have two possibilities here:
7 |
8 | 1. Use CloudWatch Events to monitor activity on the S3 bucket and select Step Functions as the target for its execution
9 |
10 | 1. Use a Lambda Function that:
11 | - Invokes the state machine
12 | - Is triggered by an S3 event
13 |
14 | The first step requires some extra configuration as it needs CloudTrail to be enabled. For brevity, we will go with Option 2.
15 |
16 | ### Step 5A: Instruct StartExecution Lambda function what Step Functions state machine it is to be triggered
17 |
18 | 1. Go to [AWS Step Functions management console](http://console.aws.amazon.com/states/home). Make sure the AWS Region selection matches the one you have been working with so far.
19 |
20 | 1. On the Dashboard locate your state machine. If you followed instructions on prior steps it should be *ImageProcessing*
21 |
22 | 1. On the **Details** box, find and copy the **ARN**:
23 |
24 |
25 |
26 | 1. Navigate to the [AWS Lambda management console](https://console.aws.amazon.com/lambda/home) and find the Lambda function with a name that ends with `StartExecution`. That is the one that triggers the state machine. Select it by clicking on the link on its name.
27 |
28 | 1. The specific AWS Step Function state machine it launches is passed to the Lambda function as a configurable environment variable. Scroll down to the **Environment variables** section. Expand it and change the placeholder value `FILL_WITH_YOUR_VALUE` to the ARN of your state machine.
29 |
30 |
31 |
32 | 1. Scroll up to the top of the page and click **Save**
33 |
34 | ### Step 5B: Set up S3 event to trigger StartExecution Lambda function
35 |
36 | The Lambda function now knows what state machine we want it to run. Now we need to set up the event that will, in turn, trigger the Lambda function. Since we want it to be launched automatically whenever a new object is uploaded to the landing bucket, we need the Lambda funtion to be triggered by an S3 event.
37 |
38 | 1. Go to the S3 management console and select the landing bucket:
39 |
40 | ```
41 | sfn-workshop-setup-photorepos3bucket-xxxxxxxxxxxxx
42 | ```
43 |
44 | 1. Create a folder and call it *Incoming*
45 |
46 |
47 |
48 | 1. Click on the **Properties** tab
49 |
50 | 1. Click on **Events**
51 |
52 |
53 |
54 | 1. Click on **Add notification**
55 |
56 | 1. Enter the following parameters:
57 | - **Name**: ExecuteStateMachine
58 | - **Events**: All object create events
59 | - **Prefix**: Incoming/
60 | - **Send to**: Lambda Function
61 | - **Lambda**: sfn-workshop-setup-StartExecution
62 |
63 | > **Note:** the **Prefix** parameter is critical: this limits the event trigger to only trigger processing workflows when an image file lands in the "Incoming/" prefix. Because the thumbnail generation process uploads the thumbnails to the same S3 bucket, without limiting the prefix, the thumbnail upload will trigger another workflow and causes an infinite loop.
64 |
65 |
66 |
67 | 1. Click **Save**
68 |
69 | ### Step 5C: Test the event trigger by uploading a photo to S3
70 |
71 | Now you are ready to test your event! Just upload an image within the S3 bucket into the "Incoming" folder and check the execution in the Step Functions console!
72 |
73 | 1. On the S3 management console go to the `Incoming/` prefix on the landing bucket and click **Upload**. Select an image with a supported format (JPEG or PNG). Click **Next**
74 |
75 |
76 | 1. Click **Next** and **Upload**
77 |
78 | 1. Verify that the state machine is triggered and it executes successfully. Verify the metadata of the new image processed is stored in DynamoDB.
79 |
80 |
81 |
82 |
83 | ### Next step
84 | You are now ready to move on to [Step 6](step-6.md)!
85 |
86 |
87 |
--------------------------------------------------------------------------------
/Workshop/step-6.md:
--------------------------------------------------------------------------------
1 | # Step 6: Build and Launch the web application
2 |
3 | To see the processing workflow in action, we will use an AngularJS web application to create photo albums and upload pictures to them.
4 |
5 | ### Step 6A: Set up the Photo Processing Web Application
6 |
7 | To complete the workshop tests, you will use an AngularJS web application to create photo albums and upload pictures to them.
8 |
9 | In this section, you will use a cloudformation template to package and deploy the web application on an S3 bucket configured for website hosting.
10 |
11 | > This cloudformation template leverages AWS CodeBuild and AWS CodePipeline to automate building, packaging and deploying the web application
12 |
13 | Region| Code | Launch
14 | ------|------|-------
15 | US East (Ohio)| us-east-2 | [](https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=sfn-workshop-setup-webapp&templateURL=https://s3-us-east-2.amazonaws.com/image-processing-step-functions-workshop-us-east-2/cloudformation/step0-webapp.yaml)
16 | US East (N. Virginia) | us-east-1 | [](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=sfn-workshop-setup-webapp&templateURL=https://s3.amazonaws.com/image-processing-step-functions-workshop-us-east-1/cloudformation/step0-webapp.yaml)
17 | US West (Oregon) | us-west-2 | [](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=sfn-workshop-setup-webapp&templateURL=https://s3-us-west-2.amazonaws.com/image-processing-step-functions-workshop-us-west-2/cloudformation/step0-webapp.yaml)
18 | EU (Ireland) | eu-west-1 | [](https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=sfn-workshop-setup-webapp&templateURL=https://s3-eu-west-1.amazonaws.com/image-processing-step-functions-workshop-eu-west-1/cloudformation/step0-webapp.yaml)
19 | Tokyo | ap-northeast-1 | [](https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/new?stackName=sfn-workshop-setup-webapp&templateURL=https://s3-ap-northeast-1.amazonaws.com/image-processing-step-functions-workshop-ap-northeast-1/cloudformation/step0-webapp.yaml)
20 | Sydney | ap-southeast-2 | [](https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-2#/stacks/new?stackName=sfn-workshop-setup-webapp&templateURL=https://s3-ap-southeast-2.amazonaws.com/image-processing-step-functions-workshop-ap-southeast-2/cloudformation/step0-webapp.yaml)
21 | Mumbai | ap-south-1 | [](https://console.aws.amazon.com/cloudformation/home?region=ap-south-1#/stacks/new?stackName=sfn-workshop-setup-webapp&templateURL=https://s3-ap-south-1.amazonaws.com/image-processing-step-functions-workshop-ap-south-1/cloudformation/step0-webapp.yaml)
22 |
23 | #### CloudFormation launch instructions
24 |
25 | 1. Click the **Launch Stack** link above for the region of your choice (make sure to pick the same region you have launched your other resources in)
26 |
27 | 1. Click **Next** on the Select Template page.
28 |
29 | 1. On the ```Specify stack details``` page, leave all the defaults and click **Next**.
30 |
31 | 1. On the ```Configure stack options``` page, also leave all the defaults and click **Next**.
32 |
33 | 1. On the ```Review page```, check all the boxes to acknowledge that CloudFormation will create IAM resources and CAPABILITY_AUTO_EXPAND and click **Create Stack**.
34 |
35 | 
36 |
37 | 1. Wait for the `sfn-workshop-setup-webapp` stack to reach a status of `CREATE_COMPLETE` (you might need to click the refresh button to see the stack being created).
38 |
39 | The stack will take a minute of so to complete. As part ot that, it copies the web application sources over to the target bucket and that will trigger the delivery pipleline.
40 |
41 | 1. Go to the [AWS CodePipeline management console](http://console.aws.amazon.com/codepipeline/home). Click on the pipeline identified by `sfn-workshop-pipeline` and verify it finishes succesfully.
42 |
43 |
44 | 1. Go to the [AWS CloudFormation management console](http://console.aws.amazon.com/cloudformation/home). With the stack `sfn-workshop-setup-webapp` selected click on the Outputs tab. The `WebsiteURL` key points at the link to access the **Image Sharing demo Web Application**
45 |
46 | 
47 |
48 | 1. Click on that link to navigate to the **Media Sharing Web Application**
49 |
50 | **Note: Make sure to use Chrome browser to open the web application.**
51 |
52 | 
53 |
54 |