Skip to content

Commit 0e39682

Browse files
chrissmillermsyyc
andauthored
Add Azure DevCenter Package (#26696)
* Add generated code * Add samples * Add test coverage * Recordings * Add defaults for test env variables * autorest, cspell, and shared reqs * Add readme items * Update to use testproxy * Work around issue * Update CI * Fix up tests to use kwargs * Add extra sanitizers, fix readme casing * Rerun with fresh container image * Whitelist pylint failure * Unblock * Update sdk/devcenter/azure-developer-devcenter/README.md Co-authored-by: Yuchao Yan <[email protected]> * Update samples/readme * Update shared_requirements.txt Co-authored-by: Yuchao Yan <[email protected]> Co-authored-by: Yuchao Yan <[email protected]>
1 parent 41c082c commit 0e39682

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+15859
-2
lines changed

.vscode/cspell.json

+10
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,16 @@
11171117
"mrenclave",
11181118
"infile"
11191119
]
1120+
},
1121+
{
1122+
"filename": "sdk/devcenter/azure-developer-devcenter/azure/developer/devcenter/*.py",
1123+
"words": [
1124+
"Nify",
1125+
"ctxt",
1126+
"unflattened",
1127+
"deseralize",
1128+
"wday"
1129+
]
11201130
}
11211131
],
11221132
"allowCompoundWords": true

