├── .coveragerc ├── .flake8 ├── .github ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ ├── PULL_REQUEST_TEMPLATE.md │ └── feature_request.md ├── dependabot.yml └── workflows │ └── main.yml ├── .gitignore ├── CHANGES.rst ├── LICENSE.txt ├── MANIFEST.in ├── README.rst ├── THIRD-PARTY ├── bin ├── __init__.py ├── eb └── ebp ├── conf.py ├── dev_requirements.txt ├── ebcli ├── __init__.py ├── bundled │ ├── __init__.py │ └── asciimatics │ │ ├── __init__.py │ │ ├── event.py │ │ ├── exceptions.py │ │ ├── overrides.py │ │ ├── screen.py │ │ └── utilities.py ├── containers │ ├── __init__.py │ ├── abstractcontainer.py │ ├── commands.py │ ├── compat.py │ ├── compose.py │ ├── container_viewmodel.py │ ├── containerfiles │ │ ├── container_config.json │ │ ├── glassfish-runtime-4.0-jdk7 │ │ ├── glassfish-runtime-4.1-jdk8 │ │ ├── glassfish-runtime-5.0-al │ │ ├── golang-runtime-1.3 │ │ ├── golang-runtime-1.4 │ │ └── python3-runtime │ ├── containerops.py │ ├── dockerrun.py │ ├── envvarcollector.py │ ├── factory.py │ ├── fshandler.py │ ├── generic_container.py │ ├── log.py │ ├── multicontainer.py │ ├── pathconfig.py │ ├── preconfigured_container.py │ └── utils.py ├── controllers │ ├── __init__.py │ ├── abort.py │ ├── appversion.py │ ├── clone.py │ ├── codesource.py │ ├── config.py │ ├── console.py │ ├── create.py │ ├── deploy.py │ ├── events.py │ ├── health.py │ ├── initialize.py │ ├── lifecycle.py │ ├── list.py │ ├── local.py │ ├── logs.py │ ├── migrate.py │ ├── migrate_scripts │ │ ├── add_virtual_dir_read_access.ps1 │ │ ├── arr_configuration_importer_script.ps1 │ │ ├── arr_msi_installer.ps1 │ │ ├── default_web_site_port_reassignment_template.ps1 │ │ ├── ebdeploy_utils.ps1 │ │ ├── modify_firewall_config.ps1 │ │ ├── noop.ps1 │ │ ├── reinstate_iisstart_htm_default_document.ps1 │ │ ├── site_installer_template.ps1 │ │ ├── site_removal_template.ps1 │ │ ├── site_restart_template.ps1 │ │ └── windows_proxy_feature_enabler.ps1 │ ├── open.py │ ├── platform │ │ ├── __init__.py │ │ ├── create.py │ │ ├── delete.py │ │ ├── events.py │ │ ├── initialize.py │ │ ├── list.py │ │ ├── logs.py │ │ ├── status.py │ │ └── use.py │ ├── printenv.py │ ├── restore.py │ ├── scale.py │ ├── setenv.py │ ├── ssh.py │ ├── status.py │ ├── swap.py │ ├── tags.py │ ├── terminate.py │ ├── upgrade.py │ └── use.py ├── core │ ├── __init__.py │ ├── abstractcontroller.py │ ├── base.py │ ├── ebcore.py │ ├── ebglobals.py │ ├── ebpcore.py │ ├── ebrun.py │ ├── fileoperations.py │ ├── hooks.py │ └── io.py ├── display │ ├── README │ ├── __init__.py │ ├── appversion.py │ ├── data_poller.py │ ├── environments.py │ ├── help.py │ ├── screen.py │ ├── specialtables.py │ ├── table.py │ ├── term.py │ └── traditional.py ├── labs │ ├── __init__.py │ ├── cleanupversions.py │ ├── cloudwatchfiles │ │ ├── cwl-activity-logs-v1.config │ │ ├── cwl-setup-v1.config │ │ └── eb-logs-v1.config │ ├── cloudwatchsetup.py │ ├── controller.py │ ├── convertdockerrun.py │ ├── download.py │ ├── quicklink.py │ └── setupssl.py ├── lib │ ├── __init__.py │ ├── aws.py │ ├── botocoredata │ │ └── elasticbeanstalk │ │ │ └── 2010-12-01 │ │ │ ├── paginators-1.json │ │ │ └── service-2.json │ ├── botopatch.py │ ├── cloudformation.py │ ├── cloudwatch.py │ ├── codebuild.py │ ├── codecommit.py │ ├── ec2.py │ ├── elasticbeanstalk.py │ ├── elb.py │ ├── elbv2.py │ ├── heuristics.py │ ├── iam.py │ ├── kms.py │ ├── s3.py │ ├── sns.py │ └── utils.py ├── objects │ ├── __init__.py │ ├── api_filters.py │ ├── application.py │ ├── buildconfiguration.py │ ├── cfn_stack.py │ ├── conversionconfiguration.py │ ├── environment.py │ ├── environmentsettings.py │ ├── event.py │ ├── exceptions.py │ ├── lifecycleconfiguration.py │ ├── log_stream.py │ ├── platform.py │ ├── region.py │ ├── requests.py │ ├── solutionstack.py │ ├── sourcecontrol.py │ └── tier.py ├── operations │ ├── __init__.py │ ├── abortops.py │ ├── appversionops.py │ ├── buildspecops.py │ ├── cloneops.py │ ├── commonops.py │ ├── composeops.py │ ├── configops.py │ ├── consoleops.py │ ├── createops.py │ ├── deployops.py │ ├── envvarops.py │ ├── eventsops.py │ ├── gitops.py │ ├── healthops.py │ ├── initializeops.py │ ├── lifecycleops.py │ ├── listops.py │ ├── localops.py │ ├── logsops.py │ ├── openops.py │ ├── platform_branch_ops.py │ ├── platform_version_ops.py │ ├── platformops.py │ ├── restoreops.py │ ├── saved_configs.py │ ├── scaleops.py │ ├── shared_lb_ops.py │ ├── solution_stack_ops.py │ ├── spotops.py │ ├── sshops.py │ ├── statusops.py │ ├── swapops.py │ ├── tagops │ │ ├── __init__.py │ │ ├── taglist.py │ │ └── tagops.py │ ├── terminateops.py │ ├── upgradeops.py │ └── useops.py └── resources │ ├── __init__.py │ ├── regex.py │ ├── statics.py │ └── strings.py ├── index.rst ├── requirements.txt ├── scripts └── jenkins │ ├── install_dependencies │ ├── run_unit_tests │ ├── runner.ps1 │ └── runner.sh ├── setup.py └── tests ├── __init__.py ├── conftest.py ├── test_dependencies_mismatch.py ├── test_help_texts.py └── unit ├── __init__.py ├── baseinttest.py ├── containers ├── __init__.py ├── dummy.py ├── test_abstractcontainer.py ├── test_commands.py ├── test_compat.py ├── test_compose.py ├── test_container_viewmodel.py ├── test_containerops.py ├── test_dockerrun.py ├── test_envvarcollector.py ├── test_factory.py ├── test_fshandler.py ├── test_generic_container.py ├── test_log.py ├── test_multicontainer.py └── test_preconfigured_container.py ├── controllers ├── __init__.py ├── platform │ ├── test_create.py │ ├── test_delete.py │ ├── test_events.py │ ├── test_initialize.py │ ├── test_list.py │ ├── test_logs.py │ ├── test_platform.py │ ├── test_status.py │ └── test_use.py ├── test_appversion.py ├── test_clone.py ├── test_codesource.py ├── test_config.py ├── test_create.py ├── test_deploy.py ├── test_events.py ├── test_health.py ├── test_init.py ├── test_lifecycle.py ├── test_list.py ├── test_local.py ├── test_logs.py ├── test_migrate.py ├── test_open.py ├── test_restore.py ├── test_ssh.py ├── test_tags.py ├── test_terminate.py └── test_upgrade.py ├── core ├── __init__.py ├── test_abstractcontroller.py ├── test_base.py ├── test_ebpcore.py ├── test_ebrun.py ├── test_fileoperations.py └── test_io.py ├── display ├── test_data_poller.py ├── test_tables.py └── test_traditional.py ├── integration ├── __init__.py ├── mockservice.py ├── test_abort.py ├── test_deploy.py ├── test_health.py ├── test_migrate.py └── test_profile_selection.py ├── lib ├── __init__.py ├── test_aws.py ├── test_cloudformation.py ├── test_cloudwatch.py ├── test_codebuild.py ├── test_codecommit.py ├── test_ec2.py ├── test_elasticbeanstalk.py ├── test_elbv2.py ├── test_heuristics.py ├── test_iam.py ├── test_kms.py ├── test_s3.py ├── test_s3_upload_workspace.py ├── test_sns.py └── test_utils.py ├── mock_logs.py ├── mock_responses.py ├── objects ├── __init__.py ├── test_cfn_stack.py ├── test_environment.py ├── test_environmentsettings.py ├── test_event.py ├── test_lifecyleconfiguration.py ├── test_log_stream.py ├── test_platform.py ├── test_request.py ├── test_solutionstack.py ├── test_sourcecontrol.py └── test_tier.py ├── operations ├── __init__.py ├── tagops │ ├── test_taglist.py │ └── test_tagops.py ├── test_appversionops.py ├── test_buildspecops.py ├── test_cloneops.py ├── test_commonops.py ├── test_composeops.py ├── test_configops.py ├── test_consoleops.py ├── test_createops.py ├── test_deployops.py ├── test_deployops_source_bundle.py ├── test_ebignore.py ├── test_environments.py ├── test_envvarops.py ├── test_eventsops.py ├── test_gitops.py ├── test_healthops.py ├── test_initializeops.py ├── test_lifecycleops.py ├── test_localops.py ├── test_logsops.py ├── test_platform_branch_ops.py ├── test_platform_version_ops.py ├── test_platformops.py ├── test_restoreops.py ├── test_saved_configs.py ├── test_scaleops.py ├── test_shared_lb_ops.py ├── test_solution_stack_ops.py ├── test_spotops.py ├── test_sshops.py ├── test_statusops.py ├── test_terminateops.py ├── test_upgradeops.py └── test_useops.py └── test_helper.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = ebcli/bundled/* 3 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 110 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create an Issue to report a bug 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 12 | 13 | ### Description 14 | 15 | Briefly describe the bug you are facing. 16 | 17 | ### Steps to reproduce 18 | 19 | Provide steps to replicate. This should include: exact `ebcli` commands, any relevant configuration files(sanitized), platform version, region, as well as any additional information you think is relevant. 20 | 21 | ### Observed result 22 | 23 | Please provide command output with `--debug` flag set. 24 | 25 | ### Expected result 26 | 27 | Describe what you expected. 28 | 29 | ### Additional environment details (Ex: Windows, Mac, Amazon Linux etc) 30 | 31 | 1. OS: 32 | 2. EBCLI version: 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Why is this change necessary?* 4 | 5 | *How does it address the issue?* 6 | 7 | *What side effects does this change have?* 8 | 9 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for the eb cli project and the team will review! 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Community Note 11 | 12 | Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request. Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request. If you are interested in working on this issue or have submitted a pull request, please leave a comment. 13 | 14 | ### Tell us about your request 15 | What do you want us to build? 16 | 17 | ### Tell us about the problem you're trying to solve. What are you trying to do, and why is it hard? 18 | What outcome are you trying to achieve, ultimately, and why is it hard/impossible to do right now? What is the impact of not having this problem solved? The more details you can provide, the better we'll be able to understand and solve the problem. 19 | 20 | ### Are you currently working around this issue? 21 | 22 | ### How are you currently solving this problem? 23 | 24 | ### Additional context 25 | Anything else we should know? 26 | 27 | ### Attachments 28 | If you think you might have additional information that you'd like to include via an attachment, please do - we'll take a look. (Remember to remove any personally-identifiable information). 29 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | 9 | - package-ecosystem: "pip" # See documentation for possible values 10 | directory: "/" # Location of package manifests 11 | schedule: 12 | interval: "daily" 13 | time: "20:30" #UTC 14 | allow: 15 | - dependency-name: "botocore*" 16 | dependency-type: "all" 17 | ignore: 18 | - dependency-name: "botocore*" 19 | update-types: [ "version-update:semver-patch" ] -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow that set up CICD infra 2 | name: CI 3 | 4 | # Controls when the workflow will run 5 | on: 6 | # Triggers the workflow on pull request events but only for the main branch 7 | pull_request: 8 | branches: [ master ] 9 | workflow_dispatch: 10 | 11 | permissions: write-all 12 | 13 | jobs: 14 | # WindowsBuild and AmazonLinux build run unit tests and E2E tests 15 | WindowsBuild: 16 | # Although the job runs on Ubuntu, but it will trigger a codebuild job that runs on Win 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Configure AWS Credentials 20 | uses: aws-actions/configure-aws-credentials@v1 21 | with: 22 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 23 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 24 | aws-region: us-west-2 25 | - name: Run CodeBuild 26 | uses: aws-actions/aws-codebuild-run-build@v1 27 | with: 28 | project-name: EBCLI-codetest-windows 29 | AmazonLinuxBuild: 30 | runs-on: ubuntu-latest 31 | steps: 32 | - name: Configure AWS Credentials 33 | uses: aws-actions/configure-aws-credentials@v1 34 | with: 35 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 36 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 37 | aws-region: us-west-2 38 | - name: Run CodeBuild 39 | uses: aws-actions/aws-codebuild-run-build@v1 40 | with: 41 | project-name: EBCLI-codetest-AL 42 | # The auto merge will only be executed if author is dependabot 43 | dependabotAutoMerge: 44 | needs: [WindowsBuild, AmazonLinuxBuild] 45 | runs-on: ubuntu-latest 46 | if: ${{ github.actor == 'dependabot[bot]' }} 47 | steps: 48 | - name: Dependabot metadata 49 | id: metadata 50 | uses: dependabot/fetch-metadata@v1.1.1 51 | with: 52 | github-token: "${{ secrets.GITHUB_TOKEN }}" 53 | - name: Login github cli using admin token 54 | run: gh auth login --with-token <<< "$BOT_TOKEN" 55 | env: 56 | BOT_TOKEN: ${{secrets.BEANRUNNER_BOT_TOKEN}} 57 | - name: Approve a PR 58 | run: gh pr review --approve "$PR_URL" 59 | env: 60 | PR_URL: ${{github.event.pull_request.html_url}} 61 | - name: Enable auto-merge for Dependabot PRs 62 | run: gh pr merge --auto --merge "$PR_URL" 63 | env: 64 | PR_URL: ${{github.event.pull_request.html_url}} 65 | approveAdminIssuedPR: 66 | needs: [WindowsBuild, AmazonLinuxBuild] 67 | runs-on: ubuntu-latest 68 | if: ${{ github.actor != 'dependabot[bot]' }} 69 | steps: 70 | - name: "Check if user has write access" 71 | uses: "lannonbr/repo-permission-check-action@2.0.0" 72 | with: 73 | permission: "write" 74 | env: 75 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 76 | - name: Approve a PR 77 | run: gh pr review --approve "$PR_URL" 78 | env: 79 | PR_URL: ${{github.event.pull_request.html_url}} 80 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .eggs/ 2 | *.pyc 3 | *.swp 4 | *.pyo 5 | *.class 6 | *~ 7 | *# 8 | /doc/generated/* 9 | /runpy 10 | /build 11 | /.idea 12 | /dist 13 | /out 14 | eb.py 15 | awsebcli.egg-info/ 16 | .eggs/ 17 | *.DS_Store 18 | .cache/ 19 | *.coverage 20 | *.xml 21 | *.iml 22 | .vscode/ 23 | venv 24 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE.txt 2 | include CHANGES.rst 3 | include README.rst 4 | include PKG_INFO 5 | exclude .coveragerc 6 | exclude .coverage 7 | exclude index.rst 8 | exclude conf.py 9 | exclude .gitignore 10 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ====== 2 | EB CLI 3 | ====== 4 | 5 | Introduction 6 | ============ 7 | 8 | The AWS Elastic Beanstalk Command Line Interface (EB CLI) is a tool that helps you deploy and manage 9 | your Elastic Beanstalk applications and environments. It also 10 | provides integration with Git. 11 | 12 | For detailed information about the EB CLI, see `Using the Elastic Beanstalk Command Line Interface (EB CLI) `__ 13 | in the *AWS Elastic Beanstalk Developer Guide*. 14 | 15 | The EB CLI is now an open source project, hosted in this repository. 16 | You're welcome to participate by reporting issues, making suggestions, and submitting pull requests. 17 | We value your contributions! 18 | 19 | Installation 20 | ============ 21 | 22 | ------------------------------- 23 | If you'd like to use the EB CLI 24 | ------------------------------- 25 | 26 | The easiest and recommended way to install the EB CLI is to use the EB CLI setup scripts available on a separate GitHub repository. 27 | Use the scripts to install the EB CLI on Linux, macOS, or Windows. The scripts install the EB CLI and its dependencies, including Python and pip. 28 | The scripts also create a virtual environment for the EB CLI. 29 | For installation instructions, see the `aws/aws-elastic-beanstalk-cli-setup `__ repository. 30 | 31 | ----------------------------------------- 32 | If you'd like to contribute to the EB CLI 33 | ----------------------------------------- 34 | 35 | Dependencies 36 | ~~~~~~~~~~~~ 37 | Install Python and Pip. The most recent version of Python now includes pip. 38 | 39 | To install Python, go `here `__. 40 | 41 | If you already have Python, but need to install Pip, go `here `__. 42 | 43 | Install the EB CLI from this repository 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | 46 | You need administrator/sudo privileges unless you install into a virtual environment. 47 | 48 | To install the EB CLI 49 | 50 | 1. Clone or download this repository to your local environment. 51 | 52 | 2. Navigate to the the root of the repository. 53 | 54 | 3. Run the following command. 55 | 56 | `pip install .`:code: 57 | 58 | Getting Started 59 | =============== 60 | 61 | The EB CLI requires you to have AWS security credentials. 62 | To learn how to get security credentials, see `Managing Access Keys for Your AWS Account Root User `__ 63 | in the *AWS General Reference*. 64 | 65 | To view a list of EB CLI commands, type: 66 | 67 | eb --help 68 | 69 | For more information about a specific command, type: 70 | 71 | eb {cmd} --help 72 | 73 | For a detailed command reference for all EB CLI commands, see `EB CLI Command Reference `__ 74 | in the *AWS Elastic Beanstalk Developer Guide*. 75 | 76 | 77 | -------------------------------------------------------------------------------- /bin/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | -------------------------------------------------------------------------------- /bin/eb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # http://aws.amazon.com/apache2.0/ 7 | # or in the "license" file accompanying this file. This file is 8 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 9 | # ANY KIND, either express or implied. See the License for the specific 10 | # language governing permissions and limitations under the License. 11 | import sys 12 | import ebcli.core.ebcore 13 | 14 | def main(): 15 | return ebcli.core.ebcore.main() 16 | 17 | if __name__ == '__main__': 18 | sys.exit(main()) -------------------------------------------------------------------------------- /bin/ebp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # http://aws.amazon.com/apache2.0/ 7 | # or in the "license" file accompanying this file. This file is 8 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 9 | # ANY KIND, either express or implied. See the License for the specific 10 | # language governing permissions and limitations under the License. 11 | import sys 12 | import ebcli.core.ebpcore as ebpcore 13 | 14 | def main(): 15 | return ebpcore.main() 16 | 17 | if __name__ == '__main__': 18 | sys.exit(main()) -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # -- General configuration ----------------------------------------------------- 4 | 5 | source_suffix = '.rst' 6 | master_doc = 'index' 7 | 8 | project = u'sphinx theme for dotted style' 9 | copyright = u'2011, Sphinx-users.jp' 10 | 11 | version = '0.1.2' 12 | 13 | # -- Options for HTML output --------------------------------------------------- 14 | 15 | # html_theme = 'dotted' 16 | 17 | # -- HTML theme options for `dotted` style ------------------------------------- 18 | 19 | # html_theme_options = { 20 | # 'slidetoc': True, 21 | # 'enablesidebar': True, 22 | # 'rightsidebar': True, 23 | # } -------------------------------------------------------------------------------- /dev_requirements.txt: -------------------------------------------------------------------------------- 1 | flake8 2 | pytest==8.3.5 3 | mock 4 | pytest-cov>=2.12.1 5 | pytest-socket>=0.6.0 6 | -------------------------------------------------------------------------------- /ebcli/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"). You 5 | # may not use this file except in compliance with the License. A copy of 6 | # the License is located at 7 | # 8 | # http://aws.amazon.com/apache2.0/ 9 | # 10 | # or in the "license" file accompanying this file. This file is 11 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 12 | # ANY KIND, either express or implied. See the License for the specific 13 | # language governing permissions and limitations under the License. 14 | __version__ = '3.24.1' 15 | -------------------------------------------------------------------------------- /ebcli/bundled/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/bundled/asciimatics/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Peter Brittain 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | """ 15 | 16 | Asciimatics is a package to help people create full-screen text UIs (from interactive forms to 17 | ASCII animations) on any platform. It is licensed under the Apache Software Foundation License 2.0. 18 | """ 19 | __author__ = 'Peter Brittain' 20 | 21 | try: 22 | from .version import version 23 | except ImportError: 24 | # Someone is running straight from the GIT repo - dummy out the version 25 | version = "0.0.0" 26 | 27 | __version__ = version 28 | -------------------------------------------------------------------------------- /ebcli/bundled/asciimatics/event.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Peter Brittain 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | """ 15 | This module defines basic input events. For more details, see 16 | http://asciimatics.readthedocs.io/en/latest/.html 17 | """ 18 | 19 | 20 | class Event(object): 21 | """ 22 | A class to hold information about an input event. 23 | 24 | The exact contents varies from event to event. See specific classes for more information. 25 | """ 26 | 27 | 28 | class KeyboardEvent(Event): 29 | """ 30 | An event that represents a key press. 31 | 32 | Its key field is the `key_code`. This is the ordinal representation of the key (taking into 33 | account keyboard state - e.g. caps lock) if possible, or an extended key code (the `KEY_xxx` 34 | constants in the :py:obj:`.Screen` class) where not. 35 | """ 36 | 37 | def __init__(self, key_code): 38 | """ 39 | :param key_code: the ordinal value of the key that was pressed. 40 | """ 41 | self.key_code = key_code 42 | 43 | def __repr__(self): 44 | """ 45 | :returns: a string representation of the keyboard event. 46 | """ 47 | return "KeyboardEvent: {}".format(self.key_code) 48 | 49 | 50 | class MouseEvent(Event): 51 | """ 52 | An event that represents a mouse move or click. 53 | 54 | Allowed values for the buttons are any bitwise combination of 55 | `LEFT_CLICK`, `RIGHT_CLICK` and `DOUBLE_CLICK`. 56 | """ 57 | 58 | # Mouse button states - bitwise flags 59 | LEFT_CLICK = 1 60 | RIGHT_CLICK = 2 61 | DOUBLE_CLICK = 4 62 | 63 | def __init__(self, x, y, buttons): 64 | """ 65 | :param x: The X coordinate of the mouse event. 66 | :param y: The Y coordinate of the mouse event. 67 | :param buttons: A bitwise flag for any mouse buttons that were pressed (if any). 68 | """ 69 | self.x = x 70 | self.y = y 71 | self.buttons = buttons 72 | 73 | def __repr__(self): 74 | """ 75 | :returns: a string representation of the mouse event. 76 | """ 77 | return "MouseEvent ({}, {}) {}".format(self.x, self.y, self.buttons) 78 | -------------------------------------------------------------------------------- /ebcli/bundled/asciimatics/overrides.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | # Copyright 2016 Peter Brittain 15 | # 16 | # Licensed under the Apache License, Version 2.0 (the "License"); 17 | # you may not use this file except in compliance with the License. 18 | # You may obtain a copy of the License at 19 | # 20 | # http://www.apache.org/licenses/LICENSE-2.0 21 | # 22 | # Unless required by applicable law or agreed to in writing, software 23 | # distributed under the License is distributed on an "AS IS" BASIS, 24 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25 | # See the License for the specific language governing permissions and 26 | # limitations under the License. 27 | import logging 28 | import threading 29 | import sys 30 | 31 | from ebcli.bundled.asciimatics.screen import Screen 32 | 33 | if not sys.platform.startswith('win32'): 34 | import curses 35 | 36 | 37 | logger = logging.getLogger(__name__) 38 | original_refresh_method = Screen.refresh 39 | 40 | 41 | class ScreenPatch(object): 42 | """ 43 | Class acts as a proxy for asciimatics.screen.Screen to help override methods defined within it 44 | for the fastest rendering experience possible 45 | """ 46 | class refresh_lock(object): 47 | _LOCK = threading.Lock() 48 | 49 | def __enter__(self): 50 | self._LOCK.acquire() 51 | 52 | def __exit__(self, a, b, c): 53 | self._LOCK.release() 54 | 55 | def refresh(self): 56 | with ScreenPatch.refresh_lock(): 57 | original_refresh_method(self) 58 | 59 | 60 | def apply(): 61 | if not sys.platform.startswith('win32'): 62 | def noop(_): 63 | pass 64 | curses.mousemask = noop 65 | 66 | Screen.refresh = ScreenPatch.refresh 67 | -------------------------------------------------------------------------------- /ebcli/bundled/asciimatics/utilities.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Peter Brittain 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | """ 15 | This module is just a collection of simple helper functions. 16 | """ 17 | from datetime import date, datetime 18 | 19 | 20 | def readable_mem(mem): 21 | """ 22 | :param mem: An integer number of bytes to convert to human-readable form. 23 | :return: A human-readable string representation of the number. 24 | """ 25 | for suffix in ["", "K", "M", "G", "T"]: 26 | if mem < 10000: 27 | return "{}{}".format(int(mem), suffix) 28 | mem /= 1024 29 | return "{}P".format(int(mem)) 30 | 31 | 32 | def readable_timestamp(stamp): 33 | """ 34 | :param stamp: A floating point number representing the POSIX file timestamp. 35 | :return: A short human-readable string representation of the timestamp. 36 | """ 37 | if date.fromtimestamp(stamp) == date.today(): 38 | return str(datetime.fromtimestamp(stamp).strftime("%I:%M:%S%p")) 39 | else: 40 | return str(date.fromtimestamp(stamp)) 41 | 42 | 43 | class _DotDict(dict): 44 | """ 45 | Modified dictionary to allow dot notation access. 46 | 47 | This can be used for quick and easy structures. See https://stackoverflow.com/q/2352181/4994021 48 | """ 49 | 50 | __getattr__ = dict.get 51 | __setattr__ = dict.__setitem__ 52 | __delattr__ = dict.__delitem__ 53 | -------------------------------------------------------------------------------- /ebcli/containers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/containers/compat.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import os 14 | import re 15 | import sys 16 | from semantic_version import Version 17 | 18 | from cement.utils.misc import minimal_logger 19 | 20 | from ebcli.containers import commands 21 | from ebcli.core import fileoperations 22 | from ebcli.lib import heuristics, utils 23 | from ebcli.resources.strings import strings 24 | from ebcli.objects.exceptions import CommandError 25 | 26 | 27 | LOG = minimal_logger(__name__) 28 | SUPPORTED_DOCKER_V = '1.6.0' 29 | SUPPORTED_BOOT2DOCKER_V = '1.6.0' 30 | LOCALHOST = '127.0.0.1' 31 | EXPORT = 'export' 32 | BOOT2DOCKER_RUNNING = 'running' 33 | DOCKER_HOST = 'DOCKER_HOST' 34 | DOCKER_CERT_PATH = 'DOCKER_CERT_PATH' 35 | DOCKER_TLS_VERIFY = 'DOCKER_TLS_VERIFY' 36 | 37 | 38 | def container_ip(): 39 | """ 40 | Return the ip address that local containers are or will be running on. 41 | :return str 42 | """ 43 | return LOCALHOST 44 | 45 | 46 | def is_windows(): 47 | return 'win32' in str(sys.platform).lower() 48 | 49 | 50 | def remove_leading_zeros_from_version(version_string): 51 | # regex explaination: remove zeroes if both: 52 | # 1. the start of string (major version) or following a '.' 53 | # 2. followed by some other digit 54 | return re.sub(r'((?<=\.)|^)[0]+(?=\d+)', r'', version_string) 55 | -------------------------------------------------------------------------------- /ebcli/containers/containerfiles/container_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "preconfigured_containers":[ 3 | { 4 | "version":"GlassFish 5.0 Java 8 (Preconfigured - Docker)", 5 | "platform_name": "Preconfigured Docker - GlassFish 5.0 with Java 8 running on 64bit Amazon Linux", 6 | "runtime_image":"amazon/aws-eb-glassfish:5.0-al-onbuild-2.11.1", 7 | "runtime_dockerfile":"glassfish-runtime-5.0-al", 8 | "runtime_default_log":"/usr/local/glassfish5/glassfish/domains/domain1/logs" 9 | }, 10 | { 11 | "version":"Python 3.4 (Preconfigured - Docker)", 12 | "platform_name": "Preconfigured Docker - Python 3.4 running on 64bit Debian", 13 | "runtime_image":"amazon/aws-eb-python:3.4.2-onbuild-3.5.1", 14 | "runtime_dockerfile":"python3-runtime", 15 | "runtime_default_log":"/var/log/uwsgi" 16 | }, 17 | { 18 | "version":"Go 1.4 (Preconfigured - Docker)", 19 | "platform_name": "Preconfigured Docker - Go 1.4 running on 64bit Debian", 20 | "runtime_image":"golang:1.4.2-onbuild", 21 | "runtime_dockerfile":"golang-runtime-1.4", 22 | "runtime_default_log":"/var/log" 23 | }, 24 | { 25 | "version":"Go 1.3 (Preconfigured - Docker)", 26 | "platform_name": "Preconfigured Docker - Go 1.3 running on 64bit Debian", 27 | "runtime_image":"golang:1.3.3-onbuild", 28 | "runtime_dockerfile":"golang-runtime-1.3", 29 | "runtime_default_log":"/var/log" 30 | } 31 | ], 32 | "generic_containers":{ 33 | "platform":"Docker" 34 | }, 35 | "multi_containers":{ 36 | "platform":"Multi-container Docker" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ebcli/containers/containerfiles/glassfish-runtime-4.0-jdk7: -------------------------------------------------------------------------------- 1 | FROM amazon/aws-eb-glassfish:4.0-jdk7-onbuild-3.5.1 2 | EXPOSE 8080 3 | -------------------------------------------------------------------------------- /ebcli/containers/containerfiles/glassfish-runtime-4.1-jdk8: -------------------------------------------------------------------------------- 1 | FROM amazon/aws-eb-glassfish:4.1-jdk8-onbuild-3.5.1 2 | EXPOSE 8080 3 | -------------------------------------------------------------------------------- /ebcli/containers/containerfiles/glassfish-runtime-5.0-al: -------------------------------------------------------------------------------- 1 | FROM amazon/aws-eb-glassfish:5.0-al-onbuild-2.11.1 2 | EXPOSE 8080 3 | -------------------------------------------------------------------------------- /ebcli/containers/containerfiles/golang-runtime-1.3: -------------------------------------------------------------------------------- 1 | FROM golang:1.3.3-onbuild 2 | ENV PORT 3000 3 | EXPOSE 3000 4 | -------------------------------------------------------------------------------- /ebcli/containers/containerfiles/golang-runtime-1.4: -------------------------------------------------------------------------------- 1 | FROM golang:1.4.2-onbuild 2 | ENV PORT 3000 3 | EXPOSE 3000 4 | -------------------------------------------------------------------------------- /ebcli/containers/containerfiles/python3-runtime: -------------------------------------------------------------------------------- 1 | FROM amazon/aws-eb-python:3.4.2-onbuild-3.5.1 2 | EXPOSE 8080 3 | -------------------------------------------------------------------------------- /ebcli/containers/envvarcollector.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from botocore.compat import six 14 | 15 | from ebcli.lib import utils 16 | from ebcli.operations import envvarops 17 | 18 | 19 | class EnvvarCollector(object): 20 | """ 21 | Immutable class for grouping environment variables to add and remove. 22 | """ 23 | 24 | def __init__(self, envvars_map=None, envvars_to_remove=None): 25 | """ 26 | Constructor for EnvvarCollector 27 | :param envvars_map: dict: contains envvars to add 28 | :param envvars_to_remove: set: keys of environment variables to remove 29 | """ 30 | 31 | self.map = envvars_map or {} 32 | self.to_remove = envvars_to_remove or set() 33 | 34 | @classmethod 35 | def from_list(cls, envvars_list): 36 | if not envvars_list: 37 | return cls() 38 | envvars_map, envvars_to_remove = envvarops.create_environment_variables_list( 39 | envvars_list, as_option_settings=False) 40 | return cls(envvars_map, envvars_to_remove) 41 | 42 | @classmethod 43 | def from_str(cls, envvars_str): 44 | if not envvars_str: 45 | return cls() 46 | envvars = envvars_str.split(',') 47 | envvars_map, envvars_to_remove = envvarops.create_environment_variables_list( 48 | envvars, as_option_settings=False) 49 | return cls(envvars_map, envvars_to_remove) 50 | 51 | def filtered(self): 52 | """ 53 | Return new Envvarcollector with all environment variables in self.map that 54 | are not in to_remove 55 | :return EnvvarCollector 56 | """ 57 | 58 | filtered_envvars = {k: v for k, v in six.iteritems(self.map) if k not in 59 | self.to_remove} 60 | return EnvvarCollector(filtered_envvars) 61 | 62 | def merge(self, higher_priority_env): 63 | """ 64 | Merge self with higher_priority_env. 65 | :param higher_priority_env: EnvvarCollector: environment to merge with 66 | :return EnvvarCollector 67 | """ 68 | 69 | envvars_map = utils.merge_dicts(low_priority=self.map, 70 | high_priority=higher_priority_env.map) 71 | to_remove = self.to_remove | higher_priority_env.to_remove 72 | 73 | return EnvvarCollector(envvars_map, to_remove) 74 | -------------------------------------------------------------------------------- /ebcli/containers/generic_container.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.containers import dockerrun 15 | from ebcli.containers.abstractcontainer import AbstractContainer 16 | from ebcli.objects.exceptions import NotFoundError 17 | from ebcli.resources.strings import strings 18 | 19 | 20 | class GenericContainer(AbstractContainer): 21 | """ 22 | Immutable class used for running Generic Docker containers. 23 | """ 24 | 25 | def validate(self): 26 | if ( 27 | not self.pathconfig.dockerfile_exists() 28 | and not self.pathconfig.dockerrun_exists() 29 | ): 30 | raise NotFoundError(strings['local.filenotfound']) 31 | dockerrun.validate_dockerrun_v1( 32 | self.fs_handler.dockerrun, 33 | not self.pathconfig.dockerfile_exists() 34 | ) 35 | 36 | # This gets called if user only provides Dockerrun.aws.json and not Dockerfile 37 | def _containerize(self): 38 | self.fs_handler.make_dockerfile() 39 | -------------------------------------------------------------------------------- /ebcli/containers/pathconfig.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.core import fileoperations 14 | 15 | 16 | class PathConfig(object): 17 | COMPOSE_FILENAME = 'docker-compose.yml' 18 | DOCKERCFG_FILENAME = '.dockercfg' 19 | DOCKERIGNORE_FILENAME = '.dockerignore' 20 | DOCKERFILE_FILENAME = 'Dockerfile' 21 | DOCKERRUN_FILENAME = 'Dockerrun.aws.json' 22 | LOCAL_STATE_FILENAME = '.localstate' 23 | NEW_DOCKERFILE_FILENAME = 'Dockerfile.local' 24 | ROOT_LOCAL_LOGS_DIRNAME = 'local' 25 | 26 | @staticmethod 27 | def docker_proj_path(): 28 | return fileoperations.get_project_root() 29 | 30 | @classmethod 31 | def dockerfile_path(cls): 32 | return fileoperations.project_file_path(cls.DOCKERFILE_FILENAME) 33 | 34 | @classmethod 35 | def new_dockerfile_path(cls): 36 | return fileoperations.get_eb_file_full_location(cls.NEW_DOCKERFILE_FILENAME) 37 | 38 | @classmethod 39 | def dockerignore_path(cls): 40 | return fileoperations.project_file_path(cls.DOCKERIGNORE_FILENAME) 41 | 42 | @classmethod 43 | def logdir_path(cls): 44 | return fileoperations.get_logs_location(cls.ROOT_LOCAL_LOGS_DIRNAME) 45 | 46 | @classmethod 47 | def dockerrun_path(cls): 48 | return fileoperations.project_file_path(cls.DOCKERRUN_FILENAME) 49 | 50 | @classmethod 51 | def compose_path(cls): 52 | return fileoperations.get_eb_file_full_location(cls.COMPOSE_FILENAME) 53 | 54 | @classmethod 55 | def local_state_path(cls): 56 | return fileoperations.get_eb_file_full_location(cls.LOCAL_STATE_FILENAME) 57 | 58 | @classmethod 59 | def dockerfile_exists(cls): 60 | return fileoperations.project_file_exists(cls.DOCKERFILE_FILENAME) 61 | 62 | @classmethod 63 | def dockerrun_exists(cls): 64 | return fileoperations.project_file_exists(cls.DOCKERRUN_FILENAME) 65 | -------------------------------------------------------------------------------- /ebcli/containers/utils.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | def is_docker_compose_installed(): 4 | try: 5 | subprocess.run(['docker','compose','version'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 6 | return True 7 | except subprocess.CalledProcessError: 8 | return False 9 | -------------------------------------------------------------------------------- /ebcli/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/controllers/abort.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings, prompts 16 | from ebcli.objects.exceptions import NotFoundError 17 | from ebcli.core import io 18 | from ebcli.lib import utils 19 | from ebcli.operations import abortops 20 | 21 | 22 | class AbortController(AbstractBaseController): 23 | class Meta: 24 | label = 'abort' 25 | description = strings['abort.info'] 26 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 27 | 28 | def do_command(self): 29 | app_name = self.get_app_name() 30 | env_name = self.get_env_name(noerror=True) 31 | provided_env_name = bool(self.app.pargs.environment_name) 32 | 33 | if not provided_env_name: 34 | envs = abortops.get_abortable_envs(app_name) 35 | if len(envs) < 1: 36 | raise NotFoundError(strings['abort.noabortableenvs']) 37 | if len(envs) == 1: 38 | env_name = envs[0].name 39 | else: 40 | io.echo() 41 | io.echo(prompts['abort.envprompt']) 42 | env_name = utils.prompt_for_item_in_list(envs).name 43 | else: 44 | pass 45 | 46 | abortops.abort_operation(env_name) 47 | -------------------------------------------------------------------------------- /ebcli/controllers/codesource.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.lib import utils 14 | from ebcli.core import io 15 | 16 | from ebcli.core.abstractcontroller import AbstractBaseController 17 | from ebcli.resources.strings import strings, flag_text, prompts 18 | from ebcli.operations import gitops 19 | 20 | 21 | class CodeSourceController(AbstractBaseController): 22 | class Meta(AbstractBaseController.Meta): 23 | label = 'codesource' 24 | description = strings['codesource.info'] 25 | arguments = [ 26 | ( 27 | ['sourcename'], 28 | dict( 29 | action='store', 30 | nargs='?', 31 | help=flag_text['codesource.sourcename'], 32 | choices=['codecommit', 'local'], 33 | type=str.lower 34 | ) 35 | ), 36 | ] 37 | usage = 'eb codesource [options ...]' 38 | 39 | def do_command(self): 40 | sourcename = self.app.pargs.sourcename 41 | if sourcename is not None: 42 | if sourcename == 'local': 43 | gitops.print_current_codecommit_settings() 44 | self.set_local() 45 | if sourcename == 'codecommit': 46 | self.set_codecommit() 47 | else: 48 | self.prompt_for_codesource() 49 | 50 | def prompt_for_codesource(self): 51 | gitops.print_current_codecommit_settings() 52 | io.echo(prompts['codesource.codesourceprompt']) 53 | setup_choices = ['CodeCommit', 'Local'] 54 | choice = utils.prompt_for_item_in_list(setup_choices, 2) 55 | if choice == setup_choices[0]: 56 | self.set_codecommit() 57 | elif choice == setup_choices[1]: 58 | self.set_local() 59 | 60 | def set_local(self): 61 | gitops.disable_codecommit() 62 | io.echo(strings['codesource.localmsg']) 63 | 64 | def set_codecommit(self): 65 | gitops.initialize_codecommit() 66 | -------------------------------------------------------------------------------- /ebcli/controllers/console.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings 16 | from ebcli.operations import consoleops 17 | 18 | 19 | class ConsoleController(AbstractBaseController): 20 | class Meta: 21 | label = 'console' 22 | description = strings['console.info'] 23 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 24 | 25 | def do_command(self): 26 | app_name = self.get_app_name() 27 | env_name = self.get_env_name(noerror=True) 28 | 29 | consoleops.open_console(app_name, env_name) 30 | -------------------------------------------------------------------------------- /ebcli/controllers/events.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings, flag_text 16 | from ebcli.operations import eventsops 17 | 18 | 19 | class EventsController(AbstractBaseController): 20 | class Meta: 21 | label = 'events' 22 | description = strings['events.info'] 23 | arguments = AbstractBaseController.Meta.arguments + [ 24 | (['-f', '--follow'], dict( 25 | action='store_true', help=flag_text['events.follow'])) 26 | ] 27 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 28 | 29 | def do_command(self): 30 | app_name = self.get_app_name() 31 | env_name = self.get_env_name() 32 | follow = self.app.pargs.follow 33 | 34 | eventsops.print_events(app_name, env_name, follow) 35 | -------------------------------------------------------------------------------- /ebcli/controllers/health.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.core.abstractcontroller import AbstractBaseController 14 | from ebcli.resources.strings import strings 15 | from ebcli.operations import healthops 16 | 17 | 18 | class HealthController(AbstractBaseController): 19 | class Meta: 20 | label = 'health' 21 | description = strings['health.info'] 22 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 23 | arguments = AbstractBaseController.Meta.arguments + [ 24 | (['--refresh'], dict(action='store_true', help='refresh')), 25 | (['--mono'], dict(action='store_true', help='no color')), 26 | ( 27 | ['--view'], dict( 28 | default='split', 29 | choices=['split', 'status', 'request', 'cpu'] 30 | ) 31 | ) 32 | ] 33 | 34 | def do_command(self): 35 | app_name = self.get_app_name() 36 | env_name = self.get_env_name() 37 | refresh = self.app.pargs.refresh 38 | mono = self.app.pargs.mono 39 | view = self.app.pargs.view 40 | 41 | healthops.display_interactive_health(app_name, env_name, refresh, 42 | mono, view) 43 | -------------------------------------------------------------------------------- /ebcli/controllers/lifecycle.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings, flag_text 16 | from ebcli.operations import lifecycleops 17 | 18 | 19 | class LifecycleController(AbstractBaseController): 20 | class Meta(AbstractBaseController.Meta): 21 | label = 'lifecycle' 22 | stacked_on = 'appversion' 23 | stacked_type = 'nested' 24 | description = strings['lifecycle.info'] 25 | arguments = AbstractBaseController.Meta.arguments + [ 26 | (['-p', '--print'], dict(action='store_true', help=flag_text['lifecycle.print'])), 27 | ] 28 | usage = 'eb appversion lifecycle [options ...]' 29 | epilog = strings['lifecycle.epilog'] 30 | 31 | def do_command(self): 32 | app_name = self.get_app_name() 33 | print_policy = getattr(self.app.pargs, 'print') 34 | 35 | if print_policy: 36 | lifecycleops.print_lifecycle_policy(app_name) 37 | return 38 | 39 | lifecycleops.interactive_update_lifcycle_policy(app_name) 40 | -------------------------------------------------------------------------------- /ebcli/controllers/list.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings, flag_text 16 | from ebcli.operations import listops 17 | 18 | 19 | class ListController(AbstractBaseController): 20 | class Meta: 21 | label = 'list' 22 | description = strings['list.info'] 23 | usage = 'eb list [options ...]' 24 | arguments = [ 25 | (['-a', '--all'], dict(action='store_true', 26 | help=flag_text['list.all'])) 27 | ] 28 | 29 | def do_command(self): 30 | all_apps = self.app.pargs.all 31 | if not all_apps: 32 | app_name = self.get_app_name() 33 | else: 34 | app_name = None 35 | verbose = self.app.pargs.verbose 36 | 37 | listops.list_env_names(app_name, verbose, all_apps) 38 | -------------------------------------------------------------------------------- /ebcli/controllers/migrate_scripts/add_virtual_dir_read_access.ps1: -------------------------------------------------------------------------------- 1 | . "$PSScriptRoot\\ebdeploy_utils.ps1" 2 | 3 | $paths = @( 4 | # This will be populated dynamically with physical paths 5 | ) 6 | foreach ($path in $paths) { 7 | if (-not (Test-Path $path)) { 8 | Write-HostWithTimestamp "'$path' for virtual directory does not exist. Creating." 9 | New-Item -Path $path -ItemType Directory -Force | Out-Null 10 | } 11 | 12 | $acl = Get-Acl $path 13 | foreach ($rule in $(Get-GenericWebpathACLRules)) { 14 | $acl.AddAccessRule($rule) 15 | } 16 | Set-Acl $path $acl 17 | 18 | Write-HostWithTimestamp "Read permission granted for $path" 19 | } 20 | -------------------------------------------------------------------------------- /ebcli/controllers/migrate_scripts/default_web_site_port_reassignment_template.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Reassigns the Default Web Site's port 80 binding to a specified configuration. 4 | 5 | .DESCRIPTION 6 | PowerShell script that modifies the Default Web Site's port binding from 7 | port 80 to a specified port configuration. Includes site restart and 8 | logging functionality. 9 | 10 | .NOTES 11 | Requires: 12 | - WebAdministration module 13 | - Administrative privileges 14 | - ebdeploy_utils.ps1 in same directory 15 | #> 16 | 17 | . "$PSScriptRoot\\ebdeploy_utils.ps1" 18 | 19 | if (-not [Environment]::Is64BitProcess) { 20 | Write-HostWithTimestamp "Restarting in 64-bit PowerShell" 21 | $scriptPath = $MyInvocation.MyCommand.Path 22 | $args = "-ExecutionPolicy unrestricted -NonInteractive -NoProfile -File `"$scriptPath`"" 23 | Start-Process "$env:windir\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe" -ArgumentList $args -Wait -NoNewWindow 24 | exit 25 | } 26 | 27 | Import-Module WebAdministration 28 | 29 | function Reassign-DefaultWebSitePort { 30 | <# 31 | .SYNOPSIS 32 | Updates Default Web Site bindings and restarts the site. 33 | 34 | .DESCRIPTION 35 | Locates the port 80 binding of Default Web Site and updates it to 36 | the specified binding configuration. Restarts the website to apply changes. 37 | 38 | .OUTPUTS 39 | Logs binding configuration before and after changes. 40 | 41 | .NOTES 42 | - Exits silently if no port 80 binding exists 43 | - Restarts website as current user 44 | - Requires WebAdministration module 45 | #> 46 | $site = Get-Item "IIS:\\Sites\\Default Web Site" 47 | $bindings = $site.Bindings.Collection 48 | 49 | $bindingToUpdate = $bindings | Where-Object { 50 | $_.protocol -eq "http" -and 51 | $_.bindingInformation -eq "*:80:" 52 | } 53 | if (-not $bindingToUpdate) { 54 | Write-HostWithTimestamp "Site, 'Default Web Site', is already running on a non-80 port:" 55 | Get-WebBinding -Name 'Default Web Site' 56 | return 57 | } 58 | $bindingToUpdate.bindingInformation = "{host}:{port}:{domain}" 59 | 60 | Set-ItemProperty 'IIS:\\Sites\\Default Web Site' -Name bindings -Value $bindings 61 | 62 | $username = [Environment]::UserName 63 | Write-HostWithTimestamp "Restarting Site, 'Default Web Site', as $username for new bindings to take effect." 64 | Stop-Website -Name 'Default Web Site' 65 | Start-Website -Name 'Default Web Site' 66 | Write-HostWithTimestamp "Site, 'Default Web Site', has been reassigned to run with the following bindings:" 67 | Get-WebBinding -Name 'Default Web Site' 68 | } 69 | 70 | Reassign-DefaultWebSitePort 71 | -------------------------------------------------------------------------------- /ebcli/controllers/migrate_scripts/modify_firewall_config.ps1: -------------------------------------------------------------------------------- 1 | # This script executes PowerShell commands on a remote machine to 2 | # configure the firewall based on configuration of a source machine 3 | 4 | . "$PSScriptRoot\\ebdeploy_utils.ps1" 5 | 6 | if (-not [Environment]::Is64BitProcess) { 7 | $utcNow = Get-Date -Format "yyyy-MM-dd HH:mm:ss" 8 | Write-HostWithTimestamp "[$($utcNow)] Restarting in 64-bit PowerShell" 9 | $scriptPath = $MyInvocation.MyCommand.Path 10 | $args = "-ExecutionPolicy unrestricted -NonInteractive -NoProfile -File `"$scriptPath`"" 11 | Start-Process "$env:windir\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe" -ArgumentList $args -Wait -NoNewWindow 12 | exit 13 | } 14 | 15 | {firewall_rules} 16 | -------------------------------------------------------------------------------- /ebcli/controllers/migrate_scripts/noop.ps1: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ebcli/controllers/migrate_scripts/reinstate_iisstart_htm_default_document.ps1: -------------------------------------------------------------------------------- 1 | # This script ensures that iisstart.htm is reinstated as a DefaultDocument 2 | 3 | . "$PSScriptRoot\\ebdeploy_utils.ps1" 4 | 5 | if (-not [Environment]::Is64BitProcess) { 6 | Write-HostWithTimestamp "Restarting in 64-bit PowerShell" 7 | $scriptPath = $MyInvocation.MyCommand.Path 8 | $args = "-ExecutionPolicy unrestricted -NonInteractive -NoProfile -File `"$scriptPath`"" 9 | Start-Process "$env:windir\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe" -ArgumentList $args -Wait -NoNewWindow 10 | exit 11 | } 12 | 13 | # Check if iisstart.htm is already in the default document list 14 | $existingEntry = Get-WebConfigurationProperty -Filter "system.webServer/defaultDocument/files/add[@value='iisstart.htm']" -Name "." -ErrorAction SilentlyContinue 15 | 16 | # Only add if it doesn't already exist 17 | if ($existingEntry -eq $null) { 18 | Add-WebConfigurationProperty -Filter "system.webServer/defaultDocument/files" -Name "." -Value @{value='iisstart.htm'} 19 | Write-HostWithTimestamp "Added iisstart.htm to default documents" 20 | } else { 21 | Write-HostWithTimestamp "iisstart.htm is already in default documents, skipping" 22 | } -------------------------------------------------------------------------------- /ebcli/controllers/migrate_scripts/site_removal_template.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Removes a specified IIS website during Elastic Beanstalk uninstallation. 4 | 5 | .DESCRIPTION 6 | PowerShell script that safely stops and removes a specified IIS website. 7 | Includes error handling and detailed logging of the removal process. 8 | 9 | .NOTES 10 | Requires: 11 | - WebAdministration module 12 | - Administrative privileges 13 | - ebdeploy_utils.ps1 in same directory 14 | 15 | .OUTPUTS 16 | Logs the removal process with timestamps: 17 | - Site stop operation 18 | - Site removal operation 19 | - Any errors encountered during the process 20 | #> 21 | 22 | . "$PSScriptRoot\\ebdeploy_utils.ps1" 23 | 24 | if (-not [Environment]::Is64BitProcess) { 25 | Write-HostWithTimestamp "Restarting in 64-bit PowerShell" 26 | $scriptPath = $MyInvocation.MyCommand.Path 27 | $args = "-ExecutionPolicy unrestricted -NonInteractive -NoProfile -File `"$scriptPath`"" 28 | Start-Process "$env:windir\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe" -ArgumentList $args -Wait -NoNewWindow 29 | exit 30 | } 31 | 32 | Import-Module WebAdministration 33 | 34 | $websiteName = "{site_name}" 35 | 36 | try { 37 | Write-HostWithTimestamp "Stopping IIS site, $websiteName." 38 | Stop-Website -Name $websiteName 39 | Write-HostWithTimestamp "Successfully stopped IIS site, $websiteName." 40 | Write-HostWithTimestamp "Removing IIS site $websiteName from IIS server." 41 | Remove-Website -Name $websiteName 42 | Write-HostWithTimestamp "Successfully removed site $websiteName from IIS server." 43 | } catch { 44 | Write-ErrorWithTimestamp "Could not remove IIS site ${websiteName}: $_" 45 | throw $_ 46 | } 47 | -------------------------------------------------------------------------------- /ebcli/controllers/migrate_scripts/site_restart_template.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Restarts a specified IIS website during Elastic Beanstalk deployment. 4 | 5 | .DESCRIPTION 6 | PowerShell script that safely stops and starts a specified IIS website. 7 | Includes checks for site existence and detailed logging of the restart process. 8 | 9 | .NOTES 10 | Requires: 11 | - WebAdministration module 12 | - Administrative privileges 13 | - ebdeploy_utils.ps1 in same directory 14 | 15 | .OUTPUTS 16 | Logs the restart process with timestamps, including: 17 | - Site existence verification 18 | - Stop operation 19 | - Start operation 20 | - Cases where site doesn't exist 21 | #> 22 | 23 | . "$PSScriptRoot\\ebdeploy_utils.ps1" 24 | 25 | if (-not [Environment]::Is64BitProcess) { 26 | Write-HostWithTimestamp "Restarting in 64-bit PowerShell" 27 | $scriptPath = $MyInvocation.MyCommand.Path 28 | $args = "-ExecutionPolicy unrestricted -NonInteractive -NoProfile -File `"$scriptPath`"" 29 | Start-Process "$env:windir\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe" -ArgumentList $args -Wait -NoNewWindow 30 | exit 31 | } 32 | 33 | Import-Module WebAdministration 34 | 35 | $websiteName = "{site_name}" 36 | 37 | if (Get-Website -Name $websiteName) { 38 | Write-HostWithTimestamp "Restarting IIS site, $websiteName." 39 | Write-HostWithTimestamp "Stopping ..." 40 | Stop-Website -Name $websiteName 41 | Write-HostWithTimestamp "Starting ..." 42 | Start-Website -Name $websiteName 43 | } 44 | else { 45 | Write-HostWithTimestamp "Website IIS site, $websiteName, doesn't exist. Nothing to restart." 46 | } 47 | -------------------------------------------------------------------------------- /ebcli/controllers/migrate_scripts/windows_proxy_feature_enabler.ps1: -------------------------------------------------------------------------------- 1 | # This script imports Automatic Request Routing (ARR) config from arr_*.xml 2 | # files, if found, exported by some source machine. This script will also 3 | # ensure that the ARR and Rewrite modules are installed from well-known 4 | # locations. 5 | 6 | . "$PSScriptRoot\\ebdeploy_utils.ps1" 7 | 8 | if (-not [Environment]::Is64BitProcess) { 9 | Write-HostWithTimestamp "Restarting in 64-bit PowerShell" 10 | $scriptPath = $MyInvocation.MyCommand.Path 11 | $args = "-ExecutionPolicy unrestricted -NonInteractive -NoProfile -File `"$scriptPath`"" 12 | Start-Process "$env:windir\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe" -ArgumentList $args -Wait -NoNewWindow 13 | exit 14 | } 15 | 16 | Import-Module WebAdministration 17 | 18 | Write-HostWithTimestamp "Installing Web-Application-Proxy Windows feature. This may take a few minutes." 19 | Install-WindowsFeature Web-Application-Proxy 20 | Write-HostWithTimestamp "Successfully installed Web-Application-Proxy" 21 | -------------------------------------------------------------------------------- /ebcli/controllers/open.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings 16 | from ebcli.operations import openops 17 | 18 | 19 | class OpenController(AbstractBaseController): 20 | class Meta: 21 | label = 'open' 22 | description = strings['open.info'] 23 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 24 | 25 | def do_command(self): 26 | app_name = self.get_app_name() 27 | env_name = self.get_env_name() 28 | 29 | openops.open_app(app_name, env_name) 30 | -------------------------------------------------------------------------------- /ebcli/controllers/platform/events.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.core.abstractcontroller import AbstractBaseController 14 | from ebcli.operations.platformops import show_platform_events 15 | from ebcli.resources.strings import strings, flag_text 16 | 17 | 18 | class GenericPlatformEventsController(AbstractBaseController): 19 | class Meta: 20 | is_platform_workspace_only_command = True 21 | requires_directory_initialization = True 22 | description = strings['platformevents.info'] 23 | arguments = [ 24 | ( 25 | ['version'], 26 | dict( 27 | action='store', 28 | nargs='?', 29 | default=None, 30 | help=flag_text['platformevents.version'] 31 | ) 32 | ), 33 | ( 34 | ['-f', '--follow'], 35 | dict( 36 | action='store_true', 37 | help=flag_text['events.follow'] 38 | ) 39 | ) 40 | ] 41 | 42 | @classmethod 43 | def clone(cls): 44 | return type('Meta', cls.__bases__, dict(cls.__dict__)) 45 | 46 | @classmethod 47 | def add_to_handler(cls, handler): 48 | handler.register(cls) 49 | 50 | def do_command(self): 51 | version = self.app.pargs.version 52 | follow = self.app.pargs.follow 53 | 54 | show_platform_events(follow, version) 55 | 56 | 57 | class PlatformEventsController(GenericPlatformEventsController): 58 | Meta = GenericPlatformEventsController.Meta.clone() 59 | Meta.label = 'platform events' 60 | Meta.aliases = ['events'] 61 | Meta.aliases_only = True 62 | Meta.stacked_on = 'platform' 63 | Meta.stacked_type = 'nested' 64 | Meta.usage = 'eb platform events [options...]' 65 | 66 | 67 | class EBPEventsController(GenericPlatformEventsController): 68 | Meta = GenericPlatformEventsController.Meta.clone() 69 | Meta.label = 'events' 70 | Meta.usage = 'ebp events [options...]' 71 | -------------------------------------------------------------------------------- /ebcli/controllers/printenv.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings 16 | from ebcli.operations import envvarops 17 | 18 | 19 | class PrintEnvController(AbstractBaseController): 20 | class Meta: 21 | label = 'printenv' 22 | description = strings['printenv.info'] 23 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 24 | 25 | def do_command(self): 26 | app_name = self.get_app_name() 27 | env_name = self.get_env_name() 28 | 29 | envvarops.get_and_print_environment_vars(app_name, env_name) 30 | -------------------------------------------------------------------------------- /ebcli/controllers/restore.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.core.abstractcontroller import AbstractBaseController 14 | from ebcli.operations import restoreops 15 | from ebcli.resources.strings import strings, flag_text 16 | 17 | 18 | class RestoreController(AbstractBaseController): 19 | class Meta(AbstractBaseController.Meta): 20 | label = 'restore' 21 | description = strings['restore.info'] 22 | arguments = [ 23 | ( 24 | ['environment_id'], 25 | dict( 26 | action='store', 27 | nargs='?', 28 | default=[], 29 | help=flag_text['restore.env'] 30 | ) 31 | ), 32 | (['--timeout'], dict(type=int, help=flag_text['general.timeout'])), 33 | ] 34 | usage = AbstractBaseController.Meta.usage.replace( 35 | '{cmd}', 36 | label 37 | ).replace( 38 | 'environment_name', 39 | 'environment_id' 40 | ) 41 | 42 | def do_command(self): 43 | self.env_id = self.app.pargs.environment_id 44 | self.timeout = self.app.pargs.timeout 45 | 46 | if self.env_id: 47 | restoreops.restore(self.env_id, self.timeout) 48 | else: 49 | self.interactive_restore_environment() 50 | 51 | def interactive_restore_environment(self): 52 | """ 53 | Interactive mode which allows user to see previous 54 | environments and allow a choice to restore one. 55 | Run when the user supplies no arguments. 56 | """ 57 | environments = restoreops.get_restorable_envs(self.get_app_name()) 58 | restoreops.display_environments(environments) 59 | -------------------------------------------------------------------------------- /ebcli/controllers/scale.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings, flag_text 16 | from ebcli.core import fileoperations, io 17 | from ebcli.lib import elasticbeanstalk 18 | from ebcli.operations import scaleops 19 | 20 | 21 | class ScaleController(AbstractBaseController): 22 | class Meta: 23 | label = 'scale' 24 | description = strings['scale.info'] 25 | arguments = [ 26 | (['number'], dict( 27 | action='store', type=int, help=flag_text['scale.number'])), 28 | (['-f', '--force'], dict( 29 | action='store_true', help=flag_text['scale.force'])), 30 | (['--timeout'], dict(type=int, help=flag_text['general.timeout'])), 31 | ] + AbstractBaseController.Meta.arguments 32 | usage = 'eb scale {number} [options ...]' 33 | 34 | def do_command(self): 35 | app_name = self.get_app_name() 36 | number = self.app.pargs.number 37 | timeout = self.app.pargs.timeout 38 | env_name = self.get_env_name(cmd_example='scale ' + str(number)) 39 | confirm = self.app.pargs.force 40 | 41 | scaleops.scale(app_name, env_name, number, confirm, timeout=timeout) 42 | -------------------------------------------------------------------------------- /ebcli/controllers/setenv.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.core.abstractcontroller import AbstractBaseController 14 | from ebcli.resources.strings import strings, flag_text 15 | from ebcli.core import fileoperations, io 16 | from ebcli.lib import elasticbeanstalk 17 | from ebcli.operations import envvarops 18 | 19 | 20 | class SetEnvController(AbstractBaseController): 21 | class Meta: 22 | label = 'setenv' 23 | description = strings['setenv.info'] 24 | usage = 'eb setenv [VAR_NAME=KEY ...] [-e environment] [options ...]' 25 | arguments = [ 26 | ( 27 | ['varKey'], 28 | dict( 29 | action='store', 30 | nargs='+', 31 | default=[], 32 | help=flag_text['setenv.vars'] 33 | ) 34 | ), 35 | ( 36 | ['-e', '--environment'], 37 | dict( 38 | dest='environment_name', 39 | help=flag_text['setenv.env'] 40 | ) 41 | ), 42 | ( 43 | ['--timeout'], 44 | dict( 45 | type=int, 46 | help=flag_text['general.timeout'] 47 | ) 48 | ), 49 | ] 50 | epilog = strings['setenv.epilog'] 51 | 52 | def do_command(self): 53 | app_name = self.get_app_name() 54 | env_name = self.get_env_name() 55 | var_list = self.app.pargs.varKey 56 | timeout = self.app.pargs.timeout 57 | 58 | envvarops.setenv(app_name, env_name, var_list, timeout) 59 | -------------------------------------------------------------------------------- /ebcli/controllers/ssh.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.core.abstractcontroller import AbstractBaseController 14 | from ebcli.resources.strings import strings, flag_text 15 | from ebcli.core import fileoperations, io 16 | from ebcli.lib import elasticbeanstalk 17 | from ebcli.objects.exceptions import InvalidOptionsError 18 | from ebcli.operations import sshops 19 | 20 | 21 | class SSHController(AbstractBaseController): 22 | class Meta: 23 | label = 'ssh' 24 | description = strings['ssh.info'] 25 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 26 | arguments = AbstractBaseController.Meta.arguments + [ 27 | (['-n', '--number'], dict(help=flag_text['ssh.number'], type=int)), 28 | (['-i', '--instance'], dict(help=flag_text['ssh.instance'])), 29 | (['-c', '--command'], dict(help=flag_text['ssh.command'], type=str)), 30 | (['-e', '--custom'], dict(help=flag_text['ssh.custom'], type=str)), 31 | (['-o', '--keep_open'], dict( 32 | action='store_true', help=flag_text['ssh.keepopen'])), 33 | (['--force'], dict( 34 | action='store_true', help=flag_text['ssh.force'])), 35 | (['--setup'], dict( 36 | action='store_true', help=flag_text['ssh.setup'])), 37 | (['--timeout'], dict(type=int, help=flag_text['ssh.timeout'])), 38 | ] 39 | 40 | def do_command(self): 41 | number = self.app.pargs.number 42 | env_name = self.get_env_name() 43 | instance = self.app.pargs.instance 44 | cmd = self.app.pargs.command 45 | custom_ssh = self.app.pargs.custom 46 | keep_open = self.app.pargs.keep_open 47 | force = self.app.pargs.force 48 | setup = self.app.pargs.setup 49 | timeout = self.app.pargs.timeout 50 | 51 | if timeout and not setup: 52 | raise InvalidOptionsError(strings['ssh.timeout_without_setup']) 53 | 54 | sshops.prepare_for_ssh( 55 | env_name=env_name, 56 | instance=instance, 57 | keep_open=keep_open, 58 | force=force, 59 | setup=setup, 60 | number=number, 61 | custom_ssh=custom_ssh, 62 | command=cmd, 63 | timeout=timeout 64 | ) 65 | -------------------------------------------------------------------------------- /ebcli/controllers/status.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.core.abstractcontroller import AbstractBaseController 14 | from ebcli.resources.strings import strings 15 | from ebcli.operations import statusops 16 | 17 | 18 | class StatusController(AbstractBaseController): 19 | class Meta: 20 | label = 'status' 21 | description = strings['status.info'] 22 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 23 | 24 | def do_command(self): 25 | app_name = self.get_app_name() 26 | env_name = self.get_env_name() 27 | 28 | verbose = self.app.pargs.verbose 29 | 30 | statusops.status(app_name, env_name, verbose) 31 | -------------------------------------------------------------------------------- /ebcli/controllers/swap.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings, flag_text, prompts 16 | from ebcli.core import io 17 | from ebcli.objects.exceptions import NotSupportedError 18 | from ebcli.lib import elasticbeanstalk, utils 19 | from ebcli.operations import swapops 20 | 21 | 22 | class SwapController(AbstractBaseController): 23 | class Meta: 24 | label = 'swap' 25 | description = strings['swap.info'] 26 | arguments = [ 27 | (['environment_name'], dict(action='store', nargs='?', 28 | help=flag_text['swap.env'])), 29 | (['-n', '--destination_name'], dict(help=flag_text['swap.name'])), 30 | ] 31 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 32 | 33 | def do_command(self): 34 | app_name = self.get_app_name() 35 | source_env = self.get_env_name() 36 | destination_env = self.app.pargs.destination_name 37 | 38 | if not destination_env: 39 | envs = elasticbeanstalk.get_environment_names(app_name) 40 | if len(envs) < 2: 41 | raise NotSupportedError(strings['swap.unsupported']) 42 | 43 | envs = [e for e in envs if e != source_env] 44 | if len(envs) == 1: 45 | destination_env = envs[0] 46 | else: 47 | io.echo() 48 | io.echo(prompts['swap.envprompt']) 49 | destination_env = utils.prompt_for_item_in_list(envs) 50 | 51 | swapops.cname_swap(source_env, destination_env) 52 | -------------------------------------------------------------------------------- /ebcli/controllers/upgrade.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings, flag_text 16 | from ebcli.operations import upgradeops 17 | 18 | 19 | class UpgradeController(AbstractBaseController): 20 | class Meta: 21 | label = 'upgrade' 22 | description = strings['upgrade.info'] 23 | usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) 24 | arguments = AbstractBaseController.Meta.arguments + [ 25 | (['--timeout'], dict(type=int, help=flag_text['general.timeout'])), 26 | (['--force'], dict( 27 | action='store_true', help=flag_text['scale.force'])), 28 | (['--noroll'], dict( 29 | action='store_true', help=flag_text['upgrade.noroll'])), 30 | ] 31 | 32 | def do_command(self): 33 | app_name = self.get_app_name() 34 | env_name = self.get_env_name() 35 | timeout = self.app.pargs.timeout 36 | confirm = self.app.pargs.force 37 | noroll = self.app.pargs.noroll 38 | 39 | upgradeops.upgrade_env(app_name, env_name, timeout, confirm, noroll) 40 | -------------------------------------------------------------------------------- /ebcli/controllers/use.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from cement.utils.misc import minimal_logger 14 | 15 | from ebcli.lib import utils 16 | from ebcli.objects.exceptions import InvalidOptionsError, NotFoundError 17 | from ebcli.objects.sourcecontrol import SourceControl 18 | from ebcli.core.abstractcontroller import AbstractBaseController 19 | from ebcli.resources.strings import strings, flag_text 20 | from ebcli.operations import useops, gitops 21 | 22 | LOG = minimal_logger(__name__) 23 | 24 | 25 | class UseController(AbstractBaseController): 26 | class Meta: 27 | label = 'use' 28 | description = strings['use.info'] 29 | arguments = [ 30 | ( 31 | ['environment_name'], 32 | dict(action='store', nargs=1, help=flag_text['use.env']) 33 | ), 34 | ( 35 | ['--source'], 36 | dict(help=flag_text['deploy.source']) 37 | ), 38 | ] 39 | usage = 'eb use [environment_name] [options ...]' 40 | 41 | def do_command(self): 42 | source = self.app.pargs.source 43 | env_name = self.app.pargs.environment_name[0] 44 | 45 | useops.switch_default_environment(env_name) 46 | 47 | if source: 48 | self.__attempt_to_checkout_branch_specified_in_source_input(source) 49 | else: 50 | self.__attempt_to_change_branch_to_environment_default() 51 | 52 | @staticmethod 53 | def __attempt_to_change_branch_to_environment_default(): 54 | source_control = SourceControl.get_source_control() 55 | default_branch = gitops.get_branch_default_for_current_environment() 56 | if default_branch: 57 | source_control.checkout_branch(default_branch) 58 | 59 | @staticmethod 60 | def __attempt_to_checkout_branch_specified_in_source_input(source): 61 | source_location, repo, branch = utils.parse_source(source) 62 | if not branch or not repo: 63 | raise InvalidOptionsError(strings['codecommit.bad_source']) 64 | 65 | source_control = SourceControl.get_source_control() 66 | source_control.is_setup() 67 | 68 | repo = repo or gitops.get_default_repository() 69 | 70 | useops.switch_default_repo_and_branch(repo, branch) 71 | successfully_checked_out_branch = source_control.checkout_branch(branch) 72 | 73 | if not successfully_checked_out_branch: 74 | raise NotFoundError("Could not checkout branch {0}.".format(branch)) 75 | -------------------------------------------------------------------------------- /ebcli/core/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/core/ebglobals.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | class Constants: 14 | class WorkSpaceTypes: 15 | APPLICATION = 'Application' 16 | PLATFORM = 'Platform' 17 | 18 | AWS_ELASTIC_BEANSTALK_ACCOUNT = "AWSElasticBeanstalk" 19 | OWNED_BY_SELF = "self" 20 | -------------------------------------------------------------------------------- /ebcli/core/hooks.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import sys 15 | 16 | from cement.ext.ext_logging import LoggingLogHandler 17 | from cement.utils.misc import minimal_logger 18 | 19 | from ebcli import __version__ 20 | from ebcli.core import fileoperations 21 | from ebcli.lib import aws 22 | from ebcli.operations import commonops 23 | 24 | 25 | LOG = minimal_logger(__name__) 26 | 27 | 28 | def pre_run_hook(app): 29 | if app.pargs.verbose: 30 | LoggingLogHandler.set_level(app.log, 'INFO') 31 | 32 | LOG.debug('-- EBCLI Version: {}'.format(__version__)) 33 | LOG.debug('-- Python Version: {}'.format(sys.version)) 34 | 35 | set_profile(app.pargs.profile) 36 | set_region(app.pargs.region) 37 | 38 | set_endpoint(app.pargs.endpoint_url) 39 | set_ssl(app.pargs.no_verify_ssl) 40 | set_debugboto(app.pargs.debugboto) 41 | 42 | 43 | def set_profile(profile): 44 | if profile: 45 | aws.set_profile_override(profile) 46 | else: 47 | profile = commonops.get_default_profile() 48 | if profile: 49 | aws.set_profile(profile) 50 | 51 | 52 | def set_ssl(noverify): 53 | if not noverify: 54 | noverify = fileoperations.get_config_setting( 55 | 'global', 'no-verify-ssl', default=False) 56 | if noverify: 57 | aws.no_verify_ssl() 58 | 59 | 60 | def set_region(region_name): 61 | if not region_name: 62 | region_name = commonops.get_default_region() 63 | 64 | aws.set_region(region_name) 65 | 66 | 67 | def set_endpoint(endpoint_url): 68 | if endpoint_url: 69 | aws.set_endpoint_url(endpoint_url) 70 | 71 | 72 | def set_debugboto(debugboto): 73 | if debugboto: 74 | aws.set_debug() 75 | -------------------------------------------------------------------------------- /ebcli/display/README: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | How to use this package: 16 | 17 | "display" is a package that allows developers to display data in a compact, visually appealing 18 | table. Essentially, a screen takes a table and some data (from a data_poller) and uses the draw method to draw the display. 19 | 20 | See an example of a display by running eb health. 21 | See another example of a display by running eb deploy --version (with no other params) 22 | 23 | In order to create your own display, look at the examples in traditional.py and versions.py. 24 | Then see how to instantiate your screen, data_poller, and table in the file deployops.py, method display_versions 25 | Or you can see in healthops.py, method display_interactive_health 26 | 27 | You can use this template to easily make your static display. 28 | 29 | (To make a dynamic, updating display, look through screen.py and data_poller.py. Check out background polling in data_poller) 30 | -------------------------------------------------------------------------------- /ebcli/display/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/display/help.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | from ebcli.core import io 16 | from ebcli.display.table import Table, Column 17 | from ebcli.display import term 18 | 19 | 20 | class HelpTable(Table): 21 | def __init__(self): 22 | super(HelpTable, self).__init__('help') 23 | self.visible = False 24 | self.columns = [ 25 | Column('Key', 18, 'key', 'none'), 26 | Column('Action', 0, 'action', 'none'), 27 | ] 28 | self.data = [] 29 | self.set_up_help_data_rows() 30 | 31 | def set_data(self, table_data): 32 | pass 33 | 34 | def set_up_help_data_rows(self): 35 | self.set_up_standard_rows() 36 | self.set_up_views() 37 | self.add_help_text(['H'], 'This help menu') 38 | self.add_section('') 39 | 40 | def set_up_standard_rows(self): 41 | self.add_help_text(['up', 'down', 'home', 'end'], 'Scroll vertically') 42 | self.add_help_text(['left', 'right'], 'Scroll horizontally') 43 | self.add_help_text(['F'], 'Freeze/unfreeze data') 44 | self.add_help_text(['X'], 'Replace instance') 45 | self.add_help_text(['B'], 'Reboot instance') 46 | self.add_help_text(['<', '>'], 'Move sort column left/right') 47 | self.add_help_text(['-', '+'], 'Sort order descending/ascending') 48 | self.add_help_text(['P'], 'Save health snapshot data file') 49 | self.add_help_text(['Z'], 'Toggle color/mono mode') 50 | self.add_help_text(['Q'], 'Quit this program') 51 | 52 | def set_up_views(self): 53 | self.add_section('') 54 | self.add_section('Views') 55 | self.add_help_text(['1'], 'All tables/split view') 56 | self.add_help_text(['2'], 'Health status table') 57 | self.add_help_text(['3'], 'Request summary table') 58 | self.add_help_text(['4'], 'CPU%/Load table') 59 | self.add_help_text(['5'], 'Deployment summary table') 60 | 61 | def add_section(self, section_name): 62 | self.add_help_line(term.underlined(section_name), ' ') 63 | 64 | def add_help_text(self, keys, action_text): 65 | line = ','.join(keys) 66 | justify_length = self.columns[0].size - len(line) 67 | for index, key in enumerate(keys): 68 | keys[index] = io.bold(key) 69 | line = ','.join(keys) + ' '*justify_length 70 | self.add_help_line(line, action_text) 71 | 72 | def add_help_line(self, key, action): 73 | self.data.append({'key': key, 'action': action}) 74 | 75 | 76 | class ViewlessHelpTable(HelpTable): 77 | def set_up_views(self): 78 | pass 79 | -------------------------------------------------------------------------------- /ebcli/labs/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/labs/cloudwatchfiles/cwl-activity-logs-v1.config: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | ## Option Settings 3 | ## Namespace: "aws:elasticbeanstalk:application:environment" 4 | ## OptionName: ActivityCWLogGroup 5 | ## Default: -activity 6 | ## Description: This is the name of the cloudwatch log group for the activity log 7 | ## 8 | ############################################################################### 9 | 10 | 11 | Mappings: 12 | CWLogs: 13 | ActivityLogGroup: 14 | LogFile: "/var/log/eb-activity.log" 15 | TimestampFormat: "%d/%b/%Y:%H:%M:%S %z" 16 | 17 | Outputs: 18 | ActivityCWLogGroup: 19 | Description: "The name of the Cloudwatch Logs Log Group created for this environments activity logs. You can specify this by setting the value for the environment variable: ActivityCWLogGroup. Please note: if you update this value, then you will need to go and clear out the old cloudwatch logs group and delete it through Cloudwatch Logs." 20 | Value: { "Ref" : "AWSEBCloudWatchLogsActivityLogGroup"} 21 | 22 | 23 | Resources : 24 | AWSEBCloudWatchLogsActivityLogGroup: ## Must have prefix: AWSEBCloudWatchLogs 25 | Type: "AWS::Logs::LogGroup" 26 | DependsOn: AWSEBBeanstalkMetadata 27 | DeletionPolicy: Retain ## this is required 28 | Properties: 29 | LogGroupName: 30 | "Fn::GetOptionSetting": 31 | Namespace: "aws:elasticbeanstalk:application:environment" 32 | OptionName: ActivityCWLogGroup 33 | DefaultValue: {"Fn::Join":["-", ["awseb", { "Ref":"AWSEBEnvironmentName" }, "activity"]]} 34 | RetentionInDays: 7 35 | 36 | ## Register the files/log groups for monitoring 37 | AWSEBAutoScalingGroup: 38 | Metadata: 39 | "AWS::CloudFormation::Init": 40 | CWLogsAgentConfigSetup: 41 | files: 42 | ## any .conf file put into /tmp/cwlogs/conf.d will be added to the cwlogs config (see cwl-agent.config) 43 | "/tmp/cwlogs/conf.d/activity-logs.conf": 44 | content : | 45 | [activity_log] 46 | file = `{"Fn::FindInMap":["CWLogs", "ActivityLogGroup", "LogFile"]}` 47 | log_group_name = `{ "Ref" : "AWSEBCloudWatchLogsActivityLogGroup" }` 48 | log_stream_name = {instance_id} 49 | datetime_format = `{"Fn::FindInMap":["CWLogs", "ActivityLogGroup", "TimestampFormat"]}` 50 | mode : "000400" 51 | owner : root 52 | group : root -------------------------------------------------------------------------------- /ebcli/labs/cloudwatchfiles/eb-logs-v1.config: -------------------------------------------------------------------------------- 1 | ################################################################## 2 | ## Sets up the elastic beanstalk log publication to include 3 | ## the admin logs for cloudwatch logs 4 | ################################################################## 5 | 6 | Resources: 7 | AWSEBAutoScalingGroup: 8 | Metadata: 9 | "AWS::CloudFormation::Init": 10 | configSets: 11 | "_OnInstanceBoot": 12 | "CmpFn::Insert": 13 | values: 14 | - EBCWLLogPublicationSetup 15 | EBCWLLogPublicationSetup: 16 | files: 17 | "/opt/elasticbeanstalk/tasks/taillogs.d/cwl-system.conf": 18 | content: | 19 | /var/log/awslogs-agent-setup.log 20 | /var/log/awslogs.log 21 | /var/log/eb-cwlogs.log 22 | mode : "000644" 23 | "/opt/elasticbeanstalk/tasks/bundlelogs.d/cwl-system.conf": 24 | content: | 25 | /var/log/awslogs-agent-setup.log 26 | /var/log/awslogs.log 27 | /var/log/eb-cwlogs.log 28 | mode : "000644" 29 | "/opt/elasticbeanstalk/tasks/systemtaillogs.d/cwl-system.conf": 30 | content: | 31 | /var/log/awslogs-agent-setup.log 32 | /var/log/awslogs.log 33 | /var/log/eb-cwlogs.log 34 | mode : "000644" 35 | "/opt/elasticbeanstalk/tasks/publishlogs.d/cwl-system.conf": 36 | content: | 37 | /var/log/awslogs-agent-setup.log ## this isn't rotated 38 | /var/log/awslogs.log*.gz 39 | mode : "000644" 40 | -------------------------------------------------------------------------------- /ebcli/labs/cloudwatchsetup.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import os 15 | import shutil 16 | 17 | from ebcli.core.abstractcontroller import AbstractBaseController 18 | from ebcli.resources.strings import strings, flag_text 19 | from ebcli.core import io, fileoperations 20 | 21 | 22 | CWFILES_DIRNAME = 'cloudwatchfiles' 23 | CWFILES_DIR_PATH = os.path.join(os.path.dirname( 24 | os.path.realpath(__file__)), 25 | CWFILES_DIRNAME 26 | ) 27 | 28 | 29 | class CloudWatchSetUp(AbstractBaseController): 30 | class Meta: 31 | label = 'setup-cloudwatchlogs' 32 | aliases = ['setup-cwl'] 33 | stacked_on = 'labs' 34 | stacked_type = 'nested' 35 | description = strings['cloudwatch-setup.info'] 36 | usage = 'eb labs setup-cloudwatchlogs [options ...]' 37 | arguments = [ 38 | (['--remove'], dict(help=flag_text['labs.cwl.remove'], action='store_true')) 39 | ] 40 | 41 | def do_command(self): 42 | cwfile_dir = CWFILES_DIR_PATH 43 | 44 | ebextension_dir = fileoperations.project_file_path('.ebextensions') 45 | 46 | if self.app.pargs.remove: 47 | return remove_cwl_extensions(cwfile_dir, ebextension_dir) 48 | 49 | if not os.path.isdir(ebextension_dir): 50 | os.makedirs(ebextension_dir) 51 | 52 | for file_name in os.listdir(cwfile_dir): 53 | source_file = os.path.join(cwfile_dir, file_name) 54 | destination = os.path.join(ebextension_dir, file_name) 55 | 56 | if fileoperations.file_exists(destination): 57 | io.log_error(strings['cloudwatch-setup.alreadysetup'] 58 | .format(filename=destination)) 59 | shutil.copy(source_file, destination) 60 | 61 | io.echo(strings['cloudwatch-setup.text']) 62 | 63 | 64 | def remove_cwl_extensions(cwfile_dir, ebextension_dir): 65 | for file_name in os.listdir(cwfile_dir): 66 | try: 67 | os.remove(os.path.join(ebextension_dir, file_name)) 68 | except: 69 | io.log_warning('Ebextension {} already removed'.format(file_name)) 70 | 71 | io.echo(strings['cloudwatch-setup.removetext']) 72 | -------------------------------------------------------------------------------- /ebcli/labs/controller.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core.abstractcontroller import AbstractBaseController 15 | from ebcli.resources.strings import strings 16 | from ebcli.core import io 17 | from ebcli.labs.quicklink import QuicklinkController 18 | from ebcli.labs.download import DownloadController 19 | from ebcli.labs.convertdockerrun import ConvertDockerrunController 20 | from ebcli.labs.cleanupversions import CleanupVersionsController 21 | from ebcli.labs.cloudwatchsetup import CloudWatchSetUp 22 | from ebcli.labs.setupssl import SetupSSLController 23 | 24 | 25 | class LabsController(AbstractBaseController): 26 | class Meta: 27 | label = 'labs' 28 | description = strings['labs.info'] 29 | usage = AbstractBaseController.Meta.usage.\ 30 | replace('{cmd}', 'labs {cmd}') 31 | arguments = [] 32 | 33 | def do_command(self): 34 | self.app.args.print_help() 35 | 36 | def complete_command(self, commands): 37 | if len(commands) == 1: 38 | labels = [c.Meta.label for c in self._get_child_controllers()] 39 | io.echo(*(label.replace('_', '-') for label in labels)) 40 | elif len(commands) > 1: 41 | controllers = self._get_child_controllers() 42 | for c in controllers: 43 | if commands[1] == c.Meta.label.replace('_', '-'): 44 | c().complete_command(commands[1:]) 45 | 46 | @staticmethod 47 | def _get_child_controllers(): 48 | return [ 49 | QuicklinkController, 50 | DownloadController, 51 | ConvertDockerrunController, 52 | CleanupVersionsController, 53 | SetupSSLController, 54 | CloudWatchSetUp 55 | ] 56 | 57 | @classmethod 58 | def _add_to_handler(cls, handler): 59 | handler.register(cls) 60 | for c in cls._get_child_controllers(): 61 | handler.register(c) 62 | -------------------------------------------------------------------------------- /ebcli/lib/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/lib/botocoredata/elasticbeanstalk/2010-12-01/paginators-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "pagination": { 3 | "DescribeApplicationVersions": { 4 | "result_key": "ApplicationVersions" 5 | }, 6 | "DescribeApplications": { 7 | "result_key": "Applications" 8 | }, 9 | "DescribeConfigurationOptions": { 10 | "result_key": "Options" 11 | }, 12 | "DescribeEnvironments": { 13 | "result_key": "Environments" 14 | }, 15 | "DescribeEvents": { 16 | "input_token": "NextToken", 17 | "output_token": "NextToken", 18 | "limit_key": "MaxRecords", 19 | "result_key": "Events" 20 | }, 21 | "ListAvailableSolutionStacks": { 22 | "result_key": "SolutionStacks" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ebcli/lib/botopatch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | """ 15 | Apply botocore fixes as monkey patches. 16 | This allows us to use any version of botocore. 17 | """ 18 | import datetime 19 | import time 20 | 21 | from dateutil import tz 22 | from botocore import parsers 23 | 24 | 25 | def fix_botocore_to_pass_response_date(): 26 | """ 27 | Patch botocore so that it includes the Date of the response in the meta 28 | data 29 | """ 30 | LOG = parsers.LOG 31 | 32 | def parse(self, response, shape): 33 | """Parse the HTTP response given a shape. 34 | 35 | :param response: The HTTP response dictionary. This is a dictionary 36 | that represents the HTTP request. The dictionary must have the 37 | following keys, ``body``, ``headers``, and ``status_code``. 38 | 39 | :param shape: The model shape describing the expected output. 40 | :return: Returns a dictionary representing the parsed response 41 | described by the model. In addition to the shape described from 42 | the model, each response will also have a ``ResponseMetadata`` 43 | which contains metadata about the response, which contains at least 44 | two keys containing ``RequestId`` and ``HTTPStatusCode``. Some 45 | responses may populate additional keys, but ``RequestId`` will 46 | always be present. 47 | 48 | """ 49 | LOG.debug('Response headers: %s', response['headers']) 50 | LOG.debug('Response body:\n%s', response['body']) 51 | if response['status_code'] >= 301: 52 | parsed = self._do_error_parse(response, shape) 53 | else: 54 | parsed = self._do_parse(response, shape) 55 | if isinstance(parsed, dict) and 'ResponseMetadata' in parsed: 56 | parsed['ResponseMetadata']['HTTPStatusCode'] = ( 57 | response['status_code']) 58 | 59 | # BEGIN PATCH 60 | # Here we inject the date 61 | parsed['ResponseMetadata']['date'] = ( 62 | response['headers']['date'] 63 | ) 64 | # END PATCH 65 | return parsed 66 | 67 | parsers.ResponseParser.parse = parse 68 | 69 | 70 | def apply_patches(): 71 | fix_botocore_to_pass_response_date() 72 | -------------------------------------------------------------------------------- /ebcli/lib/cloudwatch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.lib import aws 15 | from ebcli.objects.log_stream import LogStream 16 | 17 | 18 | def _make_api_call(operation_name, **operation_options): 19 | return aws.make_api_call('logs', operation_name, **operation_options) 20 | 21 | 22 | def get_all_stream_names(log_group_name, log_stream_name_prefix=None): 23 | """ 24 | Return all stream names under the log group. 25 | param: log_group_name: str 26 | """ 27 | streams = describe_log_streams( 28 | log_group_name=log_group_name, 29 | log_stream_name_prefix=log_stream_name_prefix, 30 | ) 31 | 32 | streams = streams or {} 33 | 34 | return [ 35 | log_stream.name 36 | for log_stream 37 | in LogStream.log_stream_objects_from_json(streams.get('logStreams', [])) 38 | ] 39 | 40 | 41 | def get_log_events(log_group_name, log_stream_name, next_token=None, 42 | start_from_head=False, start_time=None, end_time=None, 43 | limit=None): 44 | 45 | params = dict(logGroupName=log_group_name, logStreamName=log_stream_name) 46 | 47 | if next_token is not None: 48 | params['nextToken'] = next_token 49 | 50 | if start_from_head is not None: 51 | params['startFromHead'] = start_from_head 52 | 53 | if start_time is not None: 54 | params['startTime'] = start_time 55 | 56 | if end_time is not None: 57 | params['endTime'] = end_time 58 | 59 | if limit is not None: 60 | params['limit'] = limit 61 | 62 | return _make_api_call('get_log_events', **params) 63 | 64 | 65 | def describe_log_streams( 66 | limit=None, 67 | log_group_name=None, 68 | log_stream_name_prefix=None, 69 | next_token=None 70 | ): 71 | params = dict() 72 | 73 | if log_group_name: 74 | params['logGroupName'] = log_group_name 75 | 76 | if log_stream_name_prefix: 77 | params['logStreamNamePrefix'] = log_stream_name_prefix 78 | 79 | if next_token: 80 | params['nextToken'] = next_token 81 | 82 | if limit: 83 | params['limit'] = limit 84 | 85 | return _make_api_call('describe_log_streams', **params) 86 | 87 | 88 | def log_group_exists(log_group_name): 89 | response = _make_api_call('describe_log_groups', logGroupNamePrefix=log_group_name) 90 | 91 | return len(response['logGroups']) > 0 92 | -------------------------------------------------------------------------------- /ebcli/lib/elb.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from cement.utils.misc import minimal_logger 14 | 15 | from ebcli.lib import aws 16 | from ebcli.objects.exceptions import ServiceError, NotFoundError 17 | from ebcli.resources.statics import elb_names 18 | 19 | LOG = minimal_logger(__name__) 20 | 21 | 22 | def _make_api_call(operation_name, **operation_options): 23 | return aws.make_api_call('elb', operation_name, **operation_options) 24 | 25 | 26 | def version(load_balancer_name): 27 | if 'arn:aws:elasticloadbalancing' in load_balancer_name: 28 | return elb_names.APPLICATION_VERSION 29 | return elb_names.CLASSIC_VERSION 30 | 31 | 32 | def is_classic_load_balancer(load_balancer_name): 33 | return 'arn:aws:elasticloadbalancing' not in load_balancer_name 34 | 35 | 36 | def get_health_of_instances(load_balancer_name): 37 | try: 38 | result = _make_api_call( 39 | 'describe_instance_health', 40 | LoadBalancerName=load_balancer_name 41 | ) 42 | except ServiceError as e: 43 | raise NotFoundError(e) 44 | 45 | return result['InstanceStates'] 46 | -------------------------------------------------------------------------------- /ebcli/lib/elbv2.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import time 14 | 15 | from cement.utils.misc import minimal_logger 16 | 17 | from ebcli.lib import aws 18 | from ebcli.objects.exceptions import ServiceError, NotFoundError 19 | 20 | LOG = minimal_logger(__name__) 21 | 22 | 23 | def _make_api_call(operation_name, **operation_options): 24 | return aws.make_api_call('elbv2', operation_name, **operation_options) 25 | 26 | 27 | def get_instance_healths_from_target_groups(target_group_arns): 28 | instance_healths = [] 29 | for arn in target_group_arns: 30 | try: 31 | result = _make_api_call('describe_target_health', TargetGroupArn=arn) 32 | 33 | for description in result['TargetHealthDescriptions']: 34 | instance_healths.append({ 35 | 'InstanceId': description['Target']['Id'], 36 | 'State': description['TargetHealth'].get('State', ''), 37 | 'Description': description['TargetHealth'].get('Description', ''), 38 | 'Reason': description['TargetHealth'].get('Reason', '') 39 | }) 40 | 41 | except ServiceError as e: 42 | raise NotFoundError(e) 43 | 44 | return instance_healths 45 | 46 | 47 | def get_target_group_healths(target_group_arns): 48 | results = {} 49 | for arn in target_group_arns: 50 | try: 51 | results[arn] = _make_api_call('describe_target_health', TargetGroupArn=arn) 52 | except ServiceError as e: 53 | raise NotFoundError(e) 54 | 55 | return results 56 | 57 | 58 | def get_target_groups_for_load_balancer(load_balancer_arn): 59 | try: 60 | return _make_api_call( 61 | 'describe_target_groups', 62 | LoadBalancerArn=load_balancer_arn 63 | )['TargetGroups'] 64 | except ServiceError as e: 65 | raise NotFoundError(e) 66 | 67 | 68 | def get_listeners_for_load_balancer(load_balancer_arn): 69 | return _make_api_call( 70 | 'describe_listeners', 71 | LoadBalancerArn=load_balancer_arn 72 | ) 73 | 74 | 75 | def describe_load_balancers(load_balancer_name): 76 | return _make_api_call( 77 | 'describe_load_balancers', 78 | Names=load_balancer_name 79 | ) 80 | 81 | 82 | def _sleep_to_prevent_elbv2_throttling(): 83 | time.sleep(0.5) 84 | -------------------------------------------------------------------------------- /ebcli/lib/kms.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from cement.utils.misc import minimal_logger 14 | 15 | from ebcli.lib import aws 16 | 17 | LOG = minimal_logger(__name__) 18 | 19 | 20 | def _make_api_call(operation_name, **operation_options): 21 | return aws.make_api_call('kms', operation_name, **operation_options) 22 | 23 | 24 | def keys(): 25 | LOG.debug('Inside list_keys api wrapper') 26 | return [key['KeyId'] for key in _make_api_call('list_keys')['Keys']] 27 | -------------------------------------------------------------------------------- /ebcli/lib/sns.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from cement.utils.misc import minimal_logger 14 | 15 | from ebcli.lib import aws 16 | 17 | LOG = minimal_logger(__name__) 18 | 19 | 20 | def _make_api_call(operation_name, **operation_options): 21 | return aws.make_api_call('sns', operation_name, **operation_options) 22 | 23 | 24 | def topics(): 25 | LOG.debug('Inside list_topics api wrapper') 26 | return [topic['TopicArn'] for topic in _make_api_call('list_topics')['Topics']] 27 | -------------------------------------------------------------------------------- /ebcli/objects/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/objects/api_filters.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | class Filter(object): 16 | def __init__(self, values, operator='='): 17 | self.operator = operator 18 | self.values = values 19 | 20 | def json(self): 21 | return { 22 | 'Type': self.filter_type, 23 | 'Operator': self.operator, 24 | 'Values': self.values, 25 | } 26 | 27 | 28 | class PlatformNameFilter(Filter): 29 | filter_type = 'PlatformName' 30 | 31 | 32 | class PlatformOwnerFilter(Filter): 33 | filter_type = 'PlatformOwner' 34 | 35 | 36 | class PlatformStatusFilter(Filter): 37 | filter_type = 'PlatformStatus' 38 | 39 | 40 | class PlatformVersionFilter(Filter): 41 | filter_type = 'PlatformVersion' 42 | -------------------------------------------------------------------------------- /ebcli/objects/application.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | class Application(): 16 | def __init__(self, name=None, date_created=None, date_updated=None, 17 | description=None, versions=[], templates=[]): 18 | self.name = name 19 | self.date_created = date_created 20 | self.date_updated = date_updated 21 | self.description = description 22 | self.versions = versions 23 | self.templates = templates 24 | 25 | def __str__(self): 26 | return 'Name: ' + self.name 27 | -------------------------------------------------------------------------------- /ebcli/objects/buildconfiguration.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | class BuildConfiguration: 16 | def __init__(self, image=None, service_role=None, compute_type=None, 17 | timeout=None): 18 | self.image = image 19 | self.service_role = service_role 20 | self.compute_type = compute_type 21 | self.timeout = timeout 22 | 23 | def __str__(self): 24 | return ['Image: {0}'.format(self.image), 'ServiceRole: {0}'.format(self.service_role), 25 | 'ComputeType: {0}'.format(self.compute_type), 'Timeout: {0}'.format(self.timeout)] 26 | -------------------------------------------------------------------------------- /ebcli/objects/cfn_stack.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | class CFNStack(object): 16 | def __init__( 17 | self, 18 | stack_id=None, 19 | stack_name=None, 20 | change_set_id=None, 21 | description=None, 22 | creation_time=None, 23 | deletion_time=None, 24 | last_updated_time=None, 25 | stack_status=None, 26 | stack_status_reason=None, 27 | enable_termination_protection=None, 28 | ): 29 | self.stack_id = stack_id 30 | self.stack_name = stack_name 31 | self.change_set_id = change_set_id 32 | self.description = description 33 | self.creation_time = creation_time 34 | self.deletion_time = deletion_time 35 | self.last_updated_time = last_updated_time 36 | self.stack_status = stack_status 37 | self.stack_status_reason = stack_status_reason 38 | self.enable_termination_protection = enable_termination_protection 39 | 40 | def __str__(self): 41 | return self.stack_name 42 | 43 | @classmethod 44 | def json_to_stack_object(cls, cfn_stack_json): 45 | return CFNStack( 46 | stack_id=cfn_stack_json.get('StackId'), 47 | stack_name=cfn_stack_json.get('StackName'), 48 | change_set_id=cfn_stack_json.get('ChangeSetId'), 49 | description=cfn_stack_json.get('Sescription'), 50 | creation_time=cfn_stack_json.get('CreationTime'), 51 | deletion_time=cfn_stack_json.get('DeletionTime'), 52 | last_updated_time=cfn_stack_json.get('LastUpdatedTime'), 53 | stack_status=cfn_stack_json.get('StackStatus'), 54 | stack_status_reason=cfn_stack_json.get('StackStatusReason'), 55 | enable_termination_protection=cfn_stack_json.get( 56 | 'EnableTerminationProtection' 57 | ) 58 | ) 59 | -------------------------------------------------------------------------------- /ebcli/objects/conversionconfiguration.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from abc import ABCMeta, abstractmethod 15 | 16 | 17 | class ConversionConfiguration: 18 | def __init__(self, api_model): 19 | """ 20 | This abstract class is the top layer for a class that takes in raw API response 21 | and will modify it for other uses. 22 | :param api_model: API response from AWS 23 | """ 24 | self.api_model = api_model 25 | pass 26 | 27 | __metaclass__ = ABCMeta 28 | 29 | @abstractmethod 30 | def collect_changes(self, usr_model): 31 | """ 32 | Grabs all the pairs in the usr_model that are different and returns just the 33 | changes ready to be put into a request. 34 | :param usr_model: User model, key-value style 35 | :return: Api model with only the changes in it 36 | """ 37 | pass 38 | 39 | @abstractmethod 40 | def convert_api_to_usr_model(self): 41 | """ 42 | Converts the saved api model to a User model as a key-value system and remove 43 | unwanted entries 44 | :return: A user model, key-value style 45 | """ 46 | pass 47 | 48 | def _copy_api_entry(self, key_name, usr_model): 49 | """ 50 | Copies the given key-value from the api model into the given user model 51 | :param key_name: key name of the pair we want to copy 52 | :param usr_model: user model we want to add to 53 | """ 54 | usr_model[key_name] = self.api_model[key_name] 55 | -------------------------------------------------------------------------------- /ebcli/objects/log_stream.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | class LogStream(object): 16 | def __init__( 17 | self, 18 | name, 19 | creation_time 20 | ): 21 | self.name = name 22 | self.creation_time = creation_time 23 | 24 | def __lt__(self, other): 25 | return self.creation_time < other.creation_time 26 | 27 | @classmethod 28 | def log_stream_objects_from_json(cls, json): 29 | log_streams = list() 30 | for log_stream in json: 31 | log_streams.append( 32 | LogStream( 33 | name=log_stream['logStreamName'], 34 | creation_time=log_stream['creationTime'] 35 | ) 36 | ) 37 | 38 | return sorted(log_streams) 39 | -------------------------------------------------------------------------------- /ebcli/objects/region.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | 15 | def get_all_regions(): 16 | return [ 17 | Region('us-east-1', 'US East (N. Virginia)'), 18 | Region('us-west-1', 'US West (N. California)'), 19 | Region('us-west-2', 'US West (Oregon)'), 20 | Region('eu-west-1', 'EU (Ireland)'), 21 | Region('eu-central-1', 'EU (Frankfurt)'), 22 | Region('ap-south-1', 'Asia Pacific (Mumbai)'), 23 | Region('ap-southeast-1', 'Asia Pacific (Singapore)'), 24 | Region('ap-southeast-2', 'Asia Pacific (Sydney)'), 25 | Region('ap-northeast-1', 'Asia Pacific (Tokyo)'), 26 | Region('ap-northeast-2', 'Asia Pacific (Seoul)'), 27 | Region('sa-east-1', 'South America (Sao Paulo)'), 28 | Region('cn-north-1', 'China (Beijing)'), 29 | Region('cn-northwest-1', 'China (Ningxia)'), 30 | Region('us-east-2', 'US East (Ohio)'), 31 | Region('ca-central-1', 'Canada (Central)'), 32 | Region('eu-west-2', 'EU (London)'), 33 | Region('eu-west-3', 'EU (Paris)'), 34 | Region('eu-north-1', 'EU (Stockholm)'), 35 | Region('eu-south-1', 'EU (Milano)'), 36 | Region('ap-east-1', 'Asia Pacific (Hong Kong)'), 37 | Region('me-south-1', 'Middle East (Bahrain)'), 38 | Region('af-south-1', 'Africa (Cape Town)'), 39 | Region('ap-southeast-3', 'Asia Pacific (Jakarta)'), 40 | Region('ap-northeast-3', 'Asia Pacific (Osaka)'), 41 | ] 42 | 43 | 44 | class Region(): 45 | def __init__(self, name, description): 46 | self.name = name 47 | self.description = description 48 | 49 | def __str__(self): 50 | return self.name + ' : ' + self.description 51 | -------------------------------------------------------------------------------- /ebcli/objects/tier.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.objects.exceptions import NotFoundError 14 | 15 | 16 | class Tier(object): 17 | 18 | TIER_MAP = { 19 | 'webserver': (lambda: Tier('WebServer', 'Standard', '1.0')), 20 | 'webserver/standard': (lambda: Tier('WebServer', 'Standard', '1.0')), 21 | 'worker': (lambda: Tier('Worker', 'SQS/HTTP', '')), 22 | 'worker/sqs/http': (lambda: Tier('Worker', 'SQS/HTTP', '')), 23 | } 24 | 25 | @staticmethod 26 | def get_all_tiers(): 27 | lst = [ 28 | Tier('WebServer', 'Standard', '1.0'), 29 | Tier('Worker', 'SQS/HTTP', ''), 30 | ] 31 | return lst 32 | 33 | def __init__(self, name, typ, version, elb_type=None): 34 | self.name = name 35 | self.type = typ 36 | self.version = version 37 | self.elb_type = elb_type 38 | 39 | def to_dict(self): 40 | json = { 41 | 'Name': self.name, 42 | 'Type': self.type, 43 | } 44 | 45 | if self.version: 46 | json['Version'] = self.version 47 | 48 | return json 49 | 50 | def __str__(self): 51 | s = self.name + '-' + self.type 52 | if self.version: 53 | s += '-' + self.version 54 | return s 55 | 56 | def __eq__(self, other): 57 | if not isinstance(other, Tier): 58 | return False 59 | 60 | return self.name.lower() == other.name.lower() 61 | 62 | @classmethod 63 | def get_default(cls): 64 | return cls.TIER_MAP['webserver']() 65 | 66 | @classmethod 67 | def from_raw_string(cls, customer_input): 68 | try: 69 | return cls.TIER_MAP[customer_input.lower().strip()]() 70 | except KeyError: 71 | raise NotFoundError('Provided tier "{}" does not appear to be valid'.format(customer_input)) 72 | 73 | def is_webserver(self): 74 | return self.name.lower() == 'webserver' 75 | 76 | def is_worker(self): 77 | return self.name.lower() == 'worker' 78 | 79 | @classmethod 80 | def looks_like_worker_tier(cls, customer_input): 81 | return cls.from_raw_string(customer_input) == cls.from_raw_string('worker') 82 | 83 | @classmethod 84 | def looks_like_webserver_tier(cls, customer_input): 85 | return cls.from_raw_string(customer_input) == cls.from_raw_string('webserver') 86 | -------------------------------------------------------------------------------- /ebcli/operations/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/operations/abortops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.lib import elasticbeanstalk 15 | from ebcli.core import io 16 | 17 | 18 | def get_abortable_envs(app_name): 19 | envs = elasticbeanstalk.get_app_environments(app_name) 20 | return [e for e in envs if e.is_abortable] 21 | 22 | 23 | def abort_operation(env_name): 24 | elasticbeanstalk.abort_environment_update(env_name) 25 | io.echo('Aborting update to environment "{}". \n' 26 | 'Type "eb events -f" to watch the environment events.'.format(env_name)) 27 | -------------------------------------------------------------------------------- /ebcli/operations/cloneops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import re 15 | 16 | from cement.utils.misc import minimal_logger 17 | 18 | from ebcli.lib import elasticbeanstalk, utils 19 | from ebcli.lib.aws import InvalidParameterValueError 20 | from ebcli.core import io 21 | from ebcli.resources.strings import strings, responses, prompts 22 | from ebcli.operations import commonops 23 | 24 | 25 | LOG = minimal_logger(__name__) 26 | 27 | 28 | def make_cloned_env(clone_request, nohang=False, timeout=None): 29 | io.log_info('Cloning environment') 30 | env = elasticbeanstalk.get_environment( 31 | app_name=clone_request.app_name, 32 | env_name=clone_request.original_name 33 | ) 34 | clone_request.version_label = env.version_label 35 | result, request_id = clone_env(clone_request) 36 | 37 | result.print_env_details( 38 | io.echo, 39 | elasticbeanstalk.get_environments, 40 | elasticbeanstalk.get_environment_resources, 41 | health=False 42 | ) 43 | 44 | if nohang: 45 | return 46 | 47 | io.echo('Printing Status:') 48 | 49 | commonops.wait_for_success_events(request_id, timeout_in_minutes=timeout) 50 | 51 | 52 | def clone_env(clone_request): 53 | while True: 54 | try: 55 | return elasticbeanstalk.clone_environment(clone_request) 56 | except InvalidParameterValueError as e: 57 | LOG.debug('cloning env returned error: ' + e.message) 58 | if re.match(responses['env.cnamenotavailable'], e.message): 59 | io.echo(prompts['cname.unavailable']) 60 | clone_request.cname = io.prompt_for_cname() 61 | elif re.match(responses['env.nameexists'], e.message): 62 | io.echo(strings['env.exists']) 63 | current_environments = elasticbeanstalk.get_environment_names( 64 | clone_request.app_name) 65 | unique_name = utils.get_unique_name(clone_request.env_name, 66 | current_environments) 67 | clone_request.env_name = io.prompt_for_environment_name( 68 | default_name=unique_name) 69 | else: 70 | raise 71 | -------------------------------------------------------------------------------- /ebcli/operations/composeops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.lib import elasticbeanstalk 14 | from ebcli.core import io 15 | from ebcli.operations import commonops 16 | 17 | 18 | def compose(app_name, version_labels, grouped_env_names, group_name=None, 19 | nohang=False, timeout=None): 20 | 21 | success = commonops.wait_for_processed_app_versions(app_name, version_labels, timeout=timeout or 10) 22 | if not success: 23 | return 24 | 25 | request_id = compose_apps(app_name, version_labels, group_name) 26 | 27 | if nohang: 28 | return 29 | 30 | commonops.wait_for_compose_events(request_id, app_name, grouped_env_names, timeout) 31 | 32 | 33 | def compose_apps(app_name, version_labels, group_name=None): 34 | io.echo('--- Creating modules ---') 35 | request_id = elasticbeanstalk.compose_environments(app_name, version_labels, 36 | group_name) 37 | return request_id 38 | 39 | 40 | def compose_no_events(app_name, version_labels, group_name=None): 41 | success = commonops.wait_for_processed_app_versions(app_name, version_labels) 42 | if not success: 43 | return None 44 | 45 | return compose_apps(app_name, version_labels, group_name) 46 | -------------------------------------------------------------------------------- /ebcli/operations/consoleops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.lib import utils, elasticbeanstalk, aws 14 | from ebcli.objects.exceptions import NotSupportedError 15 | from ebcli.operations import commonops 16 | 17 | 18 | def open_console(app_name, env_name): 19 | if utils.is_ssh(): 20 | raise NotSupportedError('The console command is not supported' 21 | ' in an ssh type session') 22 | 23 | env = None 24 | if env_name is not None: 25 | env = elasticbeanstalk.get_environment(app_name=app_name, env_name=env_name) 26 | 27 | region = aws.get_region_name() 28 | if env is not None: 29 | page = 'environment/dashboard' 30 | else: 31 | page = 'application/overview' 32 | 33 | app_name = utils.url_encode(app_name) 34 | 35 | console_url = 'console.aws.amazon.com/elasticbeanstalk/home?' 36 | console_url += 'region=' + region 37 | console_url += '#/' + page + '?applicationName=' + app_name 38 | 39 | if env is not None: 40 | console_url += '&environmentId=' + env.id 41 | 42 | commonops.open_webpage_in_browser(console_url, ssl=True) 43 | -------------------------------------------------------------------------------- /ebcli/operations/eventsops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import os 15 | 16 | import time 17 | from ebcli.core import io 18 | from ebcli.lib import elasticbeanstalk 19 | from ebcli.objects.exceptions import EndOfTestError 20 | from ebcli.operations import commonops 21 | 22 | 23 | def print_events(app_name, env_name, follow, platform_arn=None): 24 | if follow: 25 | follow_events(app_name, env_name, platform_arn) 26 | else: 27 | events = elasticbeanstalk.get_new_events( 28 | app_name, env_name, None, platform_arn=platform_arn) 29 | 30 | data = [] 31 | for event in reversed(events): 32 | data.append(commonops.get_event_string(event, long_format=True)) 33 | io.echo_with_pager(os.linesep.join(data)) 34 | 35 | 36 | def follow_events(app_name, env_name, platform_arn=None): 37 | last_time = None 38 | streamer = io.get_event_streamer() 39 | try: 40 | while True: 41 | events = elasticbeanstalk.get_new_events( 42 | app_name, env_name, None, platform_arn=platform_arn, last_event_time=last_time 43 | ) 44 | 45 | for event in reversed(events): 46 | message = commonops.get_event_string(event, long_format=True) 47 | streamer.stream_event(message) 48 | last_time = event.event_date 49 | 50 | _sleep() 51 | except EndOfTestError: 52 | pass 53 | finally: 54 | streamer.end_stream() 55 | 56 | 57 | def _sleep(): 58 | time.sleep(4) 59 | -------------------------------------------------------------------------------- /ebcli/operations/listops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.lib import aws, utils, elasticbeanstalk 15 | from ebcli.core import io 16 | from ebcli.operations import commonops 17 | 18 | 19 | def list_env_names(app_name, verbose, all_apps): 20 | region = aws.get_region_name() 21 | 22 | if verbose: 23 | io.echo('Region:', region) 24 | 25 | if all_apps: 26 | for app_name in elasticbeanstalk.get_application_names(): 27 | list_env_names_for_app(app_name, verbose) 28 | else: 29 | list_env_names_for_app(app_name, verbose) 30 | 31 | 32 | def list_env_names_for_app(app_name, verbose): 33 | current_env = commonops.get_current_branch_environment() 34 | env_names = elasticbeanstalk.get_environment_names(app_name) 35 | env_names.sort() 36 | 37 | if verbose: 38 | io.echo('Application:', app_name) 39 | io.echo(' Environments:', len(env_names)) 40 | for e in env_names: 41 | instances = commonops.get_instance_ids(e) 42 | if e == current_env: 43 | e = '* ' + e 44 | 45 | io.echo(' ', e, ':', instances) 46 | 47 | else: 48 | for i in range(0, len(env_names)): 49 | if env_names[i] == current_env: 50 | env_names[i] = '* ' + env_names[i] 51 | 52 | if len(env_names) <= 10: 53 | for e in env_names: 54 | io.echo(e) 55 | else: 56 | utils.print_list_in_columns(env_names) 57 | -------------------------------------------------------------------------------- /ebcli/operations/openops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.resources.statics import namespaces, option_names 15 | from ebcli.lib import elasticbeanstalk 16 | from ebcli.operations import commonops 17 | 18 | 19 | def open_app(app_name, env_name): 20 | env = elasticbeanstalk.get_environment(app_name=app_name, env_name=env_name) 21 | settings = elasticbeanstalk.describe_configuration_settings( 22 | app_name, env_name) 23 | 24 | option_settings = settings.get('OptionSettings', []) 25 | http_port = elasticbeanstalk.get_option_setting( 26 | option_settings, 27 | namespaces.LOAD_BALANCER, 28 | option_names.LOAD_BALANCER_HTTP_PORT) 29 | 30 | if http_port == 'OFF': 31 | ssl = True 32 | else: 33 | ssl = False 34 | 35 | commonops.open_webpage_in_browser(env.cname, ssl=ssl) 36 | -------------------------------------------------------------------------------- /ebcli/operations/platform_branch_ops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.lib import elasticbeanstalk 14 | from ebcli.objects.platform import PlatformBranch, PlatformVersion 15 | 16 | _non_retired_platform_branches_cache = None 17 | 18 | 19 | def collect_families_from_branches(branches): 20 | return list(set([branch['PlatformName'] for branch in branches])) 21 | 22 | 23 | def is_platform_branch_name(platform_string): 24 | return bool( 25 | # a platform branch name cannot be an arn 26 | not PlatformVersion.is_valid_arn(platform_string) 27 | # request the platform branch from the api to determine if it exists 28 | and get_platform_branch_by_name(platform_string) 29 | ) 30 | 31 | 32 | def get_platform_branch_by_name(branch_name): 33 | branch_name_filter = { 34 | 'Attribute': 'BranchName', 35 | 'Operator': '=', 36 | 'Values': [branch_name], 37 | } 38 | 39 | results = elasticbeanstalk.list_platform_branches( 40 | filters=[branch_name_filter]) 41 | 42 | if len(results) == 0: 43 | return None 44 | elif len(results) > 1: 45 | return _resolve_conflicting_platform_branches(results) 46 | 47 | return results[0] 48 | 49 | 50 | def list_nonretired_platform_branches(): 51 | """ 52 | Provides a list of all platform branches that are not retired. 53 | This includes deprecated and beta platform branches. 54 | Return value is cached preventing redundant http requests on 55 | subsequent calls. 56 | """ 57 | global _non_retired_platform_branches_cache 58 | if not _non_retired_platform_branches_cache: 59 | noretired_filter = { 60 | 'Attribute': 'LifecycleState', 61 | 'Operator': '!=', 62 | 'Values': ['Retired'] 63 | } 64 | _non_retired_platform_branches_cache = elasticbeanstalk.list_platform_branches( 65 | filters=[noretired_filter]) 66 | 67 | return _non_retired_platform_branches_cache 68 | 69 | 70 | def _resolve_conflicting_platform_branches(branches): 71 | """ 72 | Accepts a list of PlatformBranchSummary objects and 73 | and returns one PlatformBranchSummary object based on 74 | LifecycleState precedence. 75 | Supported < Beta < Deprecated < Retired 76 | """ 77 | if not branches: 78 | return None 79 | 80 | branches = list(sorted( 81 | branches, 82 | key=lambda x: PlatformBranch.LIFECYCLE_SORT_VALUES.get( 83 | x['LifecycleState'], 84 | PlatformBranch.LIFECYCLE_SORT_VALUES['DEFAULT'], 85 | ) 86 | )) 87 | 88 | return branches[0] 89 | -------------------------------------------------------------------------------- /ebcli/operations/scaleops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.lib import elasticbeanstalk 15 | from ebcli.core import io 16 | from ebcli.resources.strings import prompts 17 | from ebcli.operations import commonops 18 | 19 | 20 | def scale(app_name, env_name, number, confirm, timeout=None): 21 | options = [] 22 | env = elasticbeanstalk.describe_configuration_settings( 23 | app_name, env_name 24 | )['OptionSettings'] 25 | 26 | namespace = 'aws:elasticbeanstalk:environment' 27 | setting = next((n for n in env if n["Namespace"] == namespace), None) 28 | value = setting['Value'] 29 | if value == 'SingleInstance': 30 | if not confirm: 31 | io.echo(prompts['scale.switchtoloadbalance']) 32 | io.log_warning(prompts['scale.switchtoloadbalancewarn']) 33 | switch = io.get_boolean_response() 34 | if not switch: 35 | return 36 | 37 | options.append({'Namespace': namespace, 38 | 'OptionName': 'EnvironmentType', 39 | 'Value': 'LoadBalanced'}) 40 | 41 | namespace = 'aws:autoscaling:asg' 42 | max = 'MaxSize' 43 | min = 'MinSize' 44 | 45 | for name in [max, min]: 46 | options.append( 47 | { 48 | 'Namespace': namespace, 49 | 'OptionName': name, 50 | 'Value': str(number) 51 | } 52 | ) 53 | request_id = elasticbeanstalk.update_environment(env_name, options) 54 | 55 | commonops.wait_for_success_events( 56 | request_id, 57 | timeout_in_minutes=timeout or 5, 58 | can_abort=True 59 | ) 60 | -------------------------------------------------------------------------------- /ebcli/operations/spotops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.core import io 15 | from ebcli.resources.strings import prompts, strings 16 | 17 | 18 | def get_spot_instance_types_from_customer(interactive, enable_spot): 19 | """ 20 | Prompt customer to specify their desired instances types if they 21 | selected enabled spot requests from the interactive flow. 22 | 23 | :param interactive: True/False depending on whether operating in the interactive mode or not 24 | :param enable_spot: False/True depending on user has set --enable-spot to true or false 25 | :return: list of comma separated instance types 26 | """ 27 | if not interactive or not enable_spot: 28 | return 29 | io.echo(prompts['spot.instance_types_prompt']) 30 | return prompt_for_instance_types() 31 | 32 | 33 | def get_spot_request_from_customer(interactive): 34 | """ 35 | Prompt customer to select if they would like to enable spot requests if 36 | operating in the interactive mode. 37 | 38 | Selection defaults to 'No' when provided with blank input. 39 | :param interactive: True/False depending on whether operating in the interactive mode or not 40 | :return: selected value for if to enable spot requests or not: True/False 41 | """ 42 | if not interactive: 43 | return 44 | io.echo() 45 | return io.get_boolean_response( 46 | text=prompts['spot.enable_spot_prompt'], 47 | default=False) 48 | 49 | 50 | def prompt_for_instance_types(): 51 | """ 52 | Method accepts the user's choice of instance types to be used for spot fleet request 53 | 54 | :return: user's choice of whether the spot request should be enabled 55 | """ 56 | instance_types = io.prompt(strings['spot.instance_type_defaults_notice']) 57 | io.echo() 58 | return instance_types 59 | -------------------------------------------------------------------------------- /ebcli/operations/swapops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.lib import elasticbeanstalk 15 | from ebcli.operations import commonops 16 | 17 | 18 | def cname_swap(source_env, dest_env): 19 | request_id = elasticbeanstalk.swap_environment_cnames(source_env, dest_env) 20 | 21 | commonops.wait_for_success_events( 22 | request_id, 23 | timeout_in_minutes=1, 24 | sleep_time=2 25 | ) 26 | -------------------------------------------------------------------------------- /ebcli/operations/tagops/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/operations/useops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from ebcli.objects.exceptions import ServiceError, NotFoundError 14 | from ebcli.lib import elasticbeanstalk, codecommit 15 | from ebcli.operations import commonops, gitops 16 | 17 | 18 | def switch_default_environment(env_name): 19 | __verify_environment_exists(env_name) 20 | 21 | commonops.set_environment_for_current_branch(env_name) 22 | 23 | 24 | def switch_default_repo_and_branch(repo_name, branch_name): 25 | __verify_codecommit_branch_and_repository_exist(repo_name, branch_name) 26 | 27 | gitops.set_repo_default_for_current_environment(repo_name) 28 | gitops.set_branch_default_for_current_environment(branch_name) 29 | 30 | 31 | def __verify_environment_exists(env_name): 32 | elasticbeanstalk.get_environment(env_name=env_name) 33 | 34 | 35 | def __verify_codecommit_branch_and_repository_exist(repo_name, branch_name): 36 | try: 37 | codecommit.get_branch(repo_name, branch_name) 38 | except ServiceError: 39 | raise NotFoundError("CodeCommit branch not found: {}".format(branch_name)) 40 | -------------------------------------------------------------------------------- /ebcli/resources/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /ebcli/resources/regex.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import re 14 | 15 | 16 | class PackerRegExpressions(object): 17 | LOG_MESSAGE_REGEX = re.compile(r'.* -- (.+)$') 18 | LOG_MESSAGE_SEVERITY_REGEX = re.compile(r'.*(INFO|ERROR|WARN) -- .*') 19 | OTHER_FORMAT_REGEX = re.compile(r'[^:]+: (.+)') 20 | PACKER_UI_MESSAGE_FORMAT_REGEX = re.compile(r'Packer:.*ui,.*,(.*)') 21 | PACKER_OTHER_MESSAGE_DATA_REGEX = re.compile(r'Packer: \d+,([^,]*),.*') 22 | PACKER_OTHER_MESSAGE_TARGET_REGEX = re.compile(r'Packer: \d+,[^,]*,(.+)') 23 | 24 | 25 | class PlatformRegExpressions(object): 26 | VALID_PLATFORM_NAME_FORMAT = re.compile(r'^([^:/]+)$') 27 | VALID_PLATFORM_SHORT_FORMAT = re.compile(r'^([^:/]+)/(\d+\.\d+\.\d+)$') 28 | VALID_PLATFORM_VERSION_FORMAT = re.compile(r'^\d+\.\d+\.\d+$') 29 | -------------------------------------------------------------------------------- /index.rst: -------------------------------------------------------------------------------- 1 | 2 | Welcome to Example Sphinx Project's documentation! 3 | ================================================== 4 | 5 | .. glossary:: 6 | 7 | Example Term 8 | This defines "Example Term" meaning, to be used accross the whole company and its projects. -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | botocore>=1.35.0,<2 2 | cement==2.10.14 3 | colorama>=0.4.6,<0.5 4 | pathspec==0.12.1 5 | python-dateutil>=2.1,<3.0.0 6 | requests>=2.31,<3 7 | setuptools>=20.0 8 | semantic_version>=2.10.0,<2.11 9 | termcolor>=2.4.0,<3 10 | wcwidth>=0.2.13,<0.3 11 | PyYAML>=5.3.1,<6.1 12 | urllib3>=1.26.5,<2 13 | packaging>=24.2,<25.0 14 | blessed>=1.20.0 15 | fabric==3.2.2 16 | -------------------------------------------------------------------------------- /scripts/jenkins/install_dependencies: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"). You 5 | # may not use this file except in compliance with the License. A copy of 6 | # the License is located at 7 | # 8 | # http://aws.amazon.com/apache2.0/ 9 | # 10 | # or in the "license" file accompanying this file. This file is 11 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 12 | # ANY KIND, either express or implied. See the License for the specific 13 | # language governing permissions and limitations under the License. 14 | import os 15 | import sys 16 | from subprocess import check_call, Popen, PIPE 17 | 18 | _dname = os.path.dirname 19 | 20 | REPO_ROOT = _dname(_dname(_dname(os.path.abspath(__file__)))) 21 | os.chdir(REPO_ROOT) 22 | 23 | 24 | def run(command): 25 | return check_call(command, shell=True) 26 | 27 | 28 | try: 29 | python_version = os.environ['PYTHON_VERSION'] 30 | except KeyError: 31 | python_version = '.'.join([str(i) for i in sys.version_info[:2]]) 32 | 33 | p = Popen(['pip', 'uninstall', '-y', 'awsebcli'], stdout=PIPE) 34 | p.communicate() 35 | 36 | run('pip install . --no-cache-dir') 37 | run('pip install -r dev_requirements.txt --no-cache-dir') 38 | -------------------------------------------------------------------------------- /scripts/jenkins/run_unit_tests: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import os 14 | import subprocess 15 | import sys 16 | 17 | subprocess.check_call( 18 | 'pytest {unit_test_dir} --cov-report term-missing --junitxml=junit-ebcli.xml --cov={platform_path_prefix}ebcli --cov-report xml'.format( 19 | unit_test_dir=os.path.join('tests', 'unit'), 20 | platform_path_prefix='.\\' if sys.platform.startswith('win') else './' 21 | ), 22 | shell=True 23 | ) 24 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import sys 14 | 15 | import pytest 16 | import pytest_socket 17 | 18 | from ebcli.core import fileoperations, io 19 | from ebcli.core.ebrun import fix_path 20 | 21 | 22 | pytest_socket.disable_socket() 23 | 24 | 25 | def ensure_eb_application_has_not_been_initialized(): 26 | if '--help' in sys.argv: 27 | # Allow `pytest --help` to print 28 | return 29 | 30 | if fileoperations.inside_ebcli_project(): 31 | exception_message = ' '.join( 32 | [ 33 | 'ERROR: This directory or one of its ancestors has been `eb init`-ed. Ensure that the .elasticbeanstalk', 34 | 'directories in this directory or above it have been deleted in order for the test suite to run.' 35 | ] 36 | ) 37 | io.echo(exception_message) 38 | exit(1) 39 | 40 | 41 | ensure_eb_application_has_not_been_initialized() 42 | 43 | 44 | def pytest_configure(config): 45 | fix_path() 46 | -------------------------------------------------------------------------------- /tests/unit/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. -------------------------------------------------------------------------------- /tests/unit/containers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /tests/unit/containers/dummy.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | from mock import Mock 14 | 15 | 16 | def get_pathconfig(): 17 | return Mock(docker_proj_path=lambda: DOCKER_PROJ_PATH, 18 | dockerfile_path=lambda: DOCKERFILE_PATH, 19 | new_dockerfile_path=lambda: NEW_DOCKERFILE_PATH, 20 | dockerignore_path=lambda: DOCKERIGNORE_PATH, 21 | logdir_path=lambda: LOGDIR_PATH, 22 | dockerrun_path=lambda: DOCKERRUN_PATH, 23 | compose_path=lambda: COMPOSE_PATH, 24 | setenv_path=lambda: SETENV_PATH, 25 | dockerfile_exists=lambda: DOCKERFILE_EXISTS, 26 | dockerrun_exists=lambda: DOCKERRUN_EXISTS) 27 | 28 | 29 | def get_container_fs_handler(): 30 | return Mock(pathconfig=get_pathconfig(), 31 | dockerrun=get_dockerrun_dict()) 32 | 33 | 34 | def get_multicontainer_fs_handler(): 35 | return Mock(pathconfig=get_pathconfig(), 36 | hostlog_path=HOSTLOG_PATH, 37 | dockerrun=get_container_fs_handler()) 38 | 39 | 40 | def get_soln_stk(): 41 | return Mock() 42 | 43 | 44 | def get_container_cfg(): 45 | return {} 46 | 47 | 48 | def get_dockerrun_dict(): 49 | return {'AWSEBDockerrunVersion': '1'} 50 | 51 | 52 | DOCKER_PROJ_PATH = '/eb-project' 53 | DOCKERFILE_PATH = '/eb-project/Dockerfile' 54 | NEW_DOCKERFILE_PATH = '/eb-project/.elasticbeanstalk/Dockerfile.local' 55 | DOCKERIGNORE_PATH = '/eb-project/.dockerignore' 56 | LOGDIR_PATH = '/eb-project/.elasticbeanstalk/logs/local' 57 | HOSTLOG_PATH = '/eb-project/.elasticbeanstalk/logs/local/12345_6789' 58 | DOCKERRUN_PATH = '/eb-project/Dockerrun.aws.json' 59 | COMPOSE_PATH = '/eb-project/.elasticbeanstalk/docker-compose.yml' 60 | SETENV_PATH = '/eb-project/.elasticbeanstalk/.envvars' 61 | DOCKERFILE_EXISTS = True 62 | DOCKERRUN_EXISTS = True 63 | HOST_PORT = '9000' 64 | SOLN_STK = get_soln_stk() 65 | CONTAINER_CFG = get_container_cfg() 66 | DOCKERRUN_DICT = get_dockerrun_dict() 67 | PATH_CONFIG = get_pathconfig() 68 | MULTICONTAINER_FS_HANDLER = get_multicontainer_fs_handler() 69 | CONTAINER_FS_HANDLER = get_container_fs_handler() 70 | -------------------------------------------------------------------------------- /tests/unit/containers/test_compat.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import os 14 | from mock import patch, Mock 15 | from unittest import TestCase 16 | 17 | from ebcli.containers import compat 18 | from ebcli.objects.exceptions import CommandError 19 | 20 | 21 | DOCKER_HOST_KEY = 'DOCKER_HOST' 22 | DOCKER_HOST_VAL = 'tcp://192.168.59.105:2376' 23 | DOCKER_TLS_VERIFY_KEY = 'DOCKER_TLS_VERIFY' 24 | DOCKER_TLS_VERIFY_VAL = '1' 25 | DOCKER_CERT_PATH_KEY = 'DOCKER_CERT_PATH' 26 | DOCKER_CERT_PATH_VAL = '/a/b/c' 27 | MOCK_MAC_CONTAINER_IP = '123.456.789' 28 | EXPECTED_SHELLINIT = os.linesep.join([' export {}={}'.format(DOCKER_TLS_VERIFY_KEY, DOCKER_TLS_VERIFY_VAL), 29 | ' export {}={}'.format(DOCKER_HOST_KEY, DOCKER_HOST_VAL), 30 | ' export {}={}'.format(DOCKER_CERT_PATH_KEY, DOCKER_CERT_PATH_VAL)]) 31 | 32 | EXPECTED_ENVIRON_VARS_SET = {DOCKER_HOST_KEY: DOCKER_HOST_VAL, 33 | DOCKER_TLS_VERIFY_KEY: DOCKER_TLS_VERIFY_VAL, 34 | DOCKER_CERT_PATH_KEY: DOCKER_CERT_PATH_VAL} 35 | 36 | 37 | class TestCompat(TestCase): 38 | def test_remove_leading_zeros_from_version(self): 39 | versions_tests = [] 40 | versions_tests.append(('0001.000.000', '1.0.0')) 41 | versions_tests.append(('1.0001.0000-rc.1', '1.1.0-rc.1')) 42 | versions_tests.append(('1.3.0', '1.3.0')) 43 | versions_tests.append(('17.03.0-ce', '17.3.0-ce')) 44 | versions_tests.append(('107.3.30-ce', '107.3.30-ce')) 45 | versions_tests.append(('017.030.07-ce', '17.30.7-ce')) 46 | versions_tests.append(('17.03.08-ce', '17.3.8-ce')) 47 | for test in versions_tests: 48 | self.assertEqual(compat.remove_leading_zeros_from_version(test[0]), test[1]) 49 | -------------------------------------------------------------------------------- /tests/unit/containers/test_envvarcollector.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the 'license' file accompanying this file. This file is 10 | # distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.containers.envvarcollector import EnvvarCollector 15 | from mock import patch 16 | from unittest import TestCase 17 | 18 | 19 | class TestEnvvarCollector(TestCase): 20 | def test_empty_environment(self): 21 | self.assertDictEqual({}, EnvvarCollector().map) 22 | self.assertSetEqual(set(), EnvvarCollector().to_remove) 23 | 24 | def test_merge_non_overlapping_envs(self): 25 | env0 = EnvvarCollector({'a': '0', 'b': '1'}) 26 | env1 = EnvvarCollector({'c': '3', 'd': '4'}) 27 | 28 | expected_envvars = {'a': '0', 'b': '1', 'c': '3', 'd': '4'} 29 | 30 | self.assertDictEqual(expected_envvars, env0.merge(env1).filtered().map) 31 | self.assertDictEqual(expected_envvars, env1.merge(env0).filtered().map) 32 | 33 | self.assertSetEqual(set(), env0.merge(env1).to_remove) 34 | self.assertSetEqual(set(), env1.merge(env0).to_remove) 35 | 36 | def test_merge_overlapping_and_vars_to_remove(self): 37 | env0 = EnvvarCollector({'a': '0', 'd': '1'}) 38 | env1 = EnvvarCollector({'a': '5', 'd': '5'}, {'d', 'c'}) 39 | 40 | self.assertEqual({'a': '5'}, env0.merge(env1).filtered().map) 41 | self.assertEqual({'a': '0'}, env1.merge(env0).filtered().map) 42 | 43 | self.assertSetEqual({'d', 'c'}, env0.merge(env1).to_remove) 44 | self.assertSetEqual({'d', 'c'}, env1.merge(env0).to_remove) 45 | 46 | def test_fitered_removed_all_envvars(self): 47 | env = EnvvarCollector({'a': '5', 'd': '5'}, {'a', 'd'}) 48 | result = env.filtered() 49 | self.assertDictEqual({}, result.map) 50 | self.assertSetEqual(set(), result.to_remove) 51 | 52 | def test_fitered_removed_some_envvars(self): 53 | env = EnvvarCollector({'a': '5', 'd': '5'}, {'a'}) 54 | result = env.filtered() 55 | self.assertDictEqual({'d': '5'}, result.map) 56 | self.assertSetEqual(set(), result.to_remove) 57 | 58 | def test_fitered_removed_no_envvars(self): 59 | envvars = {'a': '5', 'd': '5'} 60 | env = EnvvarCollector(envvars) 61 | result = env.filtered() 62 | self.assertDictEqual(envvars, result.map) 63 | self.assertSetEqual(set(), result.to_remove) 64 | -------------------------------------------------------------------------------- /tests/unit/containers/test_generic_container.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the 'license' file accompanying this file. This file is 10 | # distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | from ebcli.containers.generic_container import GenericContainer 15 | from ebcli.objects.exceptions import NotFoundError, ValidationError 16 | from mock import patch, Mock 17 | from unittest import TestCase 18 | 19 | 20 | MOCK_DESTINATION_DOCKERFILE = '/foo' 21 | 22 | 23 | class TestGenericContainer(TestCase): 24 | def setUp(self): 25 | self.pathconfig = Mock() 26 | self.fs_handler = Mock(pathconfig=self.pathconfig) 27 | self.fs_handler.make_dockerfile = Mock() 28 | self.fs_handler.dockerrun = None 29 | self.container = GenericContainer(self.fs_handler, None, None, None) 30 | 31 | def test_validate_no_dockerfile_or_dockerrun(self): 32 | self.pathconfig.dockerfile_exists = lambda: False 33 | self.pathconfig.dockerrun_exists = lambda: False 34 | 35 | self.assertRaises(NotFoundError, self.container.validate) 36 | 37 | @patch('ebcli.containers.generic_container.dockerrun.validate_dockerrun_v1') 38 | def test_validate_dockerrun_validation_fail(self, validate_dockerrun_v1): 39 | self.pathconfig.dockerfile_exists = lambda: True 40 | validate_dockerrun_v1.side_effect = ValidationError 41 | 42 | self.assertRaises(ValidationError, self.container.validate) 43 | 44 | def test_containerize(self): 45 | self.pathconfig.dockerfile_exists = lambda: True 46 | container = GenericContainer(self.fs_handler, None, None) 47 | container._containerize() 48 | self.fs_handler.make_dockerfile.assert_called_once_with() 49 | -------------------------------------------------------------------------------- /tests/unit/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | -------------------------------------------------------------------------------- /tests/unit/controllers/platform/test_platform.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import unittest 14 | 15 | from ebcli.core.ebcore import EB 16 | 17 | 18 | class Platform(unittest.TestCase): 19 | def test_eb_platform_help(self): 20 | with self.assertRaises(SystemExit): 21 | app = EB(argv=['platform', '--help']) 22 | app.setup() 23 | app.run() 24 | -------------------------------------------------------------------------------- /tests/unit/controllers/platform/test_status.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import mock 14 | import unittest 15 | 16 | from ebcli.controllers.platform import status 17 | from ebcli.objects.platform import PlatformVersion 18 | 19 | 20 | class TestPlatformShowController(unittest.TestCase): 21 | 22 | def setUp(self): 23 | self.platform_show_controller = status.PlatformShowController() 24 | 25 | @mock.patch('ebcli.controllers.platform.status.platform_version_ops.get_latest_custom_platform_version') 26 | def test_get_latest_custom_platform( 27 | self, 28 | get_latest_custom_platform_version_mock, 29 | ): 30 | platform_arn = 'arn:aws:elasticbeanstalk:us-west-2:123123123:platform/custom-platform-1/1.0.0' 31 | platform_version = PlatformVersion(platform_arn=platform_arn) 32 | get_latest_custom_platform_version_mock.return_value = platform_version 33 | expected = (platform_arn, 'custom-platform-1') 34 | 35 | actual = self.platform_show_controller.get_latest_custom_platform(platform_arn) 36 | 37 | get_latest_custom_platform_version_mock.assert_called_once_with(platform_arn) 38 | self.assertEqual(expected, actual) 39 | -------------------------------------------------------------------------------- /tests/unit/controllers/test_codesource.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import mock 15 | import unittest 16 | 17 | from ebcli.core.ebcore import EB 18 | from ebcli.objects.solutionstack import SolutionStack 19 | from ebcli.resources.strings import strings, prompts 20 | 21 | 22 | class TestCodeSource(unittest.TestCase): 23 | solution = SolutionStack('64bit Amazon Linux 2015.03 v2.0.6 running PHP 5.5') 24 | app_name = 'ebcli-intTest-app' 25 | 26 | def setUp(self): 27 | self.patcher_io = mock.patch('ebcli.controllers.codesource.io') 28 | self.mock_io = self.patcher_io.start() 29 | 30 | def tearDown(self): 31 | self.patcher_io.stop() 32 | 33 | @mock.patch('ebcli.controllers.codesource.gitops') 34 | def test_case_insensative_input(self, mock_gitops): 35 | EB.Meta.exit_on_close = False 36 | self.app = EB(argv=['codesource', 37 | 'LoCaL']) 38 | self.app.setup() 39 | self.app.run() 40 | self.app.close() 41 | 42 | self.mock_io.echo.assert_called_once_with(strings['codesource.localmsg']) 43 | 44 | @mock.patch('ebcli.controllers.codesource.gitops') 45 | @mock.patch('ebcli.controllers.codesource.utils.io') 46 | def test_interactive_choices_codecommit(self, mock_utils_io, mock_gitops): 47 | mock_utils_io.prompt.side_effect = [ 48 | '1', # select CodeCommit 49 | ] 50 | 51 | EB.Meta.exit_on_close = False 52 | self.app = EB(argv=['codesource']) 53 | self.app.setup() 54 | self.app.run() 55 | self.app.close() 56 | 57 | self.mock_io.echo.assert_called_with(prompts['codesource.codesourceprompt']) 58 | 59 | io_calls = [mock.call('2)', 'Local'), mock.call('1)', 'CodeCommit')] 60 | mock_utils_io.echo.assert_has_calls(io_calls, any_order=True) 61 | -------------------------------------------------------------------------------- /tests/unit/controllers/test_events.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import os 14 | import shutil 15 | 16 | import mock 17 | import unittest 18 | 19 | from ebcli.core.ebcore import EB 20 | 21 | 22 | class TestDeploy(unittest.TestCase): 23 | def setUp(self): 24 | self.root_dir = os.getcwd() 25 | if not os.path.exists('testDir'): 26 | os.mkdir('testDir') 27 | 28 | os.chdir('testDir') 29 | 30 | def tearDown(self): 31 | os.chdir(self.root_dir) 32 | shutil.rmtree('testDir') 33 | 34 | @mock.patch('ebcli.controllers.events.EventsController.get_app_name') 35 | @mock.patch('ebcli.controllers.events.EventsController.get_env_name') 36 | @mock.patch('ebcli.controllers.events.eventsops.print_events') 37 | def test_events( 38 | self, 39 | print_events_mock, 40 | get_env_name_mock, 41 | get_app_name_mock 42 | ): 43 | get_app_name_mock.return_value = 'my-application' 44 | get_env_name_mock.return_value = 'environment-1' 45 | 46 | app = EB(argv=['events']) 47 | app.setup() 48 | app.run() 49 | 50 | print_events_mock.assert_called_once_with('my-application', 'environment-1', False) 51 | 52 | @mock.patch('ebcli.controllers.events.EventsController.get_app_name') 53 | @mock.patch('ebcli.controllers.events.EventsController.get_env_name') 54 | @mock.patch('ebcli.controllers.events.eventsops.print_events') 55 | def test_events__follow( 56 | self, 57 | print_events_mock, 58 | get_env_name_mock, 59 | get_app_name_mock 60 | ): 61 | get_app_name_mock.return_value = 'my-application' 62 | get_env_name_mock.return_value = 'environment-1' 63 | 64 | app = EB(argv=['events', '-f']) 65 | app.setup() 66 | app.run() 67 | 68 | print_events_mock.assert_called_once_with('my-application', 'environment-1', True) 69 | -------------------------------------------------------------------------------- /tests/unit/controllers/test_lifecycle.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import unittest 15 | import mock 16 | 17 | from ebcli.core.ebcore import EB 18 | 19 | 20 | class TestLifecycle(unittest.TestCase): 21 | app_name = 'foo_app' 22 | 23 | def setUp(self): 24 | self.patcher_lifecycle_ops = mock.patch('ebcli.controllers.lifecycle.lifecycleops') 25 | self.patcher_base_get_app = mock.patch('ebcli.controllers.restore.AbstractBaseController.get_app_name') 26 | self.mock_lifecycle_ops = self.patcher_lifecycle_ops.start() 27 | self.mock_base_get_app = self.patcher_base_get_app.start() 28 | 29 | def tearDown(self): 30 | self.patcher_lifecycle_ops.stop() 31 | self.patcher_base_get_app.stop() 32 | 33 | def test_lifecycle_with_print_flag(self): 34 | self.mock_base_get_app.return_value = self.app_name 35 | 36 | EB.Meta.exit_on_close = False 37 | self.app = EB(argv=['appversion', 'lifecycle', '--print']) 38 | self.app.setup() 39 | self.app.run() 40 | self.app.close() 41 | 42 | self.mock_lifecycle_ops.print_lifecycle_policy.assert_called_with(self.app_name) 43 | 44 | def test_lifecycle_no_args_spawn_interactive(self): 45 | self.mock_base_get_app.return_value = self.app_name 46 | 47 | EB.Meta.exit_on_close = False 48 | self.app = EB(argv=['appversion', 'lifecycle']) 49 | self.app.setup() 50 | self.app.run() 51 | self.app.close() 52 | 53 | self.mock_lifecycle_ops.print_lifecycle_policy.assert_not_called() 54 | self.mock_lifecycle_ops.interactive_update_lifcycle_policy.assert_called_with(self.app_name) 55 | -------------------------------------------------------------------------------- /tests/unit/controllers/test_open.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import os 14 | import shutil 15 | 16 | import mock 17 | import unittest 18 | 19 | from ebcli.core.ebcore import EB 20 | 21 | 22 | class TestOpen(unittest.TestCase): 23 | def setUp(self): 24 | self.root_dir = os.getcwd() 25 | if not os.path.exists('testDir'): 26 | os.mkdir('testDir') 27 | 28 | os.chdir('testDir') 29 | 30 | def tearDown(self): 31 | os.chdir(self.root_dir) 32 | shutil.rmtree('testDir') 33 | 34 | @mock.patch('ebcli.controllers.open.openops.open_app') 35 | @mock.patch('ebcli.controllers.open.OpenController.get_env_name') 36 | @mock.patch('ebcli.controllers.open.OpenController.get_app_name') 37 | def test_health( 38 | self, 39 | get_app_name_mock, 40 | get_env_name_mock, 41 | open_app_mock 42 | ): 43 | get_app_name_mock.return_value = 'my-application' 44 | get_env_name_mock.return_value = 'environment-1' 45 | 46 | app = EB(argv=['open']) 47 | app.setup() 48 | app.run() 49 | 50 | open_app_mock.assert_called_once_with( 51 | 'my-application', 52 | 'environment-1' 53 | ) 54 | -------------------------------------------------------------------------------- /tests/unit/controllers/test_restore.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import unittest 15 | import mock 16 | from datetime import date, timedelta 17 | 18 | from ebcli.core.ebcore import EB 19 | 20 | 21 | class TestRestore(unittest.TestCase): 22 | def setUp(self): 23 | self.patcher_restore_ops = mock.patch('ebcli.controllers.restore.restoreops') 24 | self.patcher_base_controller = mock.patch('ebcli.controllers.restore.AbstractBaseController.get_app_name') 25 | self.mock_restore_ops = self.patcher_restore_ops.start() 26 | self.mock_base_controller = self.patcher_base_controller.start() 27 | 28 | def tearDown(self): 29 | self.patcher_restore_ops.stop() 30 | self.patcher_base_controller.stop() 31 | 32 | def test_restore_with_id(self): 33 | env_id = 'e-1234567890' 34 | 35 | EB.Meta.exit_on_close = False 36 | self.app = EB(argv=['restore', env_id]) 37 | self.app.setup() 38 | self.app.run() 39 | self.app.close() 40 | 41 | self.mock_restore_ops.restore.assert_called_with(env_id, None) 42 | 43 | def test_restore_interactive(self): 44 | env1 = {'EnvironmnetId': "e-1234567890", 'EnvironmentName': "env1", 'VersionLabel': "v1", 45 | 'ApplicationName': "app1", 46 | 'DateUpdated': (date.today() - timedelta(days=10))} 47 | env2 = {'EnvironmnetId': "e-0987654321", 'EnvironmentName': "env2", 'VersionLabel': "v2", 48 | 'ApplicationName': "app2", 49 | 'DateUpdated': (date.today())} 50 | 51 | self.mock_restore_ops.get_restorable_envs.return_value = [env1, env2] 52 | 53 | EB.Meta.exit_on_close = False 54 | self.app = EB(argv=['restore']) 55 | self.app.setup() 56 | self.app.run() 57 | self.app.close() 58 | 59 | self.mock_restore_ops.display_environments.assert_called_with([env1, env2]) 60 | -------------------------------------------------------------------------------- /tests/unit/core/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /tests/unit/core/test_base.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import unittest 14 | 15 | from ebcli.core.ebcore import EB 16 | 17 | 18 | class TestBase(unittest.TestCase): 19 | def test_eb_help(self): 20 | with self.assertRaises(SystemExit): 21 | app = EB(argv=['--help']) 22 | app.setup() 23 | app.run() 24 | -------------------------------------------------------------------------------- /tests/unit/core/test_ebpcore.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import unittest 14 | 15 | from ebcli.core.ebpcore import EBP 16 | 17 | 18 | class TestEBPCore(unittest.TestCase): 19 | def test_ebp_help(self): 20 | with self.assertRaises(SystemExit): 21 | app = EBP(argv=['--help']) 22 | app.setup() 23 | app.run() 24 | -------------------------------------------------------------------------------- /tests/unit/display/test_tables.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import datetime 14 | 15 | from unittest import TestCase 16 | 17 | from ebcli.display.table import Table 18 | 19 | 20 | class TestDisplay(TestCase): 21 | 22 | def test_ascii_string__successfully_wraps_utf8_string(self): 23 | original_utf8_string = u'The m\u0192\u2202\u0153\u2211\u0153\u2211\xae\xae\xae' 24 | wrapped_ascii_string = Table('my_table').ascii_string(original_utf8_string) 25 | 26 | self.assertEqual(original_utf8_string, wrapped_ascii_string) 27 | self.assertEqual(14, len(wrapped_ascii_string)) 28 | 29 | def test_ascii_string__successfully_wraps_ascii_string(self): 30 | original_ascii_string = 'Hello, world!' 31 | wrapped_ascii_string = Table('my_table').ascii_string(original_ascii_string) 32 | 33 | self.assertEqual('Hello, world!', wrapped_ascii_string) 34 | self.assertEqual(13, len(wrapped_ascii_string)) 35 | 36 | def test_ascii_string__successfully_wraps_number(self): 37 | number = 100 38 | wrapped_number = Table('my_table').ascii_string(number) 39 | 40 | self.assertEqual('100', wrapped_number) 41 | self.assertEqual(3, len(wrapped_number)) 42 | 43 | def test_ascii_string__successfully_wraps_datetime(self): 44 | expected_datetime = datetime.datetime(2007, 12, 6, 16, 29, 43, 79043) 45 | wrapped_date_time = Table('my_table').ascii_string(expected_datetime) 46 | 47 | self.assertEqual('2007-12-06 16:29:43.079043', wrapped_date_time) 48 | self.assertEqual(26, len(wrapped_date_time)) 49 | -------------------------------------------------------------------------------- /tests/unit/integration/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | -------------------------------------------------------------------------------- /tests/unit/lib/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. -------------------------------------------------------------------------------- /tests/unit/lib/test_cloudwatch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import mock 14 | import unittest 15 | 16 | from ebcli.lib import cloudwatch 17 | 18 | from .. import mock_responses 19 | 20 | 21 | class TestCloudWatch(unittest.TestCase): 22 | @mock.patch('ebcli.lib.cloudwatch.aws.make_api_call') 23 | def test_get_all_stream_names(self, make_api_call_mock): 24 | make_api_call_mock.return_value = mock_responses.DESCRIBE_LOG_STREAMS_RESPONSE 25 | 26 | self.assertEqual( 27 | [ 28 | 'archive-health-2018-03-26', 29 | 'archive-health-2018-03-27', 30 | 'archive-health-2018-03-28', 31 | ], 32 | cloudwatch.get_all_stream_names('some-log-group') 33 | ) 34 | 35 | @mock.patch('ebcli.lib.cloudwatch.aws.make_api_call') 36 | def test_get_log_events(self, make_api_call_mock): 37 | cloudwatch.get_log_events( 38 | 'environment-health.log', 39 | 'archive-health-2018-03-26', 40 | next_token='1234123412341234', 41 | start_time='4567456745674567', 42 | end_time='7890789078907890', 43 | limit=10 44 | ) 45 | 46 | make_api_call_mock.assert_called_once_with( 47 | 'logs', 48 | 'get_log_events', 49 | endTime='7890789078907890', 50 | limit=10, 51 | logGroupName='environment-health.log', 52 | logStreamName='archive-health-2018-03-26', 53 | nextToken='1234123412341234', 54 | startFromHead=False, 55 | startTime='4567456745674567' 56 | ) 57 | 58 | @mock.patch('ebcli.lib.cloudwatch.aws.make_api_call') 59 | def test_log_group_exists( 60 | self, 61 | make_api_call_mock 62 | ): 63 | make_api_call_mock.return_value = mock_responses.DESCRIBE_LOG_GROUPS_RESPONSE 64 | 65 | self.assertTrue(cloudwatch.log_group_exists('my-log-group-name')) 66 | 67 | @mock.patch('ebcli.lib.cloudwatch.aws.make_api_call') 68 | def test_log_group_exists__log_group_does_not_exist( 69 | self, 70 | make_api_call_mock 71 | ): 72 | make_api_call_mock.return_value = { 73 | 'logGroups': [] 74 | } 75 | 76 | self.assertFalse(cloudwatch.log_group_exists('my-log-group-name')) 77 | -------------------------------------------------------------------------------- /tests/unit/lib/test_iam.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import mock 14 | import unittest 15 | 16 | from ebcli.lib import iam 17 | 18 | from .. import mock_responses 19 | 20 | 21 | class TestIAM(unittest.TestCase): 22 | @mock.patch('ebcli.lib.sns.aws.make_api_call') 23 | def test_account_id( 24 | self, 25 | make_api_call_mock 26 | ): 27 | make_api_call_mock.return_value = mock_responses.GET_USER_RESPONSE 28 | 29 | self.assertEqual('123123123123', iam.account_id()) 30 | 31 | make_api_call_mock.assert_called_once_with('iam', 'get_user') 32 | 33 | @mock.patch('ebcli.lib.iam.get_roles') 34 | def test_role_exists(self, get_roles_mock): 35 | # Mock the get_roles function to return a sample list of roles 36 | mock_roles = [ 37 | {'RoleName': 'aws-elasticbeanstalk-ec2-role'}, 38 | {'RoleName': 'aws-elasticbeanstalk-service-role'} 39 | ] 40 | get_roles_mock.return_value = mock_roles 41 | 42 | # Test for a role that exists 43 | self.assertTrue(iam.role_exists('aws-elasticbeanstalk-ec2-role')) 44 | 45 | # Test for a role that doesn't exist 46 | self.assertFalse(iam.role_exists('SomeRandomIAMRole')) 47 | 48 | self.assertEqual(get_roles_mock.call_count, 2) 49 | -------------------------------------------------------------------------------- /tests/unit/lib/test_kms.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import mock 14 | from pytest_socket import disable_socket, enable_socket 15 | import unittest 16 | 17 | from ebcli.lib import kms 18 | 19 | from .. import mock_responses 20 | 21 | 22 | class TestKMS(unittest.TestCase): 23 | @mock.patch('ebcli.lib.kms.aws.make_api_call') 24 | def test_topics( 25 | self, 26 | make_api_call_mock 27 | ): 28 | make_api_call_mock.return_value = mock_responses.LIST_KEYS_RESPONSE 29 | 30 | self.assertEqual( 31 | [ 32 | '12312312-a783-4f6c-8b8f-502a99545967', 33 | '12312312-c7d9-457a-a90d-943be31f6144', 34 | '12312312-ff32-4398-b352-a470ced64752', 35 | '12312312-36d5-43e6-89ef-c6e82f027d8b', 36 | '12312312-c660-48ee-b5d1-02d6d1ffc275', 37 | '12312312-eec7-49a1-a696-335efc664327', 38 | '12312312-87b5-4fe3-b69f-57494da80071' 39 | ], 40 | kms.keys() 41 | ) 42 | 43 | make_api_call_mock.assert_called_once_with('kms', 'list_keys') 44 | -------------------------------------------------------------------------------- /tests/unit/lib/test_sns.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import mock 14 | import unittest 15 | 16 | from ebcli.lib import sns 17 | 18 | from .. import mock_responses 19 | 20 | 21 | class TestSNS(unittest.TestCase): 22 | @mock.patch('ebcli.lib.sns.aws.make_api_call') 23 | def test_topics( 24 | self, 25 | make_api_call_mock 26 | ): 27 | make_api_call_mock.return_value = mock_responses.LIST_TOPICS_RESPONSE 28 | 29 | self.assertEqual( 30 | [ 31 | 'arn:aws:sns:us-west-2:123123123123:topic_1', 32 | 'arn:aws:sns:us-west-2:123123123123:topic_2', 33 | 'arn:aws:sns:us-west-2:123123123123:topic_3' 34 | ], 35 | sns.topics() 36 | ) 37 | 38 | make_api_call_mock.assert_called_once_with('sns', 'list_topics') 39 | -------------------------------------------------------------------------------- /tests/unit/objects/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. -------------------------------------------------------------------------------- /tests/unit/objects/test_cfn_stack.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import datetime 14 | 15 | from dateutil import tz 16 | import unittest 17 | 18 | from ebcli.objects.cfn_stack import CFNStack 19 | 20 | from .. import mock_responses 21 | 22 | 23 | class TestCFNStack(unittest.TestCase): 24 | def test_json_to_stack_object(self): 25 | cfn_stack = CFNStack.json_to_stack_object(mock_responses.DESCRIBE_STACKS_RESPONSE__2['Stacks'][0]) 26 | 27 | self.assertEqual( 28 | 'arn:aws:cloudformation:us-west-2:123123123123:stack/sam-cfn-stack-2/13bfae60-b196-11e8-b2de-0ad5109330ec', 29 | cfn_stack.stack_id 30 | ) 31 | self.assertEqual('sam-cfn-stack-2', cfn_stack.stack_name) 32 | self.assertEqual('ROLLBACK_COMPLETE', cfn_stack.stack_status) 33 | self.assertIsNone(cfn_stack.stack_status_reason) 34 | self.assertIsNone(cfn_stack.description) 35 | self.assertEqual( 36 | datetime.datetime(2018, 9, 6, 5, 31, 16, 951000, tzinfo=tz.tzutc()), 37 | cfn_stack.creation_time 38 | ) 39 | self.assertEqual( 40 | datetime.datetime(2018, 9, 19, 4, 41, 12, 407000, tzinfo=tz.tzutc()), 41 | cfn_stack.deletion_time 42 | ) 43 | self.assertEqual( 44 | datetime.datetime(2018, 9, 19, 4, 41, 8, 956000, tzinfo=tz.tzutc()), 45 | cfn_stack.last_updated_time 46 | ) 47 | self.assertIsNone(cfn_stack.change_set_id) 48 | -------------------------------------------------------------------------------- /tests/unit/objects/test_environment.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import unittest 14 | 15 | from ebcli.objects.environment import Environment 16 | 17 | 18 | class TestCFNStack(unittest.TestCase): 19 | def test_is_valid_arn(self): 20 | self.assertTrue( 21 | Environment.is_valid_arn( 22 | 'arn:aws:elasticbeanstalk:us-west-2:123123123123:environment/my-application/environment-1' 23 | ) 24 | ) 25 | 26 | def test_is_valid_arn__cn_region(self): 27 | self.assertTrue( 28 | Environment.is_valid_arn( 29 | 'arn:aws-cn:elasticbeanstalk:us-west-2:123123123123:environment/my-application/environment-1' 30 | ) 31 | ) 32 | 33 | def test_is_valid_arn__invalid_arns(self): 34 | invalid_inputs = [ 35 | 'an:aws:elasticbeanstalk:us-west-2:123123123123:environment/my-application/environment-1', 36 | 'arn:ws:elasticbeanstalk:us-west-2:123123123123:environment/my-application/environment-1', 37 | 'arn:aws:elasticbeanstlk:us-west-2:123123123123:environment/my-application/environment-1', 38 | 'arn:aws:elasticbeanstlk:us-west-2:123123123123://', 39 | 'arn:aws:elasticbeanstalk::123123123123:/environment-1', 40 | ] 41 | 42 | for string in invalid_inputs: 43 | self.assertFalse(Environment.is_valid_arn(string)) 44 | -------------------------------------------------------------------------------- /tests/unit/objects/test_log_stream.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import unittest 14 | 15 | from ebcli.objects.log_stream import LogStream 16 | 17 | 18 | class TestLogStream(unittest.TestCase): 19 | def test_log_streams__sorted(self): 20 | 21 | log_streams = [ 22 | { 23 | 'logStreamName': 'archive-health-2018-04-14-B5A100C12FEE498324A234B9ED377644', 24 | 'creationTime': 1523674444444 25 | }, 26 | { 27 | 'logStreamName': 'archive-health-2018-04-16-B5A100C12FEE498324A234B9ED377644', 28 | 'creationTime': 1523678888888 29 | }, 30 | { 31 | 'logStreamName': 'archive-health-2018-04-15-B5A100C12FEE498324A234B9ED377644', 32 | 'creationTime': 1523676666666 33 | } 34 | ] 35 | 36 | self.assertEqual( 37 | [ 38 | 'archive-health-2018-04-14-B5A100C12FEE498324A234B9ED377644', 39 | 'archive-health-2018-04-15-B5A100C12FEE498324A234B9ED377644', 40 | 'archive-health-2018-04-16-B5A100C12FEE498324A234B9ED377644' 41 | ], 42 | [log_stream.name for log_stream in LogStream.log_stream_objects_from_json(log_streams)] 43 | ) 44 | -------------------------------------------------------------------------------- /tests/unit/objects/test_tier.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | import unittest 15 | from ebcli.objects.tier import Tier 16 | from ebcli.objects.exceptions import NotFoundError 17 | 18 | 19 | class TestTier(unittest.TestCase): 20 | 21 | def test_from_raw_string__webserver(self): 22 | for customer_input in [ 23 | 'WebServer', 24 | 'WebServer/Standard' 25 | ]: 26 | tier = Tier.from_raw_string(customer_input) 27 | self.assertEqual('WebServer', tier.name) 28 | self.assertEqual('Standard', tier.type) 29 | self.assertEqual('1.0', tier.version) 30 | 31 | def test_from_raw_string__worker(self): 32 | for customer_input in [ 33 | 'Worker', 34 | 'Worker/SQS/HTTP' 35 | ]: 36 | tier = Tier.from_raw_string(customer_input) 37 | self.assertEqual('Worker', tier.name) 38 | self.assertEqual('SQS/HTTP', tier.type) 39 | self.assertEqual('', tier.version) 40 | 41 | def test_from_raw_string__invalid_input(self): 42 | with self.assertRaises(NotFoundError): 43 | Tier.from_raw_string('invalid/input') 44 | -------------------------------------------------------------------------------- /tests/unit/operations/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | -------------------------------------------------------------------------------- /tests/unit/operations/test_consoleops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import mock 14 | import unittest 15 | 16 | from ebcli.operations import consoleops 17 | 18 | 19 | class TestConsoleOps(unittest.TestCase): 20 | @mock.patch('ebcli.operations.consoleops.utils.is_ssh') 21 | def test_open_console__ssh_shell( 22 | self, 23 | is_ssh_mock 24 | ): 25 | is_ssh_mock.return_value = True 26 | 27 | with self.assertRaises(consoleops.NotSupportedError) as context_manager: 28 | consoleops.open_console('my-application', 'environment-1') 29 | 30 | self.assertEqual( 31 | 'The console command is not supported in an ssh type session', 32 | str(context_manager.exception) 33 | ) 34 | 35 | @mock.patch('ebcli.operations.consoleops.utils.is_ssh') 36 | @mock.patch('ebcli.operations.consoleops.elasticbeanstalk.get_environment') 37 | @mock.patch('ebcli.operations.consoleops.aws.get_region_name') 38 | @mock.patch('ebcli.operations.consoleops.commonops.open_webpage_in_browser') 39 | def test_open_console__non_ssh_shell( 40 | self, 41 | open_webpage_in_browser_mock, 42 | get_region_name_mock, 43 | get_environment_mock, 44 | is_ssh_mock 45 | ): 46 | is_ssh_mock.return_value = False 47 | environment_mock = mock.MagicMock() 48 | environment_mock.id = 'env-id' 49 | get_environment_mock.return_value = environment_mock 50 | get_region_name_mock.return_value = 'us-west-2' 51 | 52 | consoleops.open_console('my-application', 'environment-1') 53 | 54 | open_webpage_in_browser_mock.assert_called_once_with( 55 | 'console.aws.amazon.com/elasticbeanstalk/home?region=us-west-2#/environment/dashboard?applicationName=my-application&environmentId=env-id', 56 | ssl=True 57 | ) 58 | -------------------------------------------------------------------------------- /tests/unit/operations/test_spotops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import os 14 | import shutil 15 | import io 16 | 17 | import unittest 18 | import mock 19 | 20 | from ebcli.operations import spotops 21 | 22 | 23 | class TestSpotOps(unittest.TestCase): 24 | 25 | @mock.patch('ebcli.operations.spotops.prompt_for_instance_types') 26 | def test_get_spot_instance_types_from_customer__success( 27 | self, 28 | prompt_for_instance_types_mock, 29 | ): 30 | enable_spot=True 31 | interactive=True 32 | prompt_for_instance_types_mock.return_value='t2.micro, t3.micro' 33 | self.assertEqual('t2.micro, t3.micro', spotops.get_spot_instance_types_from_customer(interactive, enable_spot)) 34 | 35 | @mock.patch('ebcli.operations.spotops.prompt_for_instance_types') 36 | def test_get_spot_instance_types_from_customer__test_for_prompting( 37 | self, 38 | prompt_for_instance_types_mock, 39 | ): 40 | prompt_for_instance_types_mock.return_value='' 41 | self.assertEqual( 42 | '', 43 | spotops.get_spot_instance_types_from_customer( 44 | interactive=True, 45 | enable_spot=True, 46 | ) 47 | ) 48 | prompt_for_instance_types_mock.assert_called_once_with() 49 | 50 | @mock.patch('ebcli.operations.spotops.prompt_for_instance_types') 51 | def test_get_spot_instance_types_from_customer__enable_spot_not_passed( 52 | self, 53 | prompt_for_instance_types_mock, 54 | ): 55 | enable_spot=None 56 | interactive=True 57 | prompt_for_instance_types_mock.assert_not_called() 58 | self.assertFalse(spotops.get_spot_instance_types_from_customer(interactive, enable_spot)) 59 | 60 | @mock.patch('ebcli.operations.spotops.prompt_for_instance_types') 61 | def test_get_spot_instance_types_from_customer__interactive_is_disabled( 62 | self, 63 | prompt_for_instance_types_mock, 64 | ): 65 | enable_spot=False 66 | interactive=False 67 | prompt_for_instance_types_mock.assert_not_called() 68 | self.assertFalse(spotops.get_spot_instance_types_from_customer(interactive, enable_spot)) 69 | -------------------------------------------------------------------------------- /tests/unit/test_helper.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You 4 | # may not use this file except in compliance with the License. A copy of 5 | # the License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is 10 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | # ANY KIND, either express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | import os 14 | 15 | 16 | class EnvVarSubstitutor(object): 17 | def __init__(self, variable, new_value): 18 | self.variable = variable 19 | self.original_value = os.environ.get(variable) 20 | 21 | if new_value is not None: 22 | os.environ[variable] = new_value 23 | elif new_value is None and self.original_value is not None: 24 | del os.environ[variable] 25 | 26 | def __enter__(self): 27 | pass 28 | 29 | def __exit__(self, exc_type, exc_val, exc_tb): 30 | if self.original_value is not None: 31 | os.environ[self.variable] = self.original_value 32 | elif self.original_value is None and os.environ.get(self.variable): 33 | del os.environ[self.variable] 34 | --------------------------------------------------------------------------------