├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .vscode └── launch.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md └── src ├── aci_docs_sample.py └── requirements.txt /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | > Please provide us with the following information: 5 | > --------------------------------------------------------------- 6 | 7 | ### This issue is for a: (mark with an `x`) 8 | ``` 9 | - [ ] bug report -> please search issues before submitting 10 | - [ ] feature request 11 | - [ ] documentation issue or request 12 | - [ ] regression (a behavior that used to work and stopped in a new release) 13 | ``` 14 | 15 | ### Minimal steps to reproduce 16 | > 17 | 18 | ### Any log messages given by the failure 19 | > 20 | 21 | ### Expected/desired behavior 22 | > 23 | 24 | ### OS and Version? 25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) 26 | 27 | ### Versions 28 | > 29 | 30 | ### Mention any other details that might be useful 31 | 32 | > --------------------------------------------------------------- 33 | > Thanks! We'll be in touch soon. 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | * ... 4 | 5 | ## Does this introduce a breaking change? 6 | 7 | ``` 8 | [ ] Yes 9 | [ ] No 10 | ``` 11 | 12 | ## Pull Request Type 13 | What kind of change does this Pull Request introduce? 14 | 15 | 16 | ``` 17 | [ ] Bugfix 18 | [ ] Feature 19 | [ ] Code style update (formatting, local variables) 20 | [ ] Refactoring (no functional changes, no api changes) 21 | [ ] Documentation content changes 22 | [ ] Other... Please describe: 23 | ``` 24 | 25 | ## How to Test 26 | * Get the code 27 | 28 | ``` 29 | git clone [repo-address] 30 | cd [repo-name] 31 | git checkout [branch-name] 32 | npm install 33 | ``` 34 | 35 | * Test the code 36 | 37 | ``` 38 | ``` 39 | 40 | ## What to Check 41 | Verify that the following are valid 42 | * ... 43 | 44 | ## Other Information 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python: Current File", 9 | "type": "python", 10 | "request": "launch", 11 | "program": "${file}" 12 | }, 13 | { 14 | "name": "Python: Attach", 15 | "type": "python", 16 | "request": "attach", 17 | "localRoot": "${workspaceFolder}", 18 | "remoteRoot": "${workspaceFolder}", 19 | "port": 3000, 20 | "secret": "my_secret", 21 | "host": "localhost" 22 | }, 23 | { 24 | "name": "Python: Terminal (integrated)", 25 | "type": "python", 26 | "request": "launch", 27 | "program": "${file}", 28 | "console": "integratedTerminal" 29 | }, 30 | { 31 | "name": "Python: Terminal (external)", 32 | "type": "python", 33 | "request": "launch", 34 | "program": "${file}", 35 | "console": "externalTerminal" 36 | }, 37 | { 38 | "name": "Python: Django", 39 | "type": "python", 40 | "request": "launch", 41 | "program": "${workspaceFolder}/manage.py", 42 | "args": [ 43 | "runserver", 44 | "--noreload", 45 | "--nothreading" 46 | ], 47 | "debugOptions": [ 48 | "RedirectOutput", 49 | "Django" 50 | ] 51 | }, 52 | { 53 | "name": "Python: Flask (0.11.x or later)", 54 | "type": "python", 55 | "request": "launch", 56 | "module": "flask", 57 | "env": { 58 | "FLASK_APP": "${workspaceFolder}/app.py" 59 | }, 60 | "args": [ 61 | "run", 62 | "--no-debugger", 63 | "--no-reload" 64 | ] 65 | }, 66 | { 67 | "name": "Python: Module", 68 | "type": "python", 69 | "request": "launch", 70 | "module": "module.name" 71 | }, 72 | { 73 | "name": "Python: Pyramid", 74 | "type": "python", 75 | "request": "launch", 76 | "args": [ 77 | "${workspaceFolder}/development.ini" 78 | ], 79 | "debugOptions": [ 80 | "RedirectOutput", 81 | "Pyramid" 82 | ] 83 | }, 84 | { 85 | "name": "Python: Watson", 86 | "type": "python", 87 | "request": "launch", 88 | "program": "${workspaceFolder}/console.py", 89 | "args": [ 90 | "dev", 91 | "runserver", 92 | "--noreload=True" 93 | ] 94 | }, 95 | { 96 | "name": "Python: All debug Options", 97 | "type": "python", 98 | "request": "launch", 99 | "pythonPath": "${config:python.pythonPath}", 100 | "program": "${file}", 101 | "module": "module.name", 102 | "env": { 103 | "VAR1": "1", 104 | "VAR2": "2" 105 | }, 106 | "envFile": "${workspaceFolder}/.env", 107 | "args": [ 108 | "arg1", 109 | "arg2" 110 | ], 111 | "debugOptions": [ 112 | "RedirectOutput" 113 | ] 114 | } 115 | ] 116 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [project-title] Changelog 2 | 3 | 4 | # x.y.z (yyyy-mm-dd) 5 | 6 | *Features* 7 | * ... 8 | 9 | *Bug Fixes* 10 | * ... 11 | 12 | *Breaking Changes* 13 | * ... 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to [project-title] 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 5 | the rights to use your contribution. For details, visit https://cla.microsoft.com. 6 | 7 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide 8 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions 9 | provided by the bot. You will only need to do this once across all repos using our CLA. 10 | 11 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 12 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 13 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 14 | 15 | - [Code of Conduct](#coc) 16 | - [Issues and Bugs](#issue) 17 | - [Feature Requests](#feature) 18 | - [Submission Guidelines](#submit) 19 | 20 | ## Code of Conduct 21 | Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 22 | 23 | ## Found an Issue? 24 | If you find a bug in the source code or a mistake in the documentation, you can help us by 25 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can 26 | [submit a Pull Request](#submit-pr) with a fix. 27 | 28 | ## Want a Feature? 29 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub 30 | Repository. If you would like to *implement* a new feature, please submit an issue with 31 | a proposal for your work first, to be sure that we can use it. 32 | 33 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). 34 | 35 | ## Submission Guidelines 36 | 37 | ### Submitting an Issue 38 | Before you submit an issue, search the archive, maybe your question was already answered. 39 | 40 | If your issue appears to be a bug, and hasn't been reported, open a new issue. 41 | Help us to maximize the effort we can spend fixing issues and adding new 42 | features, by not reporting duplicate issues. Providing the following information will increase the 43 | chances of your issue being dealt with quickly: 44 | 45 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps 46 | * **Version** - what version is affected (e.g. 0.1.2) 47 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you 48 | * **Browsers and Operating System** - is this a problem with all browsers? 49 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps 50 | * **Related Issues** - has a similar issue been reported before? 51 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be 52 | causing the problem (line of code or commit) 53 | 54 | You can file new issues by providing the above information at the corresponding repository's issues link: https://github.com/[organization-name]/[repository-name]/issues/new]. 55 | 56 | ### Submitting a Pull Request (PR) 57 | Before you submit your Pull Request (PR) consider the following guidelines: 58 | 59 | * Search the repository (https://github.com/[organization-name]/[repository-name]/pulls) for an open or closed PR 60 | that relates to your submission. You don't want to duplicate effort. 61 | 62 | * Make your changes in a new git fork: 63 | 64 | * Commit your changes using a descriptive commit message 65 | * Push your fork to GitHub: 66 | * In GitHub, create a pull request 67 | * If we suggest changes then: 68 | * Make the required updates. 69 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request): 70 | 71 | ```shell 72 | git rebase master -i 73 | git push -f 74 | ``` 75 | 76 | That's it! Thank you for your contribution! 77 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | languages: 4 | - python 5 | products: 6 | - azure 7 | description: "This sample application demonstrates several common Azure Container Instances operations in Python using the Azure libraries for Python." 8 | urlFragment: aci-docs-sample-python 9 | --- 10 | 11 | # Azure Container Instances Python code samples for documentation 12 | 13 | This sample application demonstrates several common [Azure Container Instances](https://docs.microsoft.com/azure/container-instances/) operations in Python using the [Azure libraries for Python](https://docs.microsoft.com/python/azure/python-sdk-azure-overview). 14 | 15 | The code in this project is ingested into one or more articles on [docs.microsoft.com](https://docs.microsoft.com). Modifying the code in the sample source may impact the rendering of code snippets on [docs.microsoft.com](https://docs.microsoft.com). 16 | 17 | This sample has been tested as functional on Python versions 2.7.15rc1 and 3.6.5. 18 | 19 | ## Features 20 | 21 | The code in this sample project demonstrates the following operations: 22 | 23 | * Authenticate with Azure 24 | * Create resource group 25 | * Create single- and multi-container container groups 26 | * Expose application container to internet with public DNS name 27 | * Multi-container group includes both application and sidecar containers 28 | * Run a task-based container with custom command line and environment variables 29 | * List container groups in resource group 30 | * Get and print container group details 31 | * Delete container groups 32 | * Delete resource group 33 | 34 | ## Getting Started 35 | 36 | ### Prerequisites 37 | 38 | * [Azure subscription](https://azure.microsoft.com/free) 39 | * [Python](https://docs.microsoft.com/python/azure/python-sdk-azure-install#where-to-get-python) 40 | * [pip](https://pypi.org/project/pip/) 41 | * [virtualenv](https://virtualenv.pypa.io) (optional) 42 | 43 | ### Run the sample 44 | 45 | 1. Optional but recommended, use [virtualenv](https://virtualenv.pypa.io/en/stable/) to create and activate a virtual environment for the project: 46 | ``` 47 | virtualenv ~/venv/aci-docs-sample-python 48 | source ~/venv/aci-docs-sample-python/bin/activate 49 | ``` 50 | 51 | 1. Use the [Azure CLI](https://docs.microsoft.com/cli/azure) (or [Cloud Shell](https://shell.azure.com/)) to generate an Azure credentials file ([more authentication details](https://docs.microsoft.com/python/azure/python-sdk-azure-authenticate?view=azure-python#mgmt-auth-file)) 52 | 53 | `az ad sp create-for-rbac --sdk-auth > my.azureauth` 54 | 55 | 1. Set environment variable `AZURE_AUTH_LOCATION` to the full path of the credentials file 56 | 1. `git clone https://github.com/Azure-Samples/aci-docs-sample-python` 57 | 1. `cd aci-docs-sample-python` 58 | 1. `pip install -r src/requirements.txt` 59 | 1. `python src/aci_docs_sample.py` 60 | 61 | ...sample runs... 62 | 63 | 1. Exit virtualenv (if using a virtual environment): `deactivate` 64 | 65 | ## Resources 66 | 67 | * [Azure SDK for Python](https://github.com/Azure/azure-sdk-for-python) (GitHub) 68 | * [More Azure Container Instances code samples](https://azure.microsoft.com/resources/samples/?sort=0&term=aci) 69 | -------------------------------------------------------------------------------- /src/aci_docs_sample.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | import time 4 | import sys 5 | from os import getenv 6 | from azure.common.client_factory import get_client_from_auth_file 7 | from azure.mgmt.resource import ResourceManagementClient 8 | from azure.mgmt.containerinstance import ContainerInstanceManagementClient 9 | from azure.mgmt.containerinstance.models import (ContainerGroup, 10 | Container, 11 | ContainerGroupNetworkProtocol, 12 | ContainerGroupRestartPolicy, 13 | ContainerPort, 14 | EnvironmentVariable, 15 | IpAddress, 16 | Port, 17 | ResourceRequests, 18 | ResourceRequirements, 19 | OperatingSystemTypes) 20 | 21 | # Support input() on Python 2.x 22 | try: 23 | input = raw_input 24 | except NameError: 25 | pass 26 | 27 | 28 | def main(): 29 | """Main entry point for the application. 30 | """ 31 | 32 | azure_region = 'eastus' 33 | resource_group_name = 'aci-rg-' + ''.join(random.choice(string.digits) 34 | for _ in range(6)) 35 | container_group_name = 'aci-' + ''.join(random.choice(string.digits) 36 | for _ in range(6)) 37 | 38 | multi_container_group_name = container_group_name + "-multi" 39 | task_container_group_name = container_group_name + "-task" 40 | 41 | container_image_app = "microsoft/aci-helloworld" 42 | container_image_sidecar = "microsoft/aci-tutorial-sidecar" 43 | container_image_taskbased = "microsoft/aci-wordcount" 44 | 45 | # Authenticate the management clients with Azure. 46 | # Set the AZURE_AUTH_LOCATION environment variable to the full path to an 47 | # auth file. Generate an auth file with the Azure CLI or Cloud Shell: 48 | # az ad sp create-for-rbac --sdk-auth > my.azureauth 49 | auth_file_path = getenv('AZURE_AUTH_LOCATION', None) 50 | if auth_file_path is not None: 51 | print("Authenticating with Azure using credentials in file at {0}" 52 | .format(auth_file_path)) 53 | 54 | aciclient = get_client_from_auth_file( 55 | ContainerInstanceManagementClient) 56 | resclient = get_client_from_auth_file(ResourceManagementClient) 57 | else: 58 | print("\nFailed to authenticate to Azure. Have you set the" 59 | " AZURE_AUTH_LOCATION environment variable?\n") 60 | 61 | # Create (and then get) a resource group into which the container groups 62 | # are to be created 63 | print("Creating resource group '{0}'...".format(resource_group_name)) 64 | resclient.resource_groups.create_or_update(resource_group_name, 65 | {'location': azure_region}) 66 | resource_group = resclient.resource_groups.get(resource_group_name) 67 | 68 | # Demonstrate various container group operations 69 | create_container_group(aciclient, resource_group, container_group_name, 70 | container_image_app) 71 | create_container_group_multi(aciclient, resource_group, 72 | multi_container_group_name, 73 | container_image_app, 74 | container_image_sidecar) 75 | run_task_based_container(aciclient, resource_group, 76 | task_container_group_name, 77 | container_image_taskbased, 78 | None) 79 | list_container_groups(aciclient, resource_group) 80 | print_container_group_details(aciclient, 81 | resource_group, 82 | multi_container_group_name) 83 | 84 | # Clean up resources 85 | input("Press ENTER to delete all resources created by this sample: ") 86 | aciclient.container_groups.delete(resource_group_name, 87 | container_group_name) 88 | aciclient.container_groups.delete(resource_group_name, 89 | multi_container_group_name) 90 | aciclient.container_groups.delete(resource_group_name, 91 | task_container_group_name) 92 | resclient.resource_groups.delete(resource_group_name) 93 | 94 | 95 | def create_container_group(aci_client, resource_group, 96 | container_group_name, container_image_name): 97 | """Creates a container group with a single container. 98 | 99 | Arguments: 100 | aci_client {azure.mgmt.containerinstance.ContainerInstanceManagementClient} 101 | -- An authenticated container instance management client. 102 | resource_group {azure.mgmt.resource.resources.models.ResourceGroup} 103 | -- The resource group in which to create the container group. 104 | container_group_name {str} 105 | -- The name of the container group to create. 106 | container_image_name {str} 107 | -- The container image name and tag, for example: 108 | microsoft\aci-helloworld:latest 109 | """ 110 | print("Creating container group '{0}'...".format(container_group_name)) 111 | 112 | # Configure the container 113 | container_resource_requests = ResourceRequests(memory_in_gb=1, cpu=1.0) 114 | container_resource_requirements = ResourceRequirements( 115 | requests=container_resource_requests) 116 | container = Container(name=container_group_name, 117 | image=container_image_name, 118 | resources=container_resource_requirements, 119 | ports=[ContainerPort(port=80)]) 120 | 121 | # Configure the container group 122 | ports = [Port(protocol=ContainerGroupNetworkProtocol.tcp, port=80)] 123 | group_ip_address = IpAddress(ports=ports, 124 | dns_name_label=container_group_name, 125 | type="Public") 126 | group = ContainerGroup(location=resource_group.location, 127 | containers=[container], 128 | os_type=OperatingSystemTypes.linux, 129 | ip_address=group_ip_address) 130 | 131 | # Create the container group 132 | aci_client.container_groups.create_or_update(resource_group.name, 133 | container_group_name, 134 | group) 135 | 136 | # Get the created container group 137 | container_group = aci_client.container_groups.get(resource_group.name, 138 | container_group_name) 139 | 140 | print("Once DNS has propagated, container group '{0}' will be reachable at" 141 | " http://{1}".format(container_group_name, 142 | container_group.ip_address.fqdn)) 143 | 144 | 145 | def create_container_group_multi(aci_client, resource_group, 146 | container_group_name, 147 | container_image_1, container_image_2): 148 | """Creates a container group with two containers in the specified 149 | resource group. 150 | 151 | Arguments: 152 | aci_client {azure.mgmt.containerinstance.ContainerInstanceManagementClient} 153 | -- An authenticated container instance management client. 154 | resource_group {azure.mgmt.resource.resources.models.ResourceGroup} 155 | -- The resource group in which to create the container group. 156 | container_group_name {str} 157 | -- The name of the container group to create. 158 | container_image_1 {str} 159 | -- The first container image name and tag, for example: 160 | microsoft\aci-helloworld:latest 161 | container_image_2 {str} 162 | -- The second container image name and tag, for example: 163 | microsoft\aci-tutorial-sidecar:latest 164 | """ 165 | print("Creating container group '{0}'...".format(container_group_name)) 166 | 167 | # Configure the containers 168 | container_resource_requests = ResourceRequests(memory_in_gb=2, cpu=1.0) 169 | container_resource_requirements = ResourceRequirements( 170 | requests=container_resource_requests) 171 | 172 | container_1 = Container(name=container_group_name + '-1', 173 | image=container_image_1, 174 | resources=container_resource_requirements, 175 | ports=[ContainerPort(port=80)]) 176 | 177 | container_2 = Container(name=container_group_name + '-2', 178 | image=container_image_2, 179 | resources=container_resource_requirements) 180 | 181 | # Configure the container group 182 | ports = [Port(protocol=ContainerGroupNetworkProtocol.tcp, port=80)] 183 | group_ip_address = IpAddress( 184 | ports=ports, dns_name_label=container_group_name, type='Public') 185 | group = ContainerGroup(location=resource_group.location, 186 | containers=[container_1, container_2], 187 | os_type=OperatingSystemTypes.linux, 188 | ip_address=group_ip_address) 189 | 190 | # Create the container group 191 | aci_client.container_groups.create_or_update(resource_group.name, 192 | container_group_name, group) 193 | 194 | # Get the created container group 195 | container_group = aci_client.container_groups.get(resource_group.name, 196 | container_group_name) 197 | 198 | print("Once DNS has propagated, container group '{0}' will be reachable at" 199 | " http://{1}".format(container_group_name, 200 | container_group.ip_address.fqdn)) 201 | 202 | 203 | def run_task_based_container(aci_client, resource_group, container_group_name, 204 | container_image_name, start_command_line=None): 205 | """Creates a container group with a single task-based container who's 206 | restart policy is 'Never'. If specified, the container runs a custom 207 | command line at startup. 208 | 209 | Arguments: 210 | aci_client {azure.mgmt.containerinstance.ContainerInstanceManagementClient} 211 | -- An authenticated container instance management client. 212 | resource_group {azure.mgmt.resource.resources.models.ResourceGroup} 213 | -- The resource group in which to create the container group. 214 | container_group_name {str} 215 | -- The name of the container group to create. 216 | container_image_name {str} 217 | -- The container image name and tag, for example: 218 | microsoft\aci-helloworld:latest 219 | start_command_line {str} 220 | -- The command line that should be executed when the 221 | container starts. This value can be None. 222 | """ 223 | # If a start command wasn't specified, use a default 224 | if start_command_line is None: 225 | start_command_line = "python wordcount.py http://shakespeare.mit.edu/romeo_juliet/full.html" 226 | 227 | # Configure some environment variables in the container which the 228 | # wordcount.py or other script can read to modify its behavior. 229 | env_var_1 = EnvironmentVariable(name='NumWords', value='5') 230 | env_var_2 = EnvironmentVariable(name='MinLength', value='8') 231 | 232 | print("Creating container group '{0}' with start command '{1}'" 233 | .format(container_group_name, start_command_line)) 234 | 235 | # Configure the container 236 | container_resource_requests = ResourceRequests(memory_in_gb=1, cpu=1.0) 237 | container_resource_requirements = ResourceRequirements( 238 | requests=container_resource_requests) 239 | container = Container(name=container_group_name, 240 | image=container_image_name, 241 | resources=container_resource_requirements, 242 | command=start_command_line.split(), 243 | environment_variables=[env_var_1, env_var_2]) 244 | 245 | # Configure the container group 246 | group = ContainerGroup(location=resource_group.location, 247 | containers=[container], 248 | os_type=OperatingSystemTypes.linux, 249 | restart_policy=ContainerGroupRestartPolicy.never) 250 | 251 | # Create the container group 252 | result = aci_client.container_groups.create_or_update(resource_group.name, 253 | container_group_name, 254 | group) 255 | 256 | # Wait for the container create operation to complete. The operation is 257 | # "done" when the container group provisioning state is one of: 258 | # Succeeded, Canceled, Failed 259 | while result.done() is False: 260 | sys.stdout.write('.') 261 | time.sleep(1) 262 | 263 | # Get the provisioning state of the container group. 264 | container_group = aci_client.container_groups.get(resource_group.name, 265 | container_group_name) 266 | if str(container_group.provisioning_state).lower() == 'succeeded': 267 | print("\nCreation of container group '{}' succeeded." 268 | .format(container_group_name)) 269 | else: 270 | print("\nCreation of container group '{}' failed. Provisioning state" 271 | "is: {}".format(container_group_name, 272 | container_group.provisioning_state)) 273 | 274 | # Get the logs for the container 275 | logs = aci_client.container.list_logs(resource_group.name, 276 | container_group_name, 277 | container.name) 278 | 279 | print("Logs for container '{0}':".format(container_group_name)) 280 | print("{0}".format(logs.content)) 281 | 282 | 283 | def list_container_groups(aci_client, resource_group): 284 | """Lists the container groups in the specified resource group. 285 | 286 | Arguments: 287 | aci_client {azure.mgmt.containerinstance.ContainerInstanceManagementClient} 288 | -- An authenticated container instance management client. 289 | resource_group {azure.mgmt.resource.resources.models.ResourceGroup} 290 | -- The resource group containing the container group(s). 291 | """ 292 | print("Listing container groups in resource group '{0}'...".format( 293 | resource_group.name)) 294 | 295 | container_groups = aci_client.container_groups.list_by_resource_group( 296 | resource_group.name) 297 | 298 | for container_group in container_groups: 299 | print(" {0}".format(container_group.name)) 300 | 301 | 302 | def print_container_group_details(aci_client, resource_group, container_group_name): 303 | """Gets the specified container group and then prints a few of its properties and their values. 304 | 305 | Arguments: 306 | aci_client {azure.mgmt.containerinstance.ContainerInstanceManagementClient} 307 | -- An authenticated container instance management client. 308 | resource_group {azure.mgmt.resource.resources.models.ResourceGroup} 309 | -- The name of the resource group containing the container 310 | group. 311 | container_group_name {str} 312 | -- The name of the container group whose details should be 313 | printed. 314 | """ 315 | print("Getting container group details for container group '{0}'..." 316 | .format(container_group_name)) 317 | 318 | container_group = aci_client.container_groups.get(resource_group.name, 319 | container_group_name) 320 | print("------------------------") 321 | print("Name: {0}".format(container_group.name)) 322 | print("State: {0}".format(container_group.provisioning_state)) 323 | print("FQDN: {0}".format(container_group.ip_address.fqdn)) 324 | print("IP: {0}".format(container_group.ip_address.ip)) 325 | print("Region: {0}".format(container_group.location)) 326 | print("Containers:") 327 | for container in container_group.containers: 328 | print(" Name: {0}".format(container.name)) 329 | print(" Image: {0}".format(container.image)) 330 | print(" State: {0}".format( 331 | container.instance_view.current_state.state)) 332 | print(" ----------") 333 | 334 | 335 | if __name__ == "__main__": 336 | main() 337 | -------------------------------------------------------------------------------- /src/requirements.txt: -------------------------------------------------------------------------------- 1 | azure-common==1.1.18 2 | azure-mgmt-containerinstance==1.4.1 3 | azure-mgmt-resource==2.1.0 --------------------------------------------------------------------------------