eng/tox/allowed_pylint_failures.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,6 @@
5858
"azure-purview-administration",
5959
"azure-messaging-nspkg",
6060
"azure-agrifood-farming",
61-
"azure-developer-loadtesting"
61+
"azure-developer-loadtesting",
62+
"azure-developer-devcenter"
6263
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Release History
2+
3+
## 1.0.0b1 (2022-11-01)
4+
5+
- Initial version for the DevCenter service
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Copyright (c) Microsoft Corporation.
2+
3+
MIT License
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.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
include *.md
2+
include LICENSE
3+
include azure/developer/devcenter/py.typed
4+
recursive-include tests *.py
5+
recursive-include samples *.py *.md
6+
include azure/__init__.py
7+
include azure/developer/__init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
2+
# Azure DevCenter Service client library for Python
3+
The Azure DevCenter package provides access to manage resources for Microsoft Dev Box and Azure Deployment Environments. This SDK enables managing developer machines and environments in Azure.
4+
5+
Use the package for Azure DevCenter to:
6+
> Create, access, manage, and delete Dev Box resources
7+
> Create, deploy, manage, and delete Environment resources
8+
9+
## Getting started
10+
11+
### Installating the package
12+
13+
```bash
14+
python -m pip install azure-developer-devcenter
15+
```
16+
17+
#### Prequisites
18+
19+
- Python 3.7 or later is required to use this package.
20+
- You need an [Azure subscription][azure_sub] to use this package.
21+
- You must have [configured](https://learn.microsoft.com/azure/dev-box/quickstart-configure-dev-box-service) a DevCenter, Project, Network Connection, Dev Box Definition, and Pool before you can create Dev Boxes
22+
- You must have [configured](https://learn.microsoft.com/azure/deployment-environments/) a DevCenter, Project, Catalog, and Environment Type before you can create Environments
23+
24+
#### Create with an Azure Active Directory Credential
25+
To use an [Azure Active Directory (AAD) token credential][authenticate_with_token],
26+
provide an instance of the desired credential type obtained from the
27+
[azure-identity][azure_identity_credentials] library.
28+
29+
To authenticate with AAD, you must first [pip][pip] install [`azure-identity`][azure_identity_pip]
30+
31+
After setup, you can choose which type of [credential][azure_identity_credentials] from azure.identity to use.
32+
As an example, [DefaultAzureCredential][default_azure_credential] can be used to authenticate the client:
33+
34+
Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables:
35+
`AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_SECRET`
36+
37+
Use the returned token credential to authenticate the client:
38+
39+
```python
40+
>>> import os
41+
>>> from azure.developer.devcenter import DevCenterClient
42+
>>> from azure.identity import DefaultAzureCredential
43+
>>> tenant_id = os.environ['AZURE_TENANT_ID']
44+
>>> client = DevCenterClient(tenant_id=tenant_id, dev_center="my_dev_center", credential=DefaultAzureCredential())
45+
```
46+
47+
## Examples
48+
49+
### Dev Box Management
50+
```python
51+
>>> import os
52+
>>> from azure.developer.devcenter import DevCenterClient
53+
>>> from azure.identity import DefaultAzureCredential
54+
>>> from azure.core.exceptions import HttpResponseError
55+
>>> tenant_id = os.environ['AZURE_TENANT_ID']
56+
>>> client = DevCenterClient(tenant_id=tenant_id, dev_center="my_dev_center", credential=DefaultAzureCredential())
57+
>>> try:
58+
# Fetch control plane resource dependencies
59+
projects = list(client.dev_center.list_projects(top=1))
60+
target_project_name = projects[0]['name']
61+
62+
pools = list(client.dev_boxes.list_pools(target_project_name, top=1))
63+
target_pool_name = pools[0]['name']
64+
65+
# Stand up a new dev box
66+
create_response = client.dev_boxes.begin_create_dev_box(target_project_name, "Test_DevBox", {"poolName": target_pool_name})
67+
devbox_result = create_response.result()
68+
69+
LOG.info(f"Provisioned dev box with status {devbox_result['provisioningState']}.")
70+
71+
# Connect to the provisioned dev box
72+
remote_connection_response = client.dev_boxes.get_remote_connection(target_project_name, "Test_DevBox")
73+
LOG.info(f"Connect to the dev box using web URL {remote_connection_response['webUrl']}")
74+
75+
# Tear down the dev box when finished
76+
delete_response = client.dev_boxes.begin_delete_dev_box(target_project_name, "Test_DevBox")
77+
delete_response.wait()
78+
LOG.info("Deleted dev box successfully.")
79+
except HttpResponseError as e:
80+
print('service responds error: {}'.format(e.response.json()))
81+
82+
```
83+
84+
### Environment Management
85+
```python
86+
>>> import os
87+
>>> from azure.developer.devcenter import DevCenterClient
88+
>>> from azure.identity import DefaultAzureCredential
89+
>>> from azure.core.exceptions import HttpResponseError
90+
>>> tenant_id = os.environ['AZURE_TENANT_ID']
91+
>>> client = DevCenterClient(tenant_id=tenant_id, dev_center="my_dev_center", credential=DefaultAzureCredential())
92+
>>> try:
93+
# Fetch control plane resource dependencies
94+
target_project_name = list(client.dev_center.list_projects(top=1))[0]['name']
95+
target_catalog_item_name = list(client.environments.list_catalog_items(target_project_name, top=1))[0]['name']
96+
target_environment_type_name = list(client.environments.list_environment_types(target_project_name, top=1))[0]['name']
97+
98+
# Stand up a new environment
99+
create_response = client.environments.begin_create_environment(target_project_name,
100+
"Dev_Environment",
101+
{"catalogItemName": target_catalog_item_name, "environmentType": target_environment_type_name})
102+
environment_result = create_response.result()
103+
104+
LOG.info(f"Provisioned environment with status {environment_result['provisioningState']}.")
105+
106+
# Fetch deployment artifacts
107+
artifact_response = client.environments.list_artifacts_by_environment(target_project_name, "Dev_Environment")
108+
109+
for artifact in artifact_response:
110+
LOG.info(artifact)
111+
112+
# Tear down the environment when finished
113+
delete_response = client.environments.begin_delete_environment(target_project_name, "Dev_Environment")
114+
delete_response.wait()
115+
LOG.info("Completed deletion for the environment.")
116+
except HttpResponseError as e:
117+
print('service responds error: {}'.format(e.response.json()))
118+
119+
```
120+
## Key concepts
121+
Dev Boxes refer to managed developer machines running in Azure. Dev Boxes are provisioned in Pools, which define the network and image used for a Dev Box.
122+
123+
Environments refer to templated developer environments, which combine a template (Catalog Item) and parameters.
124+
125+
## Troubleshooting
126+
Errors can occur during initial requests and long-running operations, and will provide information about how to resolve the error.
127+
Be sure to confirm that dependent resources, such as pools and catalogs, are set up properly and are in a healthy state. You will not be able to create resources with the package when your dependent resources are in a failed state.
128+
129+
## Next steps
130+
Get started by exploring our samples and starting to use the package!
131+
132+
## Contributing
133+
134+
This project welcomes contributions and suggestions. Most contributions require
135+
you to agree to a Contributor License Agreement (CLA) declaring that you have
136+
the right to, and actually do, grant us the rights to use your contribution.
137+
For details, visit https://cla.microsoft.com.
138+
139+
When you submit a pull request, a CLA-bot will automatically determine whether
140+
you need to provide a CLA and decorate the PR appropriately (e.g., label,
141+
comment). Simply follow the instructions provided by the bot. You will only
142+
need to do this once across all repos using our CLA.
143+
144+
This project has adopted the
145+
[Microsoft Open Source Code of Conduct][code_of_conduct]. For more information,
146+
see the Code of Conduct FAQ or contact [email protected] with any
147+
additional questions or comments.
148+
149+
<!-- LINKS -->
150+
[code_of_conduct]: https://opensource.microsoft.com/codeofconduct/
151+
[authenticate_with_token]: https://docs.microsoft.com/azure/cognitive-services/authentication?tabs=powershell#authenticate-with-an-authentication-token
152+
[azure_identity_credentials]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#credentials
153+
[azure_identity_pip]: https://pypi.org/project/azure-identity/
154+
[default_azure_credential]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#defaultazurecredential
155+
[pip]: https://pypi.org/project/pip/
156+
[azure_sub]: https://azure.microsoft.com/free/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# coding=utf-8
2+
# --------------------------------------------------------------------------
3+
# Copyright (c) Microsoft Corporation. All rights reserved.
4+
# Licensed under the MIT License. See License.txt in the project root for license information.
5+
# Code generated by Microsoft (R) AutoRest Code Generator.
6+
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
7+
# --------------------------------------------------------------------------
8+
9+
from ._client import DevCenterClient
10+
from ._version import VERSION
11+
12+
__version__ = VERSION
13+
14+
try:
15+
from ._patch import __all__ as _patch_all
16+
from ._patch import * # type: ignore # pylint: disable=unused-wildcard-import
17+
except ImportError:
18+
_patch_all = []
19+
from ._patch import patch_sdk as _patch_sdk
20+
21+
__all__ = ["DevCenterClient"]
22+
__all__.extend([p for p in _patch_all if p not in __all__])
23+
24+
_patch_sdk()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# coding=utf-8
2+
# --------------------------------------------------------------------------
3+
# Copyright (c) Microsoft Corporation. All rights reserved.
4+
# Licensed under the MIT License. See License.txt in the project root for license information.
5+
# Code generated by Microsoft (R) AutoRest Code Generator.
6+
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
7+
# --------------------------------------------------------------------------
8+
9+
from copy import deepcopy
10+
from typing import Any, TYPE_CHECKING
11+
12+
from azure.core import PipelineClient
13+
from azure.core.rest import HttpRequest, HttpResponse
14+
15+
from ._configuration import DevCenterClientConfiguration
16+
from ._serialization import Deserializer, Serializer
17+
from .operations import DevBoxesOperations, DevCenterOperations, EnvironmentsOperations
18+
19+
if TYPE_CHECKING:
20+
# pylint: disable=unused-import,ungrouped-imports
21+
from typing import Dict
22+
23+
from azure.core.credentials import TokenCredential
24+
25+
26+
class DevCenterClient: # pylint: disable=client-accepts-api-version-keyword
27+
"""DevBox API.
28+
29+
:ivar dev_center: DevCenterOperations operations
30+
:vartype dev_center: azure.developer.devcenter.operations.DevCenterOperations
31+
:ivar dev_boxes: DevBoxesOperations operations
32+
:vartype dev_boxes: azure.developer.devcenter.operations.DevBoxesOperations
33+
:ivar environments: EnvironmentsOperations operations
34+
:vartype environments: azure.developer.devcenter.operations.EnvironmentsOperations
35+
:param tenant_id: The tenant to operate on. Required.
36+
:type tenant_id: str
37+
:param dev_center: The DevCenter to operate on. Required.
38+
:type dev_center: str
39+
:param credential: Credential needed for the client to connect to Azure. Required.
40+
:type credential: ~azure.core.credentials.TokenCredential
41+
:param dev_center_dns_suffix: The DNS suffix used as the base for all devcenter requests.
42+
Default value is "devcenter.azure.com".
43+
:type dev_center_dns_suffix: str
44+
:keyword api_version: Api Version. Default value is "2022-03-01-preview". Note that overriding
45+
this default value may result in unsupported behavior.
46+
:paramtype api_version: str
47+
:keyword int polling_interval: Default waiting time between two polls for LRO operations if no
48+
Retry-After header is present.
49+
"""
50+
51+
def __init__(
52+
self,
53+
tenant_id: str,
54+
dev_center: str,
55+
credential: "TokenCredential",
56+
dev_center_dns_suffix: str = "devcenter.azure.com",
57+
**kwargs: Any
58+
) -> None:
59+
_endpoint = "https://{tenantId}-{devCenter}.{devCenterDnsSuffix}"
60+
self._config = DevCenterClientConfiguration(
61+
tenant_id=tenant_id,
62+
dev_center=dev_center,
63+
credential=credential,
64+
dev_center_dns_suffix=dev_center_dns_suffix,
65+
**kwargs
66+
)
67+
self._client = PipelineClient(base_url=_endpoint, config=self._config, **kwargs)
68+
69+
self._serialize = Serializer()
70+
self._deserialize = Deserializer()
71+
self._serialize.client_side_validation = False
72+
self.dev_center = DevCenterOperations(self._client, self._config, self._serialize, self._deserialize)
73+
self.dev_boxes = DevBoxesOperations(self._client, self._config, self._serialize, self._deserialize)
74+
self.environments = EnvironmentsOperations(self._client, self._config, self._serialize, self._deserialize)
75+
76+
def send_request(self, request: HttpRequest, **kwargs: Any) -> HttpResponse:
77+
"""Runs the network request through the client's chained policies.
78+
79+
>>> from azure.core.rest import HttpRequest
80+
>>> request = HttpRequest("GET", "https://www.example.org/")
81+
<HttpRequest [GET], url: 'https://www.example.org/'>
82+
>>> response = client.send_request(request)
83+
<HttpResponse: 200 OK>
84+
85+
For more information on this code flow, see https://aka.ms/azsdk/dpcodegen/python/send_request
86+
87+
:param request: The network request you want to make. Required.
88+
:type request: ~azure.core.rest.HttpRequest
89+
:keyword bool stream: Whether the response payload will be streamed. Defaults to False.
90+
:return: The response of your network call. Does not do error handling on your response.
91+
:rtype: ~azure.core.rest.HttpResponse
92+
"""
93+
94+
request_copy = deepcopy(request)
95+
path_format_arguments = {
96+
"tenantId": self._serialize.url("self._config.tenant_id", self._config.tenant_id, "str", skip_quote=True),
97+
"devCenter": self._serialize.url(
98+
"self._config.dev_center", self._config.dev_center, "str", skip_quote=True
99+
),
100+
"devCenterDnsSuffix": self._serialize.url(
101+
"self._config.dev_center_dns_suffix", self._config.dev_center_dns_suffix, "str", skip_quote=True
102+
),
103+
}
104+
105+
request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments)
106+
return self._client.send_request(request_copy, **kwargs)
107+
108+
def close(self):
109+
# type: () -> None
110+
self._client.close()
111+
112+
def __enter__(self):
113+
# type: () -> DevCenterClient
114+
self._client.__enter__()
115+
return self
116+
117+
def __exit__(self, *exc_details):
118+
# type: (Any) -> None
119+
self._client.__exit__(*exc_details)

0 commit comments

Comments
 (0)