├── .checkov.yaml
├── .github
└── ISSUE_TEMPLATE
│ ├── bug-report.yml
│ ├── config.yml
│ └── feature-request.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .tflint.hcl
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── application
└── ecsdemo-python
│ ├── .bandit
│ ├── .coveragerc
│ ├── .dockerignore
│ ├── .gitignore
│ ├── .pylintrc
│ ├── Dockerfile
│ ├── app.py
│ ├── requirements-dev.txt
│ ├── requirements.txt
│ ├── static
│ ├── amazon-ecs.png
│ └── css
│ │ └── style.css
│ ├── templates
│ └── index.html
│ ├── tests
│ ├── __init__.py
│ └── unit
│ │ ├── __init__.py
│ │ └── test_ecs_app.py
│ └── version.txt
├── docs
├── aquasec.md
├── datadog.md
└── github.md
├── images
├── connect-to-github-1.png
├── connect-to-github-2.png
├── first_demo_page.png
├── github_connection.png
├── github_connection2.png
├── spok.png
└── successful-deployment-alb.jpg
├── modules
├── aquasec
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── codepipeline
│ └── github
│ │ ├── codepipeline_python
│ │ ├── locals.tf
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── s3
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ │ ├── variables.tf
│ │ └── versions.tf
└── datadog
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
└── patterns
├── aquasec-sidecar
└── Dockerfile
└── fargate-cluster
├── aquasec.tf.draft
├── delete_ecr_images.sh
├── main.tf
├── networking.tf
├── outputs.tf
├── terraform.tfvars
├── variables.tf
└── versions.tf
/.checkov.yaml:
--------------------------------------------------------------------------------
1 | block-list-secret-scan: []
2 | branch: master
3 | directory:
4 | - .
5 | download-external-modules: true
6 | evaluate-variables: true
7 | external-modules-download-path: .external_modules
8 | framework:
9 | - terraform
10 | mask: []
11 | output:
12 | - sarif
13 | - junitxml
14 | output-file-path: console,checkov-output/results_junitxml.xml
15 | quiet: true
16 | secrets-history-timeout: 12h
17 | secrets-scan-file-type: []
18 | summary-position: top
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.yml:
--------------------------------------------------------------------------------
1 | name: "🐛 Bug Report"
2 | description: Report a bug
3 | title: "(short issue description)"
4 | labels: [bug, needs-triage]
5 | assignees: []
6 | body:
7 | - type: textarea
8 | id: description
9 | attributes:
10 | label: Describe the bug
11 | description: What is the problem? A clear and concise description of the bug.
12 | validations:
13 | required: true
14 | - type: textarea
15 | id: expected
16 | attributes:
17 | label: Expected Behavior
18 | description: |
19 | What did you expect to happen?
20 | validations:
21 | required: true
22 | - type: textarea
23 | id: current
24 | attributes:
25 | label: Current Behavior
26 | description: |
27 | What actually happened?
28 |
29 | Please include full errors, uncaught exceptions, stack traces, and relevant logs.
30 | If service responses are relevant, please include wire logs.
31 | validations:
32 | required: true
33 | - type: textarea
34 | id: reproduction
35 | attributes:
36 | label: Reproduction Steps
37 | description: |
38 | Provide a self-contained, concise snippet of code that can be used to reproduce the issue.
39 | For more complex issues provide a repo with the smallest sample that reproduces the bug.
40 | validations:
41 | required: true
42 | - type: textarea
43 | id: solution
44 | attributes:
45 | label: Possible Solution
46 | description: |
47 | Suggest a fix/reason for the bug
48 | validations:
49 | required: false
50 | - type: textarea
51 | id: context
52 | attributes:
53 | label: Additional Information/Context
54 | description: |
55 | Anything else that might be relevant for troubleshooting this bug. Providing context helps us come up with a solution that is most useful in the real world.
56 | validations:
57 | required: false
58 |
59 | - type: input
60 | id: terraform-version
61 | attributes:
62 | label: Terraform Version
63 | description: Output of `terraform version`
64 | validations:
65 | required: true
66 |
67 | - type: input
68 | id: operating-system
69 | attributes:
70 | label: OS
71 | validations:
72 | required: true
73 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | ---
2 | blank_issues_enabled: false
3 | contact_links:
4 | - name: 💬 General Question
5 | url: https://github.com/aws-samples/fargate-serverless-platform-operator-kit/discussions/categories/q-a
6 | about: Please ask and answer questions as a discussion thread.
7 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🚀 Feature Request
3 | description: Suggest an idea for this project
4 | title: "(short issue description)"
5 | labels: [feature-request, needs-triage]
6 | assignees: []
7 | body:
8 | - type: textarea
9 | id: description
10 | attributes:
11 | label: Describe the feature
12 | description: A clear and concise description of the feature you are proposing.
13 | validations:
14 | required: true
15 | - type: textarea
16 | id: use-case
17 | attributes:
18 | label: Use Case
19 | description: |
20 | Why do you need this feature? For example: "I'm always frustrated when..."
21 | validations:
22 | required: true
23 | - type: textarea
24 | id: solution
25 | attributes:
26 | label: Proposed Solution
27 | description: |
28 | Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation.
29 | validations:
30 | required: false
31 | - type: textarea
32 | id: other
33 | attributes:
34 | label: Other Information
35 | description: |
36 | Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc.
37 | validations:
38 | required: false
39 | - type: checkboxes
40 | id: ack
41 | attributes:
42 | label: Acknowledgements
43 | options:
44 | - label: I may be able to implement this feature request
45 | required: false
46 | - label: This feature might incur a breaking change
47 | required: false
48 |
49 | - type: input
50 | id: terraform-version
51 | attributes:
52 | label: Terraform Version
53 | description: Output of `terraform version`
54 | validations:
55 | required: true
56 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/macos,windows
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos,windows
3 |
4 | ### macOS ###
5 | # General
6 | .DS_Store
7 | .AppleDouble
8 | .LSOverride
9 |
10 | # Icon must end with two \r
11 | Icon
12 |
13 | # Thumbnails
14 | ._*
15 |
16 | # Files that might appear in the root of a volume
17 | .DocumentRevisions-V100
18 | .fseventsd
19 | .Spotlight-V100
20 | .TemporaryItems
21 | .Trashes
22 | .VolumeIcon.icns
23 | .com.apple.timemachine.donotpresent
24 |
25 | # Directories potentially created on remote AFP share
26 | .AppleDB
27 | .AppleDesktop
28 | Network Trash Folder
29 | Temporary Items
30 | .apdisk
31 |
32 | ### macOS Patch ###
33 | # iCloud generated files
34 | *.icloud
35 |
36 | ### Windows ###
37 | # Windows thumbnail cache files
38 | Thumbs.db
39 | Thumbs.db:encryptable
40 | ehthumbs.db
41 | ehthumbs_vista.db
42 |
43 | # Dump file
44 | *.stackdump
45 |
46 | # Folder config file
47 | [Dd]esktop.ini
48 |
49 | # Recycle Bin used on file shares
50 | $RECYCLE.BIN/
51 |
52 | # Windows Installer files
53 | *.cab
54 | *.msi
55 | *.msix
56 | *.msm
57 | *.msp
58 |
59 | # Windows shortcuts
60 | *.lnk
61 |
62 | # End of https://www.toptal.com/developers/gitignore/api/macos,windows
63 |
64 | plan.out
65 | plan.out.json
66 | # Local .terraform directories
67 | .terraform/
68 | # .tfstate files
69 | *.tfstate
70 | *.tfstate.*
71 | .terraform*
72 | # Crash log files
73 | crash.log
74 | # Exclude all .tfvars files, which are likely to contain sentitive data, such as
75 | # password, private keys, and other secrets. These should not be part of version
76 | # control as they are data points which are potentially sensitive and subject
77 | # to change depending on the environment.
78 | #
79 | # Ignore override files as they are usually used to override resources locally and so
80 | # are not checked in
81 | override.tf
82 | override.tf.json
83 | *_override.tf
84 | *_override.tf.json
85 | *.tfvars
86 | # Include override files you do wish to add to version control using negated pattern
87 | #
88 | # !example_override.tf
89 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
90 | # example: *tfplan*
91 | # Ignore CLI configuration files
92 | .terraformrc
93 | terraform.rc
94 | .terraform.lock.hcl
95 | go.mod
96 | go.sum
97 | # Ignore autogenerated hooks files
98 | checkov-output/
99 | .external_modules/
100 | results.sarif
101 |
102 | #Python virtualenv
103 | .env
104 | .venv
105 |
106 | #Other files
107 | .DS_Store
108 | .hypothesis
109 |
110 | !terraform.tfvars
111 | microenforcer
112 | backend.tf
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v4.4.0
4 | hooks:
5 | - id: check-yaml
6 | args: [--allow-multiple-documents]
7 | - id: check-json
8 | - id: trailing-whitespace
9 | args: ["--markdown-linebreak-ext=md"]
10 | - id: check-added-large-files
11 | - id: check-executables-have-shebangs
12 | - id: check-shebang-scripts-are-executable
13 | - id: check-merge-conflict
14 | - id: check-vcs-permalinks
15 | - id: detect-private-key
16 | - id: detect-aws-credentials
17 | args: ["--allow-missing-credentials"]
18 | - id: end-of-file-fixer
19 | - id: no-commit-to-branch
20 | - id: pretty-format-json
21 | args:
22 | - --autofix
23 | - repo: https://github.com/zricethezav/gitleaks
24 | rev: v8.16.3
25 | hooks:
26 | - id: gitleaks
27 | - repo: https://github.com/bridgecrewio/checkov.git
28 | rev: 2.3.247
29 | hooks:
30 | - id: checkov
31 | args:
32 | - --config-file
33 | - .checkov.yaml
34 | - repo: https://github.com/antonbabenko/pre-commit-terraform
35 | rev: v1.79.1
36 | hooks:
37 | - id: terraform_fmt
38 | - id: terraform_validate
39 | args:
40 | - --hook-config=--retry-once-with-cleanup=true
41 | - id: terraform_docs
42 | args:
43 | - --args=--config=.terraform-docs.yaml
44 | - id: terraform_tflint
45 | args:
46 | - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
47 |
--------------------------------------------------------------------------------
/.tflint.hcl:
--------------------------------------------------------------------------------
1 | config {
2 | format = "compact"
3 | plugin_dir = "~/.tflint.d/plugins"
4 |
5 | call_module_type = "none"
6 | force = false
7 | disabled_by_default = true
8 | }
9 |
10 | plugin "aws" {
11 | enabled = true
12 | version = "0.23.0"
13 | source = "github.com/terraform-linters/tflint-ruleset-aws"
14 | }
15 |
16 | rule "terraform_deprecated_interpolation" {
17 | enabled = true
18 | }
19 |
20 | rule "terraform_deprecated_index" {
21 | enabled = true
22 | }
23 |
24 | rule "terraform_unused_declarations" {
25 | enabled = true
26 | }
27 |
28 | rule "terraform_comment_syntax" {
29 | enabled = true
30 | }
31 |
32 | rule "terraform_documented_outputs" {
33 | enabled = true
34 | }
35 |
36 | rule "terraform_documented_variables" {
37 | enabled = true
38 | }
39 |
40 | rule "terraform_typed_variables" {
41 | enabled = true
42 | }
43 |
44 | rule "terraform_module_pinned_source" {
45 | enabled = true
46 | }
47 |
48 | rule "terraform_naming_convention" {
49 | enabled = true
50 | }
51 |
52 | rule "terraform_required_version" {
53 | enabled = true
54 | }
55 |
56 | rule "terraform_required_providers" {
57 | enabled = true
58 | }
59 |
60 | rule "terraform_standard_module_structure" {
61 | enabled = true
62 | }
63 |
64 | rule "terraform_workspace_remote" {
65 | enabled = true
66 | }
67 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *main* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT No Attribution
2 |
3 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
13 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
15 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Serverless Platform Operator Kit (SPOK)
2 |
3 | AWS SPOK, known as an opinionated solution bundle, offers a robust technical stack that emphasizes best practices. What this means for you is that launching production-level workloads on ECS can now be done much quicker. But it's not just about ECS and Fargate. SPOK also incorporates essential tools such as Terraform, GitHub, Amazon CloudWatch, and AWS Secrets Manager for establishing end-to-end solution. These services are the go-to choices for many customers already using ECS/Fargate, ensuring you're working with the tools that have proven their worth. Importantly, this bundle is designed to simplify your workflow, letting you focus more on what you do best.
4 |
5 |
6 | ## SPOK V1
7 |
8 | 
9 |
10 | ## Getting started
11 |
12 | To make it easy for you to get started with SPOK(Serverless Platform Operator Kit), here's a list of next steps. We are going to provision ECS Cluster with AWS Fargate, serverless compute engine for containers.
13 |
14 | ### Deploy Your Pattern
15 |
16 | Go to your pattern and run the following command:
17 |
18 | ```shell
19 | terraform init
20 | terraform validate
21 | terraform plan #Here check the plan that Terraform outputs in case you want to change something.
22 | terraform apply --auto-approve
23 | ```
24 |
25 | ---
26 |
27 | ### Choose your integration available on **terraform.tfvars**
28 |
29 | Please refer following readme file for integration with third party patterns.
30 |
31 | * [Datadog](./docs/datadog.md)
32 | * [AquaSec](./docs/aquasec.md)
33 | * [Github Pipeline](./docs/github.md)
34 |
35 | ### Outputs
36 | After the execution of the Terraform code you will get an output with needed IDs and values needed as input for the following *terraform apply*. You can use this infrastructure to run other examples, all you need is the `cluster_name`.
37 |
38 | ### Check Deployment Status
39 | On the ECS Console you will find the **ecs-core** cluster, in it there will be a service called **ecsdemo-backend**, this service has an Application Load Balancer associated, you can execute the command **terraform output** on the **ecs-service** path and it will show the URL of the ALB, once you open that URL in a web browser it will show the following sample page:
40 |
41 | 
42 |
43 | If you keep refreshing the page it will show a different IP address and Availability Zone to demonstrate the Load Balancing.
44 |
45 | ### Cleanup
46 | Run the following command if you want to delete all the resources created before. If you have created other blueprints and they use these infrastructure then destroy those blueprint resources first.
47 |
48 | Go to your pattern and run the following command:
49 | ```shell
50 | terraform destroy
51 | ```
52 |
53 | Is possible that the deletion of the ECR Repository fails because there are images left on the repository, hence please delete manually the images and execute the command again.
54 |
55 | ## Best Practices
56 |
57 | Terraform uses persisted state data to keep track of the resources it manages. You can either integrate with HCP Terraform to store state data or define a backend block to store state in a remote object. This lets multiple people access the state data and work together on that collection of infrastructure resources.
58 |
59 | * Dynamodb Table (A single DynamoDB table is used to lock multiple remote state files)
60 | * S3 Bucket (Stores the state as a given key in a given bucket)
61 |
62 | In case you don't have it, use this CLI to create the DynamoDB table it:
63 |
64 | ```shell
65 | aws dynamodb create-table --table-name TerraformLockStates \
66 | --attribute-definitions AttributeName=LockID,AttributeType=S \
67 | --key-schema AttributeName=LockID,KeyType=HASH \
68 | --billing-mode PAY_PER_REQUEST --region us-east-1
69 | ```
70 |
71 | That CLI will create a DynamoDB table on us-east-1 region with name TerraformLockStates and pay per request billing mode, the table will have a Hash Key called LockID
72 |
73 | Use this CLI to create the S3 bucket:
74 |
75 | ```shell
76 | account_id=$(aws sts get-caller-identity --query "Account" --output text) && \
77 | aws s3api create-bucket --bucket ${account_id}-terraform-states \
78 | --region us-east-1 --output text --no-cli-pager && aws s3api put-bucket-versioning \
79 | --bucket ${account_id}-terraform-states --versioning-configuration Status=Enabled
80 | ```
81 |
82 | That CLI will crete a private S3 Bucket with name AccountID-terraform-states with versioning enabled by default.
83 |
84 | ### Configure Backend
85 |
86 | Go to your pattern and create the following file:
87 |
88 | * **backend.tf**
89 |
90 | Replace the **bucket name** and **dynamodb_table**, if your region is different than us-east-1 also change **region**
91 |
92 | ```
93 | terraform {
94 | backend "s3" {
95 | bucket = "${account_id}-terraform-states" <--- here
96 | ...
97 | region = "us-east-1" <--- here if your region is different than us-east-1
98 | dynamodb_table = "TerraformLockStates" <--- here
99 | }
100 | }
101 | ```
102 |
103 | After configuration, please run the following command:
104 |
105 | ```shell
106 | terraform init
107 | ```
108 |
109 | ## Troubleshooting
110 |
111 | ### Error: Error acquiring the state lock
112 |
113 | Error message: 2 errors occurred:
114 | * ResourceNotFoundException: Requested resource not found
115 | * ResourceNotFoundException: Requested resource not found
116 |
117 | #### Solution
118 |
119 | Create DynamoDB Table on **backend.tf** to store state lock (terraform.backend.dynamodb_table).
120 |
--------------------------------------------------------------------------------
/application/ecsdemo-python/.bandit:
--------------------------------------------------------------------------------
1 | [bandit]
2 | exclude = ./static,./templates,./.env,./tests
--------------------------------------------------------------------------------
/application/ecsdemo-python/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | omit =
3 | app.py
4 | .venv/*
5 | __init__.py
6 | .env/*
7 | source =
8 | .
9 | [report]
10 | include_namespace_packages = True
--------------------------------------------------------------------------------
/application/ecsdemo-python/.dockerignore:
--------------------------------------------------------------------------------
1 | .bandit
2 | tests/*
3 |
4 | *.swp
5 | package-lock.json
6 | .pytest_cache
7 | *.egg-info
8 | */dist
9 | */build
10 | # Byte-compiled / optimized / DLL files
11 | __pycache__/
12 | *.py[cod]
13 | *$py.class
14 |
15 | # Environments
16 | .env
17 | .venv
18 | env/
19 | venv/
20 | ENV/
21 | env.bak/
22 | venv.bak/
23 |
24 | # Coverage
25 | .coverage
26 | reports/
--------------------------------------------------------------------------------
/application/ecsdemo-python/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | __pycache__
3 | .pytest_cache
4 | .venv
--------------------------------------------------------------------------------
/application/ecsdemo-python/.pylintrc:
--------------------------------------------------------------------------------
1 | [MAIN]
2 |
3 | # Analyse import fallback blocks. This can be used to support both Python 2 and
4 | # 3 compatible code, which means that the block might have code that exists
5 | # only in one or another interpreter, leading to false positives when analysed.
6 | analyse-fallback-blocks=no
7 |
8 | # Load and enable all available extensions. Use --list-extensions to see a list
9 | # all available extensions.
10 | #enable-all-extensions=
11 |
12 | # In error mode, messages with a category besides ERROR or FATAL are
13 | # suppressed, and no reports are done by default. Error mode is compatible with
14 | # disabling specific errors.
15 | #errors-only=
16 |
17 | # Always return a 0 (non-error) status code, even if lint errors are found.
18 | # This is primarily useful in continuous integration scripts.
19 | #exit-zero=
20 |
21 | # A comma-separated list of package or module names from where C extensions may
22 | # be loaded. Extensions are loading into the active Python interpreter and may
23 | # run arbitrary code.
24 | extension-pkg-allow-list=
25 |
26 | # A comma-separated list of package or module names from where C extensions may
27 | # be loaded. Extensions are loading into the active Python interpreter and may
28 | # run arbitrary code. (This is an alternative name to extension-pkg-allow-list
29 | # for backward compatibility.)
30 | extension-pkg-whitelist=
31 |
32 | # Return non-zero exit code if any of these messages/categories are detected,
33 | # even if score is above --fail-under value. Syntax same as enable. Messages
34 | # specified are enabled, while categories only check already-enabled messages.
35 | fail-on=
36 |
37 | # Specify a score threshold under which the program will exit with error.
38 | fail-under=10
39 |
40 | # Interpret the stdin as a python script, whose filename needs to be passed as
41 | # the module_or_package argument.
42 | #from-stdin=
43 |
44 | # Files or directories to be skipped. They should be base names, not paths.
45 | ignore=CVS
46 |
47 | # Add files or directories matching the regular expressions patterns to the
48 | # ignore-list. The regex matches against paths and can be in Posix or Windows
49 | # format. Because '\' represents the directory delimiter on Windows systems, it
50 | # can't be used as an escape character.
51 | ignore-paths=
52 |
53 | # Files or directories matching the regular expression patterns are skipped.
54 | # The regex matches against base names, not paths. The default value ignores
55 | # Emacs file locks
56 | ignore-patterns=^\.#
57 |
58 | # List of module names for which member attributes should not be checked
59 | # (useful for modules/projects where namespaces are manipulated during runtime
60 | # and thus existing member attributes cannot be deduced by static analysis). It
61 | # supports qualified module names, as well as Unix pattern matching.
62 | ignored-modules=
63 |
64 | # Python code to execute, usually for sys.path manipulation such as
65 | # pygtk.require().
66 | #init-hook=
67 |
68 | # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
69 | # number of processors available to use, and will cap the count on Windows to
70 | # avoid hangs.
71 | jobs=1
72 |
73 | # Control the amount of potential inferred values when inferring a single
74 | # object. This can help the performance when dealing with large functions or
75 | # complex, nested conditions.
76 | limit-inference-results=100
77 |
78 | # List of plugins (as comma separated values of python module names) to load,
79 | # usually to register additional checkers.
80 | load-plugins=
81 |
82 | # Pickle collected data for later comparisons.
83 | persistent=yes
84 |
85 | # Minimum Python version to use for version dependent checks. Will default to
86 | # the version used to run pylint.
87 | py-version=3.10
88 |
89 | # Discover python modules and packages in the file system subtree.
90 | recursive=no
91 |
92 | # When enabled, pylint would attempt to guess common misconfiguration and emit
93 | # user-friendly hints instead of false-positive error messages.
94 | suggestion-mode=yes
95 |
96 | # Allow loading of arbitrary C extensions. Extensions are imported into the
97 | # active Python interpreter and may run arbitrary code.
98 | unsafe-load-any-extension=no
99 |
100 | # In verbose mode, extra non-checker-related info will be displayed.
101 | #verbose=
102 |
103 |
104 | [BASIC]
105 |
106 | # Naming style matching correct argument names.
107 | argument-naming-style=snake_case
108 |
109 | # Regular expression matching correct argument names. Overrides argument-
110 | # naming-style. If left empty, argument names will be checked with the set
111 | # naming style.
112 | #argument-rgx=
113 |
114 | # Naming style matching correct attribute names.
115 | attr-naming-style=snake_case
116 |
117 | # Regular expression matching correct attribute names. Overrides attr-naming-
118 | # style. If left empty, attribute names will be checked with the set naming
119 | # style.
120 | #attr-rgx=
121 |
122 | # Bad variable names which should always be refused, separated by a comma.
123 | bad-names=foo,
124 | bar,
125 | baz,
126 | toto,
127 | tutu,
128 | tata
129 |
130 | # Bad variable names regexes, separated by a comma. If names match any regex,
131 | # they will always be refused
132 | bad-names-rgxs=
133 |
134 | # Naming style matching correct class attribute names.
135 | class-attribute-naming-style=any
136 |
137 | # Regular expression matching correct class attribute names. Overrides class-
138 | # attribute-naming-style. If left empty, class attribute names will be checked
139 | # with the set naming style.
140 | #class-attribute-rgx=
141 |
142 | # Naming style matching correct class constant names.
143 | class-const-naming-style=UPPER_CASE
144 |
145 | # Regular expression matching correct class constant names. Overrides class-
146 | # const-naming-style. If left empty, class constant names will be checked with
147 | # the set naming style.
148 | #class-const-rgx=
149 |
150 | # Naming style matching correct class names.
151 | class-naming-style=PascalCase
152 |
153 | # Regular expression matching correct class names. Overrides class-naming-
154 | # style. If left empty, class names will be checked with the set naming style.
155 | #class-rgx=
156 |
157 | # Naming style matching correct constant names.
158 | const-naming-style=UPPER_CASE
159 |
160 | # Regular expression matching correct constant names. Overrides const-naming-
161 | # style. If left empty, constant names will be checked with the set naming
162 | # style.
163 | #const-rgx=
164 |
165 | # Minimum line length for functions/classes that require docstrings, shorter
166 | # ones are exempt.
167 | docstring-min-length=-1
168 |
169 | # Naming style matching correct function names.
170 | function-naming-style=snake_case
171 |
172 | # Regular expression matching correct function names. Overrides function-
173 | # naming-style. If left empty, function names will be checked with the set
174 | # naming style.
175 | #function-rgx=
176 |
177 | # Good variable names which should always be accepted, separated by a comma.
178 | good-names=i,
179 | j,
180 | k,
181 | ex,
182 | Run,
183 | _
184 |
185 | # Good variable names regexes, separated by a comma. If names match any regex,
186 | # they will always be accepted
187 | good-names-rgxs=
188 |
189 | # Include a hint for the correct naming format with invalid-name.
190 | include-naming-hint=no
191 |
192 | # Naming style matching correct inline iteration names.
193 | inlinevar-naming-style=any
194 |
195 | # Regular expression matching correct inline iteration names. Overrides
196 | # inlinevar-naming-style. If left empty, inline iteration names will be checked
197 | # with the set naming style.
198 | #inlinevar-rgx=
199 |
200 | # Naming style matching correct method names.
201 | method-naming-style=snake_case
202 |
203 | # Regular expression matching correct method names. Overrides method-naming-
204 | # style. If left empty, method names will be checked with the set naming style.
205 | #method-rgx=
206 |
207 | # Naming style matching correct module names.
208 | module-naming-style=snake_case
209 |
210 | # Regular expression matching correct module names. Overrides module-naming-
211 | # style. If left empty, module names will be checked with the set naming style.
212 | #module-rgx=
213 |
214 | # Colon-delimited sets of names that determine each other's naming style when
215 | # the name regexes allow several styles.
216 | name-group=
217 |
218 | # Regular expression which should only match function or class names that do
219 | # not require a docstring.
220 | no-docstring-rgx=^_
221 |
222 | # List of decorators that produce properties, such as abc.abstractproperty. Add
223 | # to this list to register other decorators that produce valid properties.
224 | # These decorators are taken in consideration only for invalid-name.
225 | property-classes=abc.abstractproperty
226 |
227 | # Regular expression matching correct type variable names. If left empty, type
228 | # variable names will be checked with the set naming style.
229 | #typevar-rgx=
230 |
231 | # Naming style matching correct variable names.
232 | variable-naming-style=snake_case
233 |
234 | # Regular expression matching correct variable names. Overrides variable-
235 | # naming-style. If left empty, variable names will be checked with the set
236 | # naming style.
237 | #variable-rgx=
238 |
239 |
240 | [CLASSES]
241 |
242 | # Warn about protected attribute access inside special methods
243 | check-protected-access-in-special-methods=no
244 |
245 | # List of method names used to declare (i.e. assign) instance attributes.
246 | defining-attr-methods=__init__,
247 | __new__,
248 | setUp,
249 | __post_init__
250 |
251 | # List of member names, which should be excluded from the protected access
252 | # warning.
253 | exclude-protected=_asdict,
254 | _fields,
255 | _replace,
256 | _source,
257 | _make
258 |
259 | # List of valid names for the first argument in a class method.
260 | valid-classmethod-first-arg=cls
261 |
262 | # List of valid names for the first argument in a metaclass class method.
263 | valid-metaclass-classmethod-first-arg=cls
264 |
265 |
266 | [DESIGN]
267 |
268 | # List of regular expressions of class ancestor names to ignore when counting
269 | # public methods (see R0903)
270 | exclude-too-few-public-methods=
271 |
272 | # List of qualified class names to ignore when counting class parents (see
273 | # R0901)
274 | ignored-parents=
275 |
276 | # Maximum number of arguments for function / method.
277 | max-args=5
278 |
279 | # Maximum number of attributes for a class (see R0902).
280 | max-attributes=7
281 |
282 | # Maximum number of boolean expressions in an if statement (see R0916).
283 | max-bool-expr=5
284 |
285 | # Maximum number of branch for function / method body.
286 | max-branches=12
287 |
288 | # Maximum number of locals for function / method body.
289 | max-locals=15
290 |
291 | # Maximum number of parents for a class (see R0901).
292 | max-parents=7
293 |
294 | # Maximum number of public methods for a class (see R0904).
295 | max-public-methods=20
296 |
297 | # Maximum number of return / yield for function / method body.
298 | max-returns=6
299 |
300 | # Maximum number of statements in function / method body.
301 | max-statements=50
302 |
303 | # Minimum number of public methods for a class (see R0903).
304 | min-public-methods=2
305 |
306 |
307 | [EXCEPTIONS]
308 |
309 | # Exceptions that will emit a warning when caught.
310 | overgeneral-exceptions=builtins.BaseException,
311 | builtins.Exception
312 |
313 |
314 | [FORMAT]
315 |
316 | # Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
317 | expected-line-ending-format=
318 |
319 | # Regexp for a line that is allowed to be longer than the limit.
320 | ignore-long-lines=^\s*(# )??$
321 |
322 | # Number of spaces of indent required inside a hanging or continued line.
323 | indent-after-paren=4
324 |
325 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
326 | # tab).
327 | indent-string=' '
328 |
329 | # Maximum number of characters on a single line.
330 | max-line-length=826
331 |
332 | # Maximum number of lines in a module.
333 | max-module-lines=1000
334 |
335 | # Allow the body of a class to be on the same line as the declaration if body
336 | # contains single statement.
337 | single-line-class-stmt=no
338 |
339 | # Allow the body of an if to be on the same line as the test if there is no
340 | # else.
341 | single-line-if-stmt=no
342 |
343 |
344 | [IMPORTS]
345 |
346 | # List of modules that can be imported at any level, not just the top level
347 | # one.
348 | allow-any-import-level=
349 |
350 | # Allow wildcard imports from modules that define __all__.
351 | allow-wildcard-with-all=no
352 |
353 | # Deprecated modules which should not be used, separated by a comma.
354 | deprecated-modules=
355 |
356 | # Output a graph (.gv or any supported image format) of external dependencies
357 | # to the given file (report RP0402 must not be disabled).
358 | ext-import-graph=
359 |
360 | # Output a graph (.gv or any supported image format) of all (i.e. internal and
361 | # external) dependencies to the given file (report RP0402 must not be
362 | # disabled).
363 | import-graph=
364 |
365 | # Output a graph (.gv or any supported image format) of internal dependencies
366 | # to the given file (report RP0402 must not be disabled).
367 | int-import-graph=
368 |
369 | # Force import order to recognize a module as part of the standard
370 | # compatibility libraries.
371 | known-standard-library=
372 |
373 | # Force import order to recognize a module as part of a third party library.
374 | known-third-party=enchant
375 |
376 | # Couples of modules and preferred modules, separated by a comma.
377 | preferred-modules=
378 |
379 |
380 | [LOGGING]
381 |
382 | # The type of string formatting that logging methods do. `old` means using %
383 | # formatting, `new` is for `{}` formatting.
384 | logging-format-style=old
385 |
386 | # Logging modules to check that the string format arguments are in logging
387 | # function parameter format.
388 | logging-modules=logging
389 |
390 |
391 | [MESSAGES CONTROL]
392 |
393 | # Only show warnings with the listed confidence levels. Leave empty to show
394 | # all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
395 | # UNDEFINED.
396 | confidence=HIGH,
397 | CONTROL_FLOW,
398 | INFERENCE,
399 | INFERENCE_FAILURE,
400 | UNDEFINED
401 |
402 | # Disable the message, report, category or checker with the given id(s). You
403 | # can either give multiple identifiers separated by comma (,) or put this
404 | # option multiple times (only on the command line, not in the configuration
405 | # file where it should appear only once). You can also use "--disable=all" to
406 | # disable everything first and then re-enable specific checks. For example, if
407 | # you want to run only the similarities checker, you can use "--disable=all
408 | # --enable=similarities". If you want to run only the classes checker, but have
409 | # no Warning level messages displayed, use "--disable=all --enable=classes
410 | # --disable=W".
411 | disable=raw-checker-failed,
412 | bad-inline-option,
413 | locally-disabled,
414 | file-ignored,
415 | suppressed-message,
416 | useless-suppression,
417 | deprecated-pragma,
418 | use-symbolic-message-instead,
419 | C0116,
420 | C0114,
421 | C0304
422 |
423 | # Enable the message, report, category or checker with the given id(s). You can
424 | # either give multiple identifier separated by comma (,) or put this option
425 | # multiple time (only on the command line, not in the configuration file where
426 | # it should appear only once). See also the "--disable" option for examples.
427 | enable=c-extension-no-member
428 |
429 |
430 | [METHOD_ARGS]
431 |
432 | # List of qualified names (i.e., library.method) which require a timeout
433 | # parameter e.g. 'requests.api.get,requests.api.post'
434 | timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
435 |
436 |
437 | [MISCELLANEOUS]
438 |
439 | # List of note tags to take in consideration, separated by a comma.
440 | notes=FIXME,
441 | XXX,
442 | TODO
443 |
444 | # Regular expression of note tags to take in consideration.
445 | notes-rgx=
446 |
447 |
448 | [REFACTORING]
449 |
450 | # Maximum number of nested blocks for function / method body
451 | max-nested-blocks=5
452 |
453 | # Complete name of functions that never returns. When checking for
454 | # inconsistent-return-statements if a never returning function is called then
455 | # it will be considered as an explicit return statement and no message will be
456 | # printed.
457 | never-returning-functions=sys.exit,argparse.parse_error
458 |
459 |
460 | [REPORTS]
461 |
462 | # Python expression which should return a score less than or equal to 10. You
463 | # have access to the variables 'fatal', 'error', 'warning', 'refactor',
464 | # 'convention', and 'info' which contain the number of messages in each
465 | # category, as well as 'statement' which is the total number of statements
466 | # analyzed. This score is used by the global evaluation report (RP0004).
467 | evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
468 |
469 | # Template used to display messages. This is a python new-style format string
470 | # used to format the message information. See doc for all details.
471 | msg-template=
472 |
473 | # Set the output format. Available formats are text, parseable, colorized, json
474 | # and msvs (visual studio). You can also give a reporter class, e.g.
475 | # mypackage.mymodule.MyReporterClass.
476 | #output-format=
477 |
478 | # Tells whether to display a full report or only the messages.
479 | reports=no
480 |
481 | # Activate the evaluation score.
482 | score=yes
483 |
484 |
485 | [SIMILARITIES]
486 |
487 | # Comments are removed from the similarity computation
488 | ignore-comments=yes
489 |
490 | # Docstrings are removed from the similarity computation
491 | ignore-docstrings=yes
492 |
493 | # Imports are removed from the similarity computation
494 | ignore-imports=yes
495 |
496 | # Signatures are removed from the similarity computation
497 | ignore-signatures=yes
498 |
499 | # Minimum lines number of a similarity.
500 | min-similarity-lines=4
501 |
502 |
503 | [SPELLING]
504 |
505 | # Limits count of emitted suggestions for spelling mistakes.
506 | max-spelling-suggestions=4
507 |
508 | # Spelling dictionary name. Available dictionaries: none. To make it work,
509 | # install the 'python-enchant' package.
510 | spelling-dict=
511 |
512 | # List of comma separated words that should be considered directives if they
513 | # appear at the beginning of a comment and should not be checked.
514 | spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
515 |
516 | # List of comma separated words that should not be checked.
517 | spelling-ignore-words=
518 |
519 | # A path to a file that contains the private dictionary; one word per line.
520 | spelling-private-dict-file=
521 |
522 | # Tells whether to store unknown words to the private dictionary (see the
523 | # --spelling-private-dict-file option) instead of raising a message.
524 | spelling-store-unknown-words=no
525 |
526 |
527 | [STRING]
528 |
529 | # This flag controls whether inconsistent-quotes generates a warning when the
530 | # character used as a quote delimiter is used inconsistently within a module.
531 | check-quote-consistency=no
532 |
533 | # This flag controls whether the implicit-str-concat should generate a warning
534 | # on implicit string concatenation in sequences defined over several lines.
535 | check-str-concat-over-line-jumps=no
536 |
537 |
538 | [TYPECHECK]
539 |
540 | # List of decorators that produce context managers, such as
541 | # contextlib.contextmanager. Add to this list to register other decorators that
542 | # produce valid context managers.
543 | contextmanager-decorators=contextlib.contextmanager
544 |
545 | # List of members which are set dynamically and missed by pylint inference
546 | # system, and so shouldn't trigger E1101 when accessed. Python regular
547 | # expressions are accepted.
548 | generated-members=
549 |
550 | # Tells whether to warn about missing members when the owner of the attribute
551 | # is inferred to be None.
552 | ignore-none=yes
553 |
554 | # This flag controls whether pylint should warn about no-member and similar
555 | # checks whenever an opaque object is returned when inferring. The inference
556 | # can return multiple potential results while evaluating a Python object, but
557 | # some branches might not be evaluated, which results in partial inference. In
558 | # that case, it might be useful to still emit no-member and other checks for
559 | # the rest of the inferred objects.
560 | ignore-on-opaque-inference=yes
561 |
562 | # List of symbolic message names to ignore for Mixin members.
563 | ignored-checks-for-mixins=no-member,
564 | not-async-context-manager,
565 | not-context-manager,
566 | attribute-defined-outside-init
567 |
568 | # List of class names for which member attributes should not be checked (useful
569 | # for classes with dynamically set attributes). This supports the use of
570 | # qualified names.
571 | ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
572 |
573 | # Show a hint with possible names when a member name was not found. The aspect
574 | # of finding the hint is based on edit distance.
575 | missing-member-hint=yes
576 |
577 | # The minimum edit distance a name should have in order to be considered a
578 | # similar match for a missing member name.
579 | missing-member-hint-distance=1
580 |
581 | # The total number of similar names that should be taken in consideration when
582 | # showing a hint for a missing member.
583 | missing-member-max-choices=1
584 |
585 | # Regex pattern to define which classes are considered mixins.
586 | mixin-class-rgx=.*[Mm]ixin
587 |
588 | # List of decorators that change the signature of a decorated function.
589 | signature-mutators=
590 |
591 |
592 | [VARIABLES]
593 |
594 | # List of additional names supposed to be defined in builtins. Remember that
595 | # you should avoid defining new builtins when possible.
596 | additional-builtins=
597 |
598 | # Tells whether unused global variables should be treated as a violation.
599 | allow-global-unused-variables=yes
600 |
601 | # List of names allowed to shadow builtins
602 | allowed-redefined-builtins=
603 |
604 | # List of strings which can identify a callback function by name. A callback
605 | # name must start or end with one of those strings.
606 | callbacks=cb_,
607 | _cb
608 |
609 | # A regular expression matching the name of dummy variables (i.e. expected to
610 | # not be used).
611 | dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
612 |
613 | # Argument names that match this expression will be ignored.
614 | ignored-argument-names=_.*|^ignored_|^unused_
615 |
616 | # Tells whether we should check for unused import in __init__ files.
617 | init-import=no
618 |
619 | # List of qualified module names which can have objects that can redefine
620 | # builtins.
621 | redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
622 |
--------------------------------------------------------------------------------
/application/ecsdemo-python/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM public.ecr.aws/docker/library/alpine:3.19.1
2 |
3 | RUN apk add --no-cache python3
4 | RUN rm /usr/lib/python3.11/EXTERNALLY-MANAGED
5 | RUN python3 -m ensurepip
6 | RUN pip3 install --upgrade pip
7 |
8 | # Update vulnerable packages
9 | RUN apk update && apk upgrade
10 | RUN pip3 install --upgrade setuptools
11 |
12 | WORKDIR /app
13 | ADD . /app
14 | RUN pip3 install -r requirements.txt
15 |
16 | CMD ["python", "app.py"]
--------------------------------------------------------------------------------
/application/ecsdemo-python/app.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import platform
3 | import os
4 | import sys
5 | import logging
6 | import flask
7 |
8 | LOG_LEVEL = logging.INFO
9 | logger = logging.getLogger()
10 | logger.setLevel(LOG_LEVEL)
11 | log_handler = logging.StreamHandler(sys.stdout)
12 | logger.addHandler(log_handler)
13 |
14 | def create_app():
15 | #pylint: disable=W0621
16 | app = flask.Flask(__name__)
17 | @app.route('/')
18 | def hello():
19 | logger.info('--------GET Root---------')
20 |
21 | app_name = os.environ.get('APP_NAME', 'Amazon ECS Flask Webpage')
22 | container_service = os.environ.get('CONTAINER_SERVICE', 'AWS')
23 | infra_version = os.environ.get('INFRA_VERSION', '0.0.0')
24 | python_version = platform.python_version()
25 | now = datetime.datetime.now()
26 |
27 | return flask.render_template(
28 | 'index.html',
29 | name=app_name,
30 | platform=container_service,
31 | infra_version=infra_version,
32 | flask_version=flask.__version__,
33 | python_version=python_version,
34 | time=now
35 | )
36 | return app
37 |
38 | if __name__ == '__main__':
39 | app = create_app()
40 | HOST = '0.0.0.0' #nosec
41 | port = int(os.environ.get('PORT_IN', '3000'))
42 | logger.info('--------start main---------')
43 | app.run(host=HOST, port=port)
44 |
--------------------------------------------------------------------------------
/application/ecsdemo-python/requirements-dev.txt:
--------------------------------------------------------------------------------
1 | pylint==2.17.4
2 | pytest==7.4.0
3 | coverage==7.2.7
4 | bandit==1.7.8
5 | safety==2.3.5
--------------------------------------------------------------------------------
/application/ecsdemo-python/requirements.txt:
--------------------------------------------------------------------------------
1 | flask==2.3.2
2 |
--------------------------------------------------------------------------------
/application/ecsdemo-python/static/amazon-ecs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/fargate-serverless-platform-operator-kit/89f06f4090c3a1d16e121b1010efe73207a04579/application/ecsdemo-python/static/amazon-ecs.png
--------------------------------------------------------------------------------
/application/ecsdemo-python/static/css/style.css:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | font-family: Helvetica;
4 | background-color: #f4f4f4;
5 | display: flex;
6 | flex-direction: column;
7 | justify-content: center;
8 | align-items: center;
9 | min-height: 100vh;
10 | margin: 20px;
11 | }
12 |
13 | .container {
14 | display: flex;
15 | flex-direction: column;
16 | justify-content: center;
17 | align-items: center;
18 | background-color: #ffe8ca;
19 | padding: 30px;
20 | box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.1);
21 | border-radius: 5px;
22 | }
23 |
24 | h1 {
25 | color: #232F3E;
26 | font-size: 32px;
27 | font-weight: bold;
28 | margin-bottom: 20px;
29 | }
30 |
--------------------------------------------------------------------------------
/application/ecsdemo-python/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |