-
Notifications
You must be signed in to change notification settings - Fork 47
Add documentation around resource pools on object templates. #8581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e20a071
997a8da
b401dcf
61f6b7c
711872a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -333,3 +333,258 @@ For more information about Profiles and templates, see: | |||||
|
|
||||||
| - [Creating and assigning Profiles](../guides/profiles.mdx) - Guide for working with Profiles | ||||||
| - [Understanding Profiles in Infrahub](../topics/profiles.mdx) - Deep dive into Profile concepts | ||||||
|
|
||||||
| ## Allocating resources from pools via templates | ||||||
|
|
||||||
| Object templates support automatic resource allocation. This section extends the device and interface schema from above by adding IP address support to `InfraInterface`, then shows how to wire a `CoreIPAddressPool` to the interface template. | ||||||
|
|
||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd add a link to the related topic section here, Like "if you want to know more about xyz"
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is documented at the bottom of the guide to learn more about resource managers. Do you want me to move that up to here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bumping this so I can get this merged in ASAP. |
||||||
| ### Update the schema | ||||||
|
|
||||||
| Add the two IPAM nodes and an `ip_address` relationship to `InfraInterface`, if you don't already have them: | ||||||
|
|
||||||
| ```yaml | ||||||
| --- | ||||||
| # yaml-language-server: $schema=https://schema.infrahub.app/infrahub/schema/latest.json | ||||||
| version: "1.0" | ||||||
|
|
||||||
| nodes: | ||||||
| - name: IPAddress | ||||||
| namespace: Ipam | ||||||
| label: "IP Address" | ||||||
| display_label: "{{ address__value }}" | ||||||
| inherit_from: | ||||||
| - BuiltinIPAddress | ||||||
|
|
||||||
| - name: IPPrefix | ||||||
| namespace: Ipam | ||||||
| label: "IP Prefix" | ||||||
| display_label: "{{ prefix__value }}" | ||||||
| inherit_from: | ||||||
| - BuiltinIPPrefix | ||||||
|
|
||||||
| - name: Interface | ||||||
| namespace: Infra | ||||||
| label: "Interface" | ||||||
| include_in_menu: true | ||||||
| icon: "mdi:ethernet" | ||||||
| display_label: "{{ name__value }}" | ||||||
| order_by: | ||||||
| - name__value | ||||||
| uniqueness_constraints: | ||||||
| - ["device", "name__value"] | ||||||
| human_friendly_id: ["device__name__value", "name__value"] | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you need
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a component relationship on device so that gets created automatically. We're building on the schema at the start of the guide, but maybe I just add the full schemas into this one as well? |
||||||
| attributes: | ||||||
| - name: name | ||||||
| kind: Text | ||||||
| - name: description | ||||||
| kind: Text | ||||||
| optional: true | ||||||
| - name: enable | ||||||
| kind: Boolean | ||||||
| optional: false | ||||||
| default_value: false | ||||||
| relationships: | ||||||
| - name: device | ||||||
| peer: InfraDevice | ||||||
| optional: false | ||||||
| cardinality: one | ||||||
| kind: Parent | ||||||
| - name: ip_address | ||||||
| peer: IpamIPAddress | ||||||
| optional: true | ||||||
| cardinality: one | ||||||
| kind: Attribute | ||||||
| ``` | ||||||
|
|
||||||
| :::info | ||||||
|
|
||||||
| When a schema node has a relationship or attribute that supports resource pool allocation, Infrahub automatically generates a corresponding `<attribute_or_relationship_name>_from_resource_pool` field on the template node. In this example, because `IpamIPAddress` can be allocated from a `CoreIPAddressPool`, an `ip_address_from_resource_pool` field is generated on `TemplateInfraInterface`. This is what connects the template to the pool. | ||||||
|
|
||||||
| ::: | ||||||
|
|
||||||
| Load this updated schema into your Infrahub instance before proceeding. | ||||||
|
|
||||||
| ### Create the resource pool | ||||||
|
|
||||||
| First create a prefix to draw addresses from, then create the pool backed by that prefix. | ||||||
|
|
||||||
| <Tabs groupId="method" queryString> | ||||||
| <TabItem value="web" label="Via the Web Interface" default> | ||||||
|
|
||||||
| **Create the IP prefix:** | ||||||
|
|
||||||
| 1. Navigate to `IPAM` > `Prefixes` | ||||||
| 2. Click `+ Add IP Prefix` | ||||||
| 3. Fill in: | ||||||
| - **Prefix**: `192.168.0.0/16` | ||||||
| - **Member Type**: `address` | ||||||
| - **Is Pool**: `true` | ||||||
| 4. Save | ||||||
|
|
||||||
| **Create the IP address pool:** | ||||||
|
|
||||||
| 1. Navigate to `Resource Manager` > `IP Address Pool` | ||||||
| 2. Click `+ Add IP Address Pool` | ||||||
| 3. Fill in: | ||||||
| - **Name**: `Interface IP Pool` | ||||||
| - **Default Address Type**: `IpamIPAddress` | ||||||
| - **IP Namespace**: `default` | ||||||
| - **Resources**: select `192.168.0.0/16` | ||||||
| 4. Save | ||||||
|
|
||||||
| </TabItem> | ||||||
| <TabItem value="graphql" label="Via the GraphQL Interface"> | ||||||
|
|
||||||
| ```graphql | ||||||
| mutation CreatePrefix { | ||||||
| IpamIPPrefixCreate( | ||||||
| data: {prefix: {value: "192.168.0.0/16"}, member_type: {value: "address"}, is_pool: {value: true}} | ||||||
| ) { | ||||||
| ok | ||||||
| object { id } | ||||||
| } | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| Then use the returned prefix ID to create the pool: | ||||||
|
|
||||||
| ```graphql | ||||||
| mutation CreatePool($prefixId: String!) { | ||||||
| CoreIPAddressPoolCreate( | ||||||
| data: { | ||||||
| name: {value: "Interface IP Pool"} | ||||||
| default_address_type: {value: "IpamIPAddress"} | ||||||
| ip_namespace: {hfid: ["default"]} | ||||||
| resources: [{id: $prefixId}] | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wonder if we can't use prefix HFID here (haven't tried tho):
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not work: Tried with HFID, but the |
||||||
| } | ||||||
| ) { | ||||||
| ok | ||||||
| } | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| </TabItem> | ||||||
| <TabItem value="object-file" label="Via an Object File"> | ||||||
|
|
||||||
| ```yaml | ||||||
| --- | ||||||
| apiVersion: infrahub.app/v1 | ||||||
| kind: Object | ||||||
| spec: | ||||||
| kind: CoreIPAddressPool | ||||||
| data: | ||||||
| - name: "Interface IP Pool" | ||||||
| default_address_type: IpamIPAddress | ||||||
| ip_namespace: default | ||||||
| resources: | ||||||
| kind: IpamIPPrefix | ||||||
| data: | ||||||
| - prefix: 192.168.0.0/16 | ||||||
| member_type: address | ||||||
| is_pool: true | ||||||
| ``` | ||||||
|
|
||||||
| Load with: `infrahubctl object load pools.yml` | ||||||
|
|
||||||
| </TabItem> | ||||||
| <TabItem value="python-sdk" label="Via the Python SDK"> | ||||||
|
|
||||||
| ```python | ||||||
| async def run(client: InfrahubClient, log: logging.Logger, branch: str) -> None: | ||||||
| prefix = await client.create( | ||||||
| kind="IpamIPPrefix", | ||||||
| data={"prefix": "192.168.0.0/16", "member_type": "address", "is_pool": True}, | ||||||
| ) | ||||||
| await prefix.save(allow_upsert=True) | ||||||
|
|
||||||
| pool = await client.create( | ||||||
| kind="CoreIPAddressPool", | ||||||
| data={ | ||||||
| "name": "Interface IP Pool", | ||||||
| "default_address_type": "IpamIPAddress", | ||||||
| "ip_namespace": {"hfid": ["default"]}, | ||||||
| "resources": [{"id": prefix.id}], | ||||||
| }, | ||||||
| ) | ||||||
| await pool.save(allow_upsert=True) | ||||||
| ``` | ||||||
|
|
||||||
| </TabItem> | ||||||
| </Tabs> | ||||||
|
|
||||||
| ### Assign the pool to the interface template | ||||||
|
|
||||||
| With the pool created, update the interface template from the previous section to allocate an IP address from it whenever a new interface is created. | ||||||
|
|
||||||
| <Tabs groupId="method" queryString> | ||||||
| <TabItem value="web" label="Via the Web Interface" default> | ||||||
|
|
||||||
| 1. Navigate to `Object Management` > `Templates` | ||||||
| 2. Open `Template-SwitchModel123-Ethernet1` (or any interface template) | ||||||
| 3. On the `IP Address` field, click the pool selector button and choose `Interface IP Pool` | ||||||
| 4. The field will show an `Allocated by pool` badge | ||||||
| 5. Save | ||||||
|
Comment on lines
+517
to
+526
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clarify whether allocation applies to one interface or all configured templates. These steps tell the reader to update a single interface template, but the closing paragraph says every generated interface gets an address. As written, a reader who only updates ✍️ Suggested wording- With the pool created, update the interface template from the previous section to allocate an IP address from it whenever a new interface is created.
+ With the pool created, update each interface template that should allocate an IP address from the pool when a new interface is created.
- 2. Open `Template-SwitchModel123-Ethernet1` (or any interface template)
+ 2. Open each interface template that should receive an allocated address, starting with `Template-SwitchModel123-Ethernet1`
- Creating a device from the template works exactly as described in the [Create object instances](`#create-object-instances-using-the-predefined-template`) section above. No additional steps are required — when the device is saved, Infrahub allocates an available IP address from `Interface IP Pool` and assigns it to each interface's `ip_address` field.
+ Creating a device from the template works exactly as described in the [Create object instances](`#create-object-instances-using-the-predefined-template`) section above. No additional steps are required — when the device is saved, Infrahub allocates an available IP address from `Interface IP Pool` for each interface template configured with `ip_address_from_resource_pool`.Also applies to: 577-579 🤖 Prompt for AI Agents |
||||||
|
|
||||||
| </TabItem> | ||||||
| <TabItem value="graphql" label="Via the GraphQL Interface"> | ||||||
|
|
||||||
| ```graphql | ||||||
| mutation { | ||||||
| TemplateInfraInterfaceUpdate( | ||||||
| data: { | ||||||
| hfid: ["Template-SwitchModel123", "Template-SwitchModel123-Ethernet1"] | ||||||
| ip_address_from_resource_pool: {hfid: ["Interface IP Pool"]} | ||||||
| } | ||||||
| ) { | ||||||
| ok | ||||||
| } | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| </TabItem> | ||||||
| <TabItem value="object-file" label="Via an Object File"> | ||||||
|
|
||||||
| ```yaml | ||||||
| --- | ||||||
| apiVersion: infrahub.app/v1 | ||||||
| kind: Object | ||||||
| spec: | ||||||
| kind: TemplateInfraInterface | ||||||
| data: | ||||||
| - template_name: "Template-SwitchModel123-Ethernet1" | ||||||
| device: "Template-SwitchModel123" | ||||||
| ip_address_from_resource_pool: "Interface IP Pool" | ||||||
| ``` | ||||||
|
Comment on lines
+545
to
+557
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Finish the object-file path with the load step. This tab stops at the YAML example, so the object-file workflow is not fully executable end to end. Please add the 🤖 Prompt for AI Agents |
||||||
|
|
||||||
| </TabItem> | ||||||
| <TabItem value="python-sdk" label="Via the Python SDK"> | ||||||
|
|
||||||
| ```python | ||||||
| async def run(client: InfrahubClient, log: logging.Logger, branch: str) -> None: | ||||||
| pool = await client.get(kind="CoreIPAddressPool", hfid=["Interface IP Pool"]) | ||||||
|
|
||||||
| iface_template = await client.get( | ||||||
| kind="TemplateInfraInterface", | ||||||
| hfid=["Template-SwitchModel123", "Template-SwitchModel123-Ethernet1"], | ||||||
| ) | ||||||
| iface_template.ip_address_from_resource_pool = {"id": pool.id} | ||||||
| await iface_template.save(allow_upsert=True) | ||||||
| ``` | ||||||
|
|
||||||
| </TabItem> | ||||||
| </Tabs> | ||||||
|
|
||||||
| ### Create objects — IP addresses are allocated automatically | ||||||
|
|
||||||
| Creating a device from the template works exactly as described in the [Create object instances](#create-object-instances-using-the-predefined-template) section above. No additional steps are required — when the device is saved, Infrahub allocates an available IP address from `Interface IP Pool` and assigns it to each interface's `ip_address` field. | ||||||
|
|
||||||
| :::info | ||||||
|
|
||||||
| Resource allocation happens at object creation time, not at template creation time. Each new device gets its own unique address drawn from the pool. | ||||||
|
|
||||||
| ::: | ||||||
|
|
||||||
| For more information about resource pools, see: | ||||||
|
|
||||||
| - [Managing resource pools](../guides/resource-manager.mdx) - Guide for creating and using pools | ||||||
| - [Resource Manager concepts](../topics/resource-manager.mdx) - Deep dive into allocation behaviour | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,6 +31,22 @@ This combination allows you to use templates for structural definition (which po | |
|
|
||
| For more details, see the [Creating and assigning Profiles guide](../guides/profiles.mdx). | ||
|
|
||
| ## Integration with Resource Pools | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have any precise use case in mind for that integration, e.g. management interface IP if all device using this template are sharing the same prefix. On that perhaps it's worth mentioning when not using it, if for instance I need to use different pool based on the site I can't put this in the template.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me think about this.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see any documented use cases for this specifically. I could see your use case, being defined as multiple object templates based on a site that they would select from the list. |
||
|
|
||
| Templates can be wired to resource pools so that unique values are allocated automatically when objects are created from the template. Rather than manually assigning an IP address or number attribute to each new object, you define once on the template which pool to draw from and Infrahub handles allocation at creation time. | ||
|
|
||
| ### How it works | ||
|
|
||
| When a schema node has a relationship or attribute whose peer type supports resource pool allocation (for example, a relationship to an IP address node, or a number attribute), Infrahub automatically generates a `<attribute_or_relationship_name>_from_resource_pool` field on the corresponding template node. Assigning a pool to that field is all that is needed — no changes to object creation are required. | ||
|
|
||
| Allocation happens at object creation time, not at template creation time. Each object created from the template receives its own unique value drawn from the pool. | ||
|
|
||
| ### Why this matters | ||
|
|
||
| Without pool integration, templates can only set static values. Any attribute that must be unique per object (IP addresses, circuit IDs, interface numbers) would have to be filled in manually each time. Pool integration closes that gap: the template defines the structural intent and the pool ensures each instance gets a valid, non-conflicting value automatically. | ||
|
|
||
| For step-by-step instructions, see [Allocating resources from pools via templates](../guides/object-template.mdx#allocating-resources-from-pools-via-templates). | ||
|
|
||
| ## Component relationship | ||
|
|
||
| When enabling template generation on a given schema node, Infrahub automatically detects whether the object has any component relationships. If it does, Infrahub will generate corresponding templates for those related objects as well. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there's an example in here for using NumberPools on an attribute in a template, which would probably be helpful. I don't know if it needs to be a full example, but it is unexpected that you have to use a relationship to specify a pool for an attribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think from a user perspective, it should be the same and that seems like an implementation detail that we'd be discussing in the guide? We can potentially discuss this in the topic.