Azure / Azure/azure-rest-api-specs
Sending full ServicesDescription object to PUT endpoint on Azure API for FHIR endpoint causes failure due to Private Endpoint Configuration being included
- Dominant language
- TypeSpec
- Stars
- 3.1k
- Forks
- 5.9k
- Avg merge
- 2d 22h
- Merged PRs (30d)
- 444
Description
The scenario:
I want to programmatically change a property on my Azure API for FHIR service. Let's say the backing CosmosDB provisioned RU amount. My expectation is that I would GET the fhir_server, edit the relevant property and PUT it back in. If there is a Private Endpoint enabled on the FHIR service, this will fail, since it is included in the GET but will not be accepted on the PUT, despite them being described as the same object in the documentation ([ServicesDescription](https://docs.microsoft.com/en-us/rest/api/healthcareapis/services/create-or-update#servicesproperties)).
Originally ran into this in the Python SDK: Azure/azure-sdk-for-python#24608
FHIR PG says that the privateEndpointConnections description is read-only. There are [separate methods](https://docs.microsoft.com/en-us/rest/api/healthcareapis/private-endpoint-connections) for handling PEs on the FHIR service.
I do not expect to have to **delete** properties of a description of a resource to update it. I think returning the privateEndpointConnections on GET is way more confusing than it is worth when there are other, more explicit methods that actually work and don't gum anything up.
#
Code:
```
fhir_server = requests.get(url=management_url, headers={"Authorization": f"Bearer {token}"}).json()
print(f"{fhir_server = }")
print(f"Current RUs: {fhir_server['properties']['cosmosDbConfiguration']['offerThroughput']}")
fhir_server['properties']['cosmosDbConfiguration']['offerThroughput'] = 5_000
print(f"Setting RUs to: {fhir_server['properties']['cosmosDbConfiguration']['offerThroughput']}")
r = requests.put(url=management_url, headers={"Authorization": f"Bearer {token}"}, json=fhir_server)
print(f"{r.json() = }")
```
Output:
```
fhir_server = {'id': '/subscriptions/1820f4e7-71ba-46f8-b759-0939ed6d0650/resourceGroups/osfsdmdhut1rg/providers/Microsoft.HealthcareApis/services/osidmdhut1v1fhir', 'name': 'osidmdhut1v1fhir', 'type': 'Microsoft.HealthcareApis/services', 'etag': '"a2010c95-0000-0400-0000-627fc92a0000"', 'location': 'eastus', 'kind': 'fhir-R4', 'tags': {}, 'properties': {'accessPolicies': [{'objectId': '1a977c4a-9058-4435-83a7-f96f4450f3da'}], 'cosmosDbConfiguration': {'offerThroughput': 3000}, 'authenticationConfiguration': {'authority': 'https://login.microsoftonline.com/85722e96-8e10-4794-9933-f05d211175ef', 'audience': 'https://osidmdhut1v1fhir.azurehealthcareapis.com', 'smartProxyEnabled': True}, 'corsConfiguration': {'origins': [], 'headers': [], 'methods': [], 'allowCredentials': False}, 'exportConfiguration': {}, 'acrConfiguration': {'loginServers': []}, 'privateEndpointConnections': [{'id': '/subscriptions/1820f4e7-71ba-46f8-b759-0939ed6d0650/resourceGroups/osfsdmdhut1rg/providers/Microsoft.HealthcareApis/services/osidmdhut1v1fhir/privateEndpointConnections/osidmdhut1v1fhir.a8182d32-e196-46d1-bc74-1530f4ed450f', 'name': 'osidmdhut1v1fhir.a8182d32-e196-46d1-bc74-1530f4ed450f', 'type': 'Microsoft.HealthcareApis/services/privateEndpointConnections', 'properties': {'provisioningState': 'Succeeded', 'privateEndpoint': {'id': '/subscriptions/1820f4e7-71ba-46f8-b759-0939ed6d0650/resourceGroups/osfsdmdhut1rg/providers/Microsoft.Network/privateEndpoints/osidmdhut1v1fhir-private-endpoint'}, 'privateLinkServiceConnectionState': {'status': 'Approved', 'description': 'Auto-Approved', 'actionsRequired': 'None'}}}], 'publicNetworkAccess': 'Disabled', 'provisioningState': 'Succeeded'}, 'identity': {'principalId': '', 'tenantId': '', 'type': 'None'}}
3000
5000
r.json() = {'error': {'code': 'BadRequest', 'message': 'The provided Private Endpoint connections configuration is invalid.'}}
```
Meanwhile if you add this line before you send in your request:
`fhir_server['properties']['privateEndpointConnections'] = None`
You get the happy result:
`r.json() = {'id': '/subscriptions/1820f4e7-71ba-46f8-b759-0939ed6d0650/resourceGroups/osfsdmdhut1rg/providers/Microsoft.HealthcareApis/services/osidmdhut1v1fhir', 'name': 'osidmdhut1v1fhir', 'type': 'Microsoft.HealthcareApis/services', 'etag': '"4000673a-0000-0400-0000-6296225e0000"', 'location': 'eastus', 'kind': 'fhir-R4', 'tags': {}, 'properties': {'accessPolicies': [{'objectId': '1a977c4a-9058-4435-83a7-f96f4450f3da'}], 'cosmosDbConfiguration': {'offerThroughput': 5000}, 'authenticationConfiguration': {'authority': 'https://login.microsoftonline.com/85722e96-8e10-4794-9933-f05d211175ef', 'audience': 'https://osidmdhut1v1fhir.azurehealthcareapis.com', 'smartProxyEnabled': True}, 'corsConfiguration': {'origins': [], 'headers': [], 'methods': [], 'allowCredentials': False}, 'exportConfiguration': {}, 'acrConfiguration': {'loginServers': []}, 'privateEndpointConnections': None, 'publicNetworkAccess': 'Disabled', 'provisioningState': 'Accepted'}, 'identity': {'principalId': '', 'tenantId': '', 'type': 'None'}}`
Contributor guide
Research direction
Start by locating the Azure API for FHIR ServicesDescription definition and its privateEndpointConnections property in this repository. Compare the GET and PUT representations and the read-only annotations, then verify the reported GET-then-PUT request behavior; done means the specification accurately supports or documents a full resource update without the reported validation failure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100