Juniper / terraform-provider-apstra

Apstra Terraform Provider
Apache License 2.0
14 stars 3 forks source link

No way to get application ID for an ESI LAG #694

Closed williampincek47 closed 2 months ago

williampincek47 commented 3 months ago

Hi,

I am unable to find a way to reference the application point (ID of the interface) for an ESI LAG when attempting to apply a connectivity template. The only way that I have found to do it, is to go into graph explorer and find the ID of the interface manually (see ID highlighted in yellow in attached diagram).

esi-lag-application-points

When not using ESI LAG, it is fairly easy to find the application point IDs of interfaces using the apstra_datacenter_interfaces_by_system data resource. Here is an example:

[lab@desktop terraform]$ terraform state show data.apstra_datacenter_interfaces_by_system.leaf1

data.apstra_datacenter_interfaces_by_system.leaf1:

data "apstra_datacenter_interfaces_by_system" "leaf1" { blueprint_id = "dee40fb6-5b26-4e6e-b1f9-ffce839c6a3d" graph_query = "node(type='system',id='j1YwO_QtlgFvL4F30vE').out(type='hosted_interfaces').node(type='interface',name='n_interface',id=not_none(),if_name=not_none())" if_map = { "ae1" = "bLSBtUI7lTfLStI_t_w" "ge-0/0/0" = "Q3Ni-GKC85beuJZA6Do" "ge-0/0/1" = "qytYoXzrPww0ugORDkE" "ge-0/0/4" = "dnocjuwtolMYrkAuQ2U" "ge-0/0/5" = "rT6ckj8qmmILHVSiW-s" "lo0.0" = "my_esi_001_leaf1_loopback" "lo0.2" = "sz:0E9cHGLEQa3tVWwM9s8,my_esi_001_leaf1_loopback" } system_id = "j1YwO_QtlgFvL4F30vE" }

I like to suggest that this data resource is modified to include a lag_map that lists the interface that is composed of any aeX interfaces. For example, it might look like this when using the network in the attached diagram...

[lab@desktop terraform]$ terraform state show data.apstra_datacenter_interfaces_by_system.leaf1

data.apstra_datacenter_interfaces_by_system.leaf1:

data "apstra_datacenter_interfaces_by_system" "leaf1" { blueprint_id = "dee40fb6-5b26-4e6e-b1f9-ffce839c6a3d" graph_query = "node(type='system',id='j1YwO_QtlgFvL4F30vE').out(type='hosted_interfaces').node(type='interface',name='n_interface',id=not_none(),if_name=not_none())" if_map = { "ae1" = "bLSBtUI7lTfLStI_t_w" "ge-0/0/0" = "Q3Ni-GKC85beuJZA6Do" "ge-0/0/1" = "qytYoXzrPww0ugORDkE" "ge-0/0/4" = "dnocjuwtolMYrkAuQ2U" "ge-0/0/5" = "rT6ckj8qmmILHVSiW-s" "lo0.0" = "my_esi_001_leaf1_loopback" "lo0.2" = "sz:0E9cHGLEQa3tVWwM9s8,my_esi_001_leaf1_loopback" } lag_map = { "ae1" = "5ZKKzA50Jgf40-Hme1Y" } system_id = "j1YwO_QtlgFvL4F30vE" }

This would mean that the lag_map would be the same for both of the systems. Since, the lag_map will be the same for both of the leaf systems involved you could use either device's lag_map to get the ID.

I'm not sure if this is possible but right now it appear to be impossible to use Terraform to access the ID of an ESI LAG for the purpose of applying a connectivity template.

One other option might be to create a new data source called apstra_datacenter_lags_by_system that lists the interface that is composed of any aeX interfaces.

Thanks,

Will Pincek

chrismarget-j commented 3 months ago

Hi @williampincek47,

The "by system" data source won't find an ESI or MLAG interface ID because the interface doesn't really belong to a single system.

We can revisit this behavior, but it's what made sense to me at the time.

For this use case, try the apstra_datacenter_interfaces_by_link_tag data source.

Because it operates by link, there's no ambiguity introduced by switch redundancy.

williampincek47 commented 3 months ago

Hi Chris,

OK, I see what you are saying. It almost seems like apstra_datacenter_interfaces_by_link_tag was created for this exact use case (getting the ID of an ESI LAG interface). One reason I say this is because of the graph query it uses (see below). If so, the documentation should probably mention it.

Definitely interesting behavior. In the config, you must assign a combination of a tag and a group label to the links of a generic system. This causes 3 links to be tagged, yet apstra_datacenter_interfaces_by_link_tag only captures the link ID of an interface associated with one of those links.....and it happens to be the right one based on its graph query. Nice!

Here is the behavior that I observed...

resource "apstra_datacenter_generic_system" "server12" { blueprint_id = resource.apstra_datacenter_blueprint.my-pod1.id name = "server12" hostname = "server12" links = [ { tags = ["agg-link"] target_switch_id = data.apstra_datacenter_system.leaf1.id target_switch_if_name = "ge-0/0/4" target_switch_if_transform_id = 1 lag_mode = "lacp_active" group_label = "ae1" }, { tags = ["agg-link"] target_switch_id = data.apstra_datacenter_system.leaf2.id target_switch_if_name = "ge-0/0/4" target_switch_if_transform_id = 1 lag_mode = "lacp_active" group_label = "ae1" }, ] }

The above config causes the tagging of 3 interfaces in the graph --- the ae interface of leaf1, the ae interfaces of leaf2, and the ae interface of the leaf-pair.

Confirmed by using a graph query of node('link', tag=has_all(['agg-link']), name='steve')

{ "count": 3, "items": [ { "steve": { "id": "my_esi_001_leaf2<->server12(ae1)[1]", "type": "link", "label": "my_esi_001_leaf2<->server12(ae1)[1]", "deploy_mode": "deploy", "group_label": "ae1", "link_type": "ethernet", "property_set": null, "role": "to_generic", "speed": "10G", "tags": null } }, { "steve": { "id": "my_esi_001_leaf1<->server12(ae1)[1]", "type": "link", "label": "my_esi_001_leaf1<->server12(ae1)[1]", "deploy_mode": "deploy", "group_label": "ae1", "link_type": "ethernet", "property_set": null, "role": "to_generic", "speed": "10G", "tags": null } }, { "steve": { "id": "my_esi_001_leaf_pair1<->server12(ae1)", "type": "link", "label": "my_esi_001_leaf_pair1<->server12(ae1)", "deploy_mode": "deploy", "group_label": "ae1", "link_type": "aggregate_link", "property_set": null, "role": "to_generic", "speed": null, "tags": null } } ] }

However, when getting the interface ID using apstra_datacenter_interfaces_by_link_tag, only the leaf-pair interface is captured by the resource...

data.apstra_datacenter_interfaces_by_link_tag.x:

data "apstra_datacenter_interfaces_by_link_tag" "x" { blueprint_id = "9c5b4b19-4689-4e50-b0a0-bdf4afddeba0" graph_query = "match(match(node(type='tag',label='agg-link').out(type='tag').node(type='link',name='n_link')),node(name='nlink').in(type='link').node(type='interface',if_type='ethernet',name='n_phyinterface').in(type='hosted_interfaces').node(type='system',system_type='switch'),optional(node(name='n_phyinterface').in(type='composed_of').node(type='interface',name='n_lag_interface')),optional(node(name='n_laginterface').in(type='composed_of').node(type='interface',name='n_mlag_interface')))" ids = [ "mLDi9yJfnMyWIL3zFFg", <<<<< only 1 interface ID is captured ] tags = [ "agg-link", ] }

It should probably be mentioned in the documentation that this is the specific use case for apstra_datacenter_interfaces_by_link_tag.

Will

chrismarget-j commented 3 months ago

It almost seems like apstra_datacenter_interfaces_by_link_tag was created for this exact use case

😉

This causes 3 links to be tagged, yet apstra_datacenter_interfaces_by_link_tag only captures the link ID of an interface associated with one of those links.....and it happens to be the right one based on its graph query. Nice!

I don't remember all of the details, but I definitely fiddled around with that graph query until it was working just right.

You might also be interested in this: https://github.com/chrismarget/terraform-modules

It should be possible to invoke it directly from Github:

module "interface_tag" {
  source = "git::https://github.com/chrismarget/terraform-modules.git//apstra_interfaces_by_link_tag"
  ## I had some trouble with the syntax above. It works with terraform 1.9.0, but not with some earlier versions I tried.
  blueprint_id = "e38a9808-6bbf-470d-82f1-f19e33d76c98"
  tags = ["a", "b"]
}

I think my intention with this module was to switch the tags logic from "match all" to "match any".

chrismarget-j commented 2 months ago

Closing - I think we worked through this one in the chat history.