Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"parameters": {
"api-version": "2025-03-01",
"subscriptionId": "subid",
"resourceGroupName": "rg1",
"publicIpAddressName": "pip1",
"parameters": {
"publicIpArmId": "/subscriptions/subid/resourcegroups/rg1/providers/Microsoft.Network/publicIpAddresses/pip2"
}
},
"responses": {
"200": {
"body": {
"name": "pip1",
"id": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/publicIPAddresses/pip1",
"location": "westus",
"properties": {
"provisioningState": "Succeeded",
"publicIPAddressVersion": "IPv4",
"publicIPAllocationMethod": "Static",
"idleTimeoutInMinutes": 4,
"ipConfiguration": {
"id": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/networkInterfaces/testDNS649/ipConfigurations/ipconfig1"
}
},
"sku": {
"name": "Basic"
},
"type": "Microsoft.Network/publicIPAddresses"
}
},
"202": {
"headers": {
"Location": "https://management.azure.com/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/locations/westus/operationResults/00000000-0000-0000-0000-000000000000?api-version=2025-01-01",
"Azure-AsyncOperation": "https://management.azure.com/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/locations/westus/operations/00000000-0000-0000-0000-000000000000?api-version=2025-01-01"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"parameters": {
"api-version": "2025-03-01",
"subscriptionId": "subid",
"resourceGroupName": "rg1",
"publicIpAddressName": "test-ip",
"parameters": {
"isRollback": "false"
}
},
"responses": {
"200": {
"body": {
"name": "test-ip",
"id": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/publicIPAddresses/test-ip",
"location": "eastus",
"properties": {
"provisioningState": "Succeeded",
"publicIPAddressVersion": "IPv4",
"publicIPAllocationMethod": "Static",
"idleTimeoutInMinutes": 4,
"ipConfiguration": {
"id": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/networkInterfaces/testDNS649/ipConfigurations/ipconfig1"
}
},
"sku": {
"name": "Basic"
},
"type": "Microsoft.Network/publicIPAddresses"
}
},
"202": {
"headers": {
"Location": "https://management.azure.com/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/locations/westus/operationResults/00000000-0000-0000-0000-000000000000?api-version=2025-01-01",
"Azure-AsyncOperation": "https://management.azure.com/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/locations/westus/operations/00000000-0000-0000-0000-000000000000?api-version=2025-01-01"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{

Check notice on line 1 in specification/network/resource-manager/Microsoft.Network/stable/2025-03-01/publicIpAddress.json

View workflow job for this annotation

GitHub Actions / TypeSpec Requirement

Your service description will soon be required to convert from OpenAPI to TypeSpec. See https://aka.ms/azsdk/typespec.
"swagger": "2.0",
"info": {
"title": "NetworkManagementClient",
Expand Down Expand Up @@ -438,6 +438,156 @@
}
}
}
},
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPAddresses/{publicIpAddressName}/reserveCloudServicePublicIpAddress": {
"post": {
"tags": [
"PublicIPAddresses"
],
"operationId": "PublicIPAddresses_ReserveCloudServicePublicIpAddress",
"description": "Reserves the specified Cloud Service Public IP by switching its allocation method to Static. If rollback is requested, reverts the allocation method to Dynamic.",
"parameters": [
{
"$ref": "./network.json#/parameters/ApiVersionParameter"
},
{
"$ref": "./network.json#/parameters/SubscriptionIdParameter"
},
{
"$ref": "./networkManager.json#/parameters/ResourceGroupNameParameter"
},
{
"name": "publicIpAddressName",
"in": "path",
"required": true,
"type": "string",
"description": "The name of the public IP address.",
"pattern": "^[A-Za-z0-9][A-Za-z0-9_\\.-]*[A-Za-z0-9_]$",
"minLength": 1,
"maxLength": 80
Copy link
Contributor

@ramoka178 ramoka178 Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other APIs do not have this pattern. If there is an existing resource that does not fall under this pattern, they cannot use this API ? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- "pattern": "^[A-Za-z0-9][A-Za-z0-9_\\.-]*[A-Za-z0-9_]$",
Relaxed it to simple min and max length validations.
Was trying to follow publicly published name rules for publicIPAddresses before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this resource does require pattern check. PR checks were failing when I removed it.
Also, there shouldn't be a problem with existing resources as valid public ip resouces already comply with this pattern.

},
{
"name": "parameters",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/ReserveCloudServicePublicIpAddressRequest"
},
"description": "Parameter that define which Public IP Address should be associated in place of given Public IP Address."
}
],
"responses": {
"200": {
"description": "Request successful. The operation returns the resulting PublicIPAddress resource.",
"schema": {
"$ref": "#/definitions/PublicIPAddress"
}
},
"202": {
"description": "Accepted and the operation will complete asynchronously.",
"headers": {
"Location": {
"description": "URL for determining when an operation has completed. Send a GET request to the URL in Location header.\nThe URI should return a 202 until the operation reaches a terminal state and 200 once it reaches a terminal state.\n\nFor more info: https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/Addendum.md#202-accepted-and-location-headers",
"type": "string"
},
"Azure-AsyncOperation": {
"description": "URL for checking the ongoing status of the operation.\nTo get the status of the asynchronous operation, send a GET request to the URL in Azure-AsyncOperation header value.\n\nFor more info: https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/Addendum.md#asynchronous-operations",
"type": "string"
}
}
},
"default": {
"description": "Error response describing why the operation failed.",
"schema": {
"$ref": "./network.json#/definitions/CloudError"
}
}
},
"x-ms-examples": {
"Reserve public IP address ": {
"$ref": "./examples/PublicIpAddressReserve.json"
}
},
"x-ms-long-running-operation": true,
"x-ms-long-running-operation-options": {
"final-state-via": "location"
}
}
},
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPAddresses/{publicIpAddressName}/disassociateCloudServiceReservedPublicIp": {
Copy link
Contributor

@ramoka178 ramoka178 Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disassociateCloudServiceReservedPublicIp

can this be consistent with the other API name ?

say, disassociateCloudServicePublicIpAddress #Resolved

Copy link
Contributor Author

@pribansa pribansa Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API explicitly supports disassociation for Reserved Public IPs only. Hence, kept it to reflect that. While the other API is for Dynamic Public IP, not reserved.

"post": {
"tags": [
"PublicIPAddresses"
],
"operationId": "PublicIPAddresses_DisassociateCloudServiceReservedPublicIp",
"description": "Disassociates the Cloud Service reserved Public IP and associates the specified Standalone Public IP to the same Cloud Service frontend.",
"parameters": [
{
"$ref": "./network.json#/parameters/ApiVersionParameter"
},
{
"$ref": "./network.json#/parameters/SubscriptionIdParameter"
},
{
"$ref": "./networkManager.json#/parameters/ResourceGroupNameParameter"
},
{
"name": "publicIpAddressName",
"in": "path",
"required": true,
"type": "string",
"description": "The name of the public IP address.",
"pattern": "^[A-Za-z0-9][A-Za-z0-9_\\.-]*[A-Za-z0-9_]$",
"minLength": 1,
"maxLength": 80
Copy link
Contributor

@ramoka178 ramoka178 Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other APIs do not have this pattern. If there is an existing resource that does not fall under this pattern, they cannot use this API ? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- "pattern": "^[A-Za-z0-9][A-Za-z0-9_\\.-]*[A-Za-z0-9_]$",
Relaxed it to simple min and max length validations.
Was trying to follow publicly published name rules for publicIPAddresses before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this resource does require pattern check. PR checks were failing when I removed it.
Also, there shouldn't be a problem with existing resources as valid public ip resouces already comply with this pattern.

},
{
"name": "parameters",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/DisassociateCloudServicePublicIpRequest"
},
"description": "Parameter that define which Public IP Address should be associated in place of given Public IP Address."
}
],
"responses": {
"200": {
"description": "Request successful. The operation returns the resulting PublicIPAddress resource.",
"schema": {
"$ref": "#/definitions/PublicIPAddress"
}
},
"202": {
"description": "Accepted and the operation will complete asynchronously.",
"headers": {
"Location": {
"description": "URL for determining when an operation has completed. Send a GET request to the URL in Location header.\nThe URI should return a 202 until the operation reaches a terminal state and 200 once it reaches a terminal state.\n\nFor more info: https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/Addendum.md#202-accepted-and-location-headers",
"type": "string"
},
"Azure-AsyncOperation": {
"description": "URL for checking the ongoing status of the operation.\nTo get the status of the asynchronous operation, send a GET request to the URL in Azure-AsyncOperation header value.\n\nFor more info: https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/Addendum.md#asynchronous-operations",
"type": "string"
}
}
},
"default": {
"description": "Error response describing why the operation failed.",
"schema": {
"$ref": "./network.json#/definitions/CloudError"
}
}
},
"x-ms-examples": {
"Disassociate public IP address ": {
"$ref": "./examples/PublicIpAddressDisassociateCloudServiceReservedPublicIp.json"
}
},
"x-ms-long-running-operation": true,
"x-ms-long-running-operation-options": {
"final-state-via": "location"
}
}
}
},
"definitions": {
Expand Down Expand Up @@ -714,6 +864,48 @@
}
},
"description": "Response for GetPublicIpAddressDdosProtectionStatusOperation API service call."
},
"ReserveCloudServicePublicIpAddressRequest": {
"type": "object",
"properties": {
"isRollback": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isRollback

Enums are preferred over booleans.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in latest commit

"type": "string",
"enum": [
"true",
"false"
],
"x-ms-enum": {
"name": "IsRollback",
"modelAsString": true
},
"description": "When true, reverts from Static to Dynamic allocation (undo reservation)."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"When true, reverts from Static to Dynamic allocation (undo reservation).

so, the same reserveCloudServicePublicIpAddress API can do the reserving and dissociation ?

Overall, I am not sure if you need 2 APIs ?

Can you rethink about the following approach ?

Can you have a single API ?
say, /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPAddresses/{publicIpAddressName}/setPublicServiceIpAddressState ( or a name that suits better )

and the request body can have a enum , say, "State" with values "Reserve", "Disassociate".
URI has the publicIPAddress information.

Copy link
Member

@razvanbadea-msft razvanbadea-msft Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment is still a valid one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While Reserve API is a means to change the Allocation Method for the Public IP. Disassociate completely removes the association of public ip with cloud service. So it's not essentially a state of a public IP.

Moreover, the Reserve API doesn't include any downtime while Disassociate does. So it is more of a coerced coupling if we club them. Also, these APIs are already GA for 1P in it's current format post discussion with partner teams.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The downstream Service (RNM) APIs we call into, also have 2 sets of corresponding APIs. So it keeps the services consistent in approach.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ramoka178 and @razvanbadea-msft -- The author is in IDC TZ, and needs to meet cutoff date of today.
Im from the IDC reviewrs team, and have reviewed the PR. The above justification sounds legit for this comment.

Other actionable comments have been incorporated. So Im approving the PR.

}
},
"required": [
"isRollback"
],
"description": "The request for ReserveCloudServicePublicIpAddressOperation."
},
"DisassociateCloudServicePublicIpRequest": {
"type": "object",
"properties": {
"publicIpArmId": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

publicIpArmId

This is already present in the URI right ? do you need it again.?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This public ip is different from the one in URL and required for disassociation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can rename it like publicIpResourceId and set the format as arm-id with type restriction to be only publicip

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in latest commit.

"type": "string",
"format": "arm-id",
"x-ms-arm-id-details": {
"allowedResources": [
{
"type": "Microsoft.Network/publicIPAddresses"
}
]
},
"description": "ARM ID of the Standalone Public IP to associate. This is of the form : /subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Network/publicIPAddresses/{publicIpAddressName}"
}
},
"required": [
"publicIpArmId"
],
"description": "The request for DisassociateCloudServicePublicIpOperation."
}
}
}