Replies: 2 comments 8 replies
-
Hi @vcz-fr, thank you for the detailed notes above. I guess I'm trying to understand what exactly the ask is here. As outlined in other discussions, the IPAM tool doesn't actually manipulate Azure in any way. The tool provides visibility by READ ONLY for network related objects in Azure (vNETs, Subnets, Endpoints) and provides an overlay in the form of Spaces & Blocks. The tools also provides a way to reserve a CIDR range from a provided Block, then using Azure API's you can create a vNET from said CIDR range and the IPAM tool will automatically associate the new vNET to the target Block by way of a tag applied to the resource. For these uses, the mechanism of interacting with IPAM in an IaC fashion is generally to request a CIDR reservation, grab the output, and then the next stages involve the Azure API directly. So, all of that being said, can you help me understand more closely what you'd like to see from the IPAM API's and the business flow that would help enable? We're always interested in how we can improve this product for everyone, so we are happy to consider any & all input. P.S. If you like to meeting directly and chat live, we're also happy to make the time for you if that is preferred. Thank you very much! |
Beta Was this translation helpful? Give feedback.
-
Indeed, I see that my actual request was not that clear. Sorry for that. Here is an example of how I would integrate the IPAM with VNET provisioning if I had access to single-resource endpoints: #>> config.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.23"
}
restapi = {
source = "Mastercard/restapi"
version = "~> 1.17"
}
}
}
provider "azurerm" {
features {}
subscription_id = var.subscription_id
}
provider "restapi" {
uri = "https://ipam.example.com/api"
headers = {
Content-Type = "application/json"
Authorization = "Bearer ${var.ipam_token}"
}
create_returns_object = true
}
#>> vars.tf
variable "ipam_token" {
type = string
description = "IPAM authentication token"
sensitive = true
}
variable "cidr_mask" {
type = string
description = "VNET CIDR mask, the actual CIDR is allocated by the IPAM"
}
variable "vnet_name" {
type = string
description = "VNET name, does not include prefix"
}
variable "rg_name" {
type = string
description = "Resource Group name to which the VNET should be attached"
}
variable "ipam_space" {
type = string
description = "IPAM Space where the VNET address block should be allocated. Refer to the IPAM documentation."
}
variable "ipam_block" {
type = string
description = "IPAM Block where the VNET address block should be allocated. Refer to the IPAM documentation."
}
#>> vnet.tf
data "azurerm_resource_group" "vnet_rg" {
name = var.rg_name
}
resource "restapi_object" "reservation" {
path = "/spaces/${var.ipam_space}/blocks/${var.ipam_block}/reservations"
data = jsonencode({
size = var.cidr_mask
})
}
resource "azurerm_virtual_network" "vnet" {
name = "vnet-${var.vnet_name}"
location = data.azurerm_resource_group.vnet_rg.location
resource_group_name = var.rg_name
# This is where we retrieve the CIDR reserved by the IPAM and give it to the VNET
address_space = [restapi_object.reservation.api_data.cidr]
}
# This only declares the VNET on the IPAM, is there a path to associate a VNET to an IPAM reservation ID?
resource "restapi_object" "vnet_association" {
path = "/spaces/${var.ipam_space}/blocks/${var.ipam_block}/networks"
data = jsonencode({
id = azurerm_virtual_network.vnet.id
active = true
})
} This provisions today but will cause reprovisioning every time this code is executed as we are missing a single-resource Read endpoint for Reservations and VNET associations. This is what the provisioning plan looks like:
Even though Terraform has no native way to keep state on REST resources (as of 1.3), using a basic REST provider could be an elegant way to manage IPAM Reservations and IPAM VNET associations. This approach also works with the other resources exposed by the API. |
Beta Was this translation helpful? Give feedback.
-
Hello,
I am currently working with Infrastructure as Code tooling to cleanly integrate this IPAM into the provisioning of network components reserving address blocks. Unfortunately, the design of this API clashes with the way the IaC tool operates. I am currently using Terraform with the Mastercard/restapi provider. That provider is picky but works until it needs to validate resource creation, and then deletion.
This is not a feature request as it requires an API redesign. However, code and OpenAPI 3 examples can be provided if needed.
The issue
The API is designed in such a way that batch operations are possible with no single operation counterpart. Single operations are technically possible (a batch containing one operation is indeed a single operation) but not offered as primitives.
Definitions
Skip this section if you are at ease with the topics of day one, day two operations and so on. We'll define the resource lifecycle as three operating phases: creation, operation and decommissioning.
Creation
We assume the resource we wish to create does not exist yet.
POST /parent/{parentId}/resource
, retrieve its unique identifier;GET /parent/{parentId}/resource/{resourceId}
.Save information returned during the resource creation and/or verification query.
Operation
We assume the resource is present. Either imported into the IaC tooling or created by it.
GET /parent/{parentId}/resource/{resourceId}
, retrieve its current value;PUT/PATCH /parent/{parentId}/resource/{resourceId}
;GET /parent/{parentId}/resource/{resourceId}
.Decommissioning
We assume the resource is present. Either imported into the IaC tooling or created by it.
GET /parent/{parentId}/resource/{resourceId}
, retrieve its current value;DELETE /parent/{parentId}/resource/{resourceId}
;GET /parent/{parentId}/resource/{resourceId}
. This invocation should fail.Discussion
When it comes to API design, it is common to start with primitives. Looping over primitives has the same effect as invoking a batch endpoint. There is of course network overhead in this approach but having primitives is always good from a software engineering standpoint. Additionally, batch operations make reporting statuses more challenging. For instance: what should happen when one in many Create fails? Should we report a fail or a success? Roll back the complete operation?
Batch operations come in handy when network overhead becomes non negligible. This is the case for data ingestion endpoints which may receive many concurrent updates from the same origin. If we follow RESTful with API path segments looking like
/resource1Type/{resource1Value}/resource2Type/{resource2Value}
then there should be no place for such an endpoint unless a resource cannot be named "batch". If this is guaranteed, then batch operation endpoints could be added to/resource1Type/{resource1Value}/resource2Type/batch
.Note: This is an ugly hack of commonly accepted API design practices to specifically allow for batch operations.
POST /resource1Type/{resource1Value}/resource2Type/batch
;PUT/PATCH /resource1Type/{resource1Value}/resource2Type/batch
;DELETE /resource1Type/{resource1Value}/resource2Type/batch
.You will notice that there is no Read endpoint here. This because in the HTTP specification GET requests cannot contain a request body. If a "many Read" endpoint is needed, the operation could be seen as a query, at which point it could be implemented as:
POST /resource1Type/{resource1Value}/resource2Type/query
.OneOf alternative design
It is tempting to accept
List(Resource) OR Resource
in the body of a single operation endpoint. However this gives an additional responsibility to the endpoint and may render implementation more complex on the API side as well as on the integration side! Typed languages require users to specify which data type they should expect and validate for, often automating that part (serializer-deserializer, often implemented as part of HTTP server framework implementations). Such a design breaks this behavior and requires users to re-validate data manually in their controllers.That was a long post. Thank you for your attention and have a nice day!
Beta Was this translation helpful? Give feedback.
All reactions