diff --git a/apstra/blueprint/freeform_resource_generator.go b/apstra/blueprint/freeform_resource_generator.go index b352e258..6bfd3a30 100644 --- a/apstra/blueprint/freeform_resource_generator.go +++ b/apstra/blueprint/freeform_resource_generator.go @@ -24,7 +24,7 @@ import ( type FreeformResourceGenerator struct { BlueprintId types.String `tfsdk:"blueprint_id"` Id types.String `tfsdk:"id"` - ResourceType types.String `tfsdk:"type"` + Type types.String `tfsdk:"type"` Name types.String `tfsdk:"name"` Scope types.String `tfsdk:"scope"` AllocatedFrom types.String `tfsdk:"allocated_from"` @@ -63,13 +63,14 @@ func (o FreeformResourceGenerator) DataSourceAttributes() map[string]dataSourceS Validators: []validator.String{stringvalidator.LengthAtLeast(1)}, }, "scope": dataSourceSchema.StringAttribute{ - MarkdownDescription: "Scope the Resource Generator uses for resource generation", - Computed: true, + MarkdownDescription: "Scope is a graph query which selects target nodes for which Resources should be generated.\n" + + "Example: `node('system', name='target', label=aeq('*prod*'))`", + Computed: true, }, "allocated_from": dataSourceSchema.StringAttribute{ - MarkdownDescription: "ID of the node from which this resource generator has been sourced. This could be an ID " + - "of resource generator or another resource (in case of IP or Host IP allocations). " + - "This also can be empty. In that case it is required that value for this resource is provided by the user.", + MarkdownDescription: "Selects the Allocation Group, parent Resource, or Local Resource Pool from which to " + + "source generated Resources. In the case of a Local Resource Pool, this value must be the name (label) " + + "of the pool. Allocation Groups and parent Resources are specified by ID.", Computed: true, }, "container_id": dataSourceSchema.StringAttribute{ @@ -107,40 +108,48 @@ func (o FreeformResourceGenerator) ResourceAttributes() map[string]resourceSchem MarkdownDescription: "Freeform Resource Generator name as shown in the Web UI.", Required: true, Validators: []validator.String{ - stringvalidator.RegexMatches(regexp.MustCompile("^[a-zA-Z0-9.-_]+$"), "name may consist only of the following characters : a-zA-Z0-9.-_"), + stringvalidator.RegexMatches( + regexp.MustCompile("^[a-zA-Z0-9.-_]+$"), + "name may consist only of the following characters : a-zA-Z0-9.-_", + ), }, }, "scope": resourceSchema.StringAttribute{ - MarkdownDescription: "Scope the Resource Generator uses for resource generation.", - Required: true, - Validators: []validator.String{stringvalidator.LengthAtLeast(1)}, + MarkdownDescription: "Scope is a graph query which selects target nodes for which Resources should be generated.\n" + + "Example: `node('system', name='target', label=aeq('*prod*'))`", + Required: true, + Validators: []validator.String{stringvalidator.LengthAtLeast(1)}, }, "allocated_from": resourceSchema.StringAttribute{ - MarkdownDescription: "ID of the node to be used as a source for this resource. This could be an ID " + - "of resource group or another resource (in case of IP or Host IP allocations). " + - "This also can be empty. In that case it is required that value for this resource is provided by the user.", + MarkdownDescription: "Selects the Allocation Group, parent Resource, or Local Resource Pool from which to " + + "source generated Resources. In the case of a Local Resource Pool, this value must be the name (label) " + + "of the pool. Allocation Groups and parent Resources are specified by ID.", Required: true, Validators: []validator.String{stringvalidator.LengthAtLeast(1)}, }, "container_id": resourceSchema.StringAttribute{ - MarkdownDescription: "ID of the group where resources are generated. ", + MarkdownDescription: "ID of the group where Resources are generated. ", Required: true, Validators: []validator.String{stringvalidator.LengthAtLeast(1)}, PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()}, }, "subnet_prefix_len": resourceSchema.Int64Attribute{ - MarkdownDescription: "Length of the subnet for the generated resources, if any.", - Optional: true, + MarkdownDescription: fmt.Sprintf("Length of the subnet for the generated Resources. "+ + "Only applicable when `type` is `%s` or `%s`", + utils.StringersToFriendlyString(apstra.FFResourceTypeIpv4), + utils.StringersToFriendlyString(apstra.FFResourceTypeIpv6), + ), + Optional: true, Validators: []validator.Int64{ int64validator.Between(1, 127), - apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("allocated_from"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeAsn))), - apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("allocated_from"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeHostIpv4))), - apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("allocated_from"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeHostIpv6))), - apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("allocated_from"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeInt))), - apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("allocated_from"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeVlan))), - apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("allocated_from"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeVni))), - apstravalidator.RequiredWhenValueIs(path.MatchRoot("allocated_from"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeIpv4))), - apstravalidator.RequiredWhenValueIs(path.MatchRoot("allocated_from"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeIpv6))), + apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeAsn))), + apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeHostIpv4))), + apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeHostIpv6))), + apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeInt))), + apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeVlan))), + apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeVni))), + apstravalidator.RequiredWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeIpv4))), + apstravalidator.RequiredWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.FFResourceTypeIpv6))), }, }, } @@ -148,14 +157,13 @@ func (o FreeformResourceGenerator) ResourceAttributes() map[string]resourceSchem func (o *FreeformResourceGenerator) Request(_ context.Context, diags *diag.Diagnostics) *apstra.FreeformResourceGeneratorData { var resourceType apstra.FFResourceType - err := utils.ApiStringerFromFriendlyString(&resourceType, o.ResourceType.ValueString()) + err := utils.ApiStringerFromFriendlyString(&resourceType, o.Type.ValueString()) if err != nil { - diags.AddError(fmt.Sprintf("error parsing type %q", o.ResourceType.ValueString()), err.Error()) + diags.AddError(fmt.Sprintf("error parsing type %q", o.Type.ValueString()), err.Error()) } var scopeNodePoolLabel *string var allocatedFrom *apstra.ObjectId - if resourceType == apstra.FFResourceTypeVlan { scopeNodePoolLabel = o.AllocatedFrom.ValueStringPointer() } else { @@ -182,7 +190,7 @@ func (o *FreeformResourceGenerator) Request(_ context.Context, diags *diag.Diagn func (o *FreeformResourceGenerator) LoadApiData(_ context.Context, in *apstra.FreeformResourceGeneratorData, diags *diag.Diagnostics) { o.Name = types.StringValue(in.Label) o.Scope = types.StringValue(in.Scope) - o.ResourceType = types.StringValue(utils.StringersToFriendlyString(in.ResourceType)) + o.Type = types.StringValue(utils.StringersToFriendlyString(in.ResourceType)) if in.ResourceType == apstra.FFResourceTypeVlan { o.AllocatedFrom = types.StringPointerValue(in.ScopeNodePoolLabel) } else { diff --git a/apstra/data_source_freeform_resource_generator.go b/apstra/data_source_freeform_resource_generator.go index 5ecd42cb..9932a11f 100644 --- a/apstra/data_source_freeform_resource_generator.go +++ b/apstra/data_source_freeform_resource_generator.go @@ -32,7 +32,7 @@ func (o *dataSourceFreeformResourceGenerator) Configure(ctx context.Context, req func (o *dataSourceFreeformResourceGenerator) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - MarkdownDescription: docCategoryFreeform + "This data source provides details of a specific Freeform Resource.\n\n" + + MarkdownDescription: docCategoryFreeform + "This data source provides details of a specific Freeform Resource Generator.\n\n" + "At least one optional attribute is required.", Attributes: blueprint.FreeformResourceGenerator{}.DataSourceAttributes(), } @@ -63,8 +63,8 @@ func (o *dataSourceFreeformResourceGenerator) Read(ctx context.Context, req data if utils.IsApstra404(err) { resp.Diagnostics.AddAttributeError( path.Root("id"), - "Freeform Resource not found", - fmt.Sprintf("Freeform Resource with ID %s not found", config.Id)) + "Freeform Resource Generator not found", + fmt.Sprintf("Freeform Resource Generator with ID %s not found", config.Id)) return } case !config.Name.IsNull(): @@ -72,17 +72,17 @@ func (o *dataSourceFreeformResourceGenerator) Read(ctx context.Context, req data if utils.IsApstra404(err) { resp.Diagnostics.AddAttributeError( path.Root("name"), - "Freeform Resource not found", - fmt.Sprintf("Freeform Resource with Name %s not found", config.Name)) + "Freeform Resource Generator not found", + fmt.Sprintf("Freeform Resource Generator with Name %s not found", config.Name)) return } } if err != nil { - resp.Diagnostics.AddError("failed reading Freeform Resource", err.Error()) + resp.Diagnostics.AddError("failed reading Freeform Resource Generator", err.Error()) return } if api.Data == nil { - resp.Diagnostics.AddError("failed reading Freeform Resource", "api response has no payload") + resp.Diagnostics.AddError("failed reading Freeform Resource Generator", "api response has no payload") return } diff --git a/apstra/resource_freeform_resource_generator.go b/apstra/resource_freeform_resource_generator.go index fc5e0988..54764c7b 100644 --- a/apstra/resource_freeform_resource_generator.go +++ b/apstra/resource_freeform_resource_generator.go @@ -35,7 +35,7 @@ func (o *resourceFreeformResourceGenerator) Configure(ctx context.Context, req r func (o *resourceFreeformResourceGenerator) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - MarkdownDescription: docCategoryFreeform + "This resource creates a Resource in a Freeform Blueprint.", + MarkdownDescription: docCategoryFreeform + "This resource creates a Resource Generator in a Freeform Blueprint.", Attributes: blueprint.FreeformResourceGenerator{}.ResourceAttributes(), } } @@ -47,17 +47,23 @@ func (o *resourceFreeformResourceGenerator) ValidateConfig(ctx context.Context, if resp.Diagnostics.HasError() { return } - if config.ResourceType.IsUnknown() || config.SubnetPrefixLen.IsUnknown() { + + // We only compare two values. Validation requires that both be known. + if config.Type.IsUnknown() || config.SubnetPrefixLen.IsUnknown() { return } + + // Extract the type var resourceType apstra.FFResourceType - err := utils.ApiStringerFromFriendlyString(&resourceType, config.ResourceType.ValueString()) + err := utils.ApiStringerFromFriendlyString(&resourceType, config.Type.ValueString()) if err != nil { resp.Diagnostics.AddAttributeError(path.Root("type"), "failed to parse 'type' attribute", err.Error()) return } + + // Catch v6-sized prefix specified when requesting a v4 subnet. if resourceType == apstra.FFResourceTypeIpv4 && config.SubnetPrefixLen.ValueInt64() > 32 { - resp.Diagnostics.AddAttributeError(path.Root("subnet_prefix_len"), " 'subnet_prefix_len' cannot be greater than 32 when 'type' is %s", config.ResourceType.String()) + resp.Diagnostics.AddAttributeError(path.Root("subnet_prefix_len"), " 'subnet_prefix_len' cannot be greater than 32 when 'type' is %s", config.Type.String()) return } } @@ -99,7 +105,7 @@ func (o *resourceFreeformResourceGenerator) Create(ctx context.Context, req reso // Create the resource id, err := bp.CreateResourceGenerator(ctx, request) if err != nil { - resp.Diagnostics.AddError("error creating new Resource", err.Error()) + resp.Diagnostics.AddError("error creating new Resource Generator", err.Error()) return } @@ -120,7 +126,7 @@ func (o *resourceFreeformResourceGenerator) Read(ctx context.Context, req resour bp, err := o.getBpClientFunc(ctx, state.BlueprintId.ValueString()) if err != nil { if utils.IsApstra404(err) { - resp.Diagnostics.AddError(fmt.Sprintf("blueprint %s not found", state.BlueprintId), err.Error()) + resp.State.RemoveResource(ctx) return } resp.Diagnostics.AddError("failed to create blueprint client", err.Error()) @@ -133,7 +139,7 @@ func (o *resourceFreeformResourceGenerator) Read(ctx context.Context, req resour resp.State.RemoveResource(ctx) return } - resp.Diagnostics.AddError("Error retrieving Freeform Resource", err.Error()) + resp.Diagnostics.AddError("Error retrieving Freeform Resource Generator", err.Error()) return } @@ -183,7 +189,7 @@ func (o *resourceFreeformResourceGenerator) Update(ctx context.Context, req reso // Update the Resource err = bp.UpdateResourceGenerator(ctx, apstra.ObjectId(plan.Id.ValueString()), request) if err != nil { - resp.Diagnostics.AddError("error updating Freeform Resource", err.Error()) + resp.Diagnostics.AddError("error updating Freeform Resource Generator", err.Error()) return } diff --git a/docs/data-sources/freeform_resource_generator.md b/docs/data-sources/freeform_resource_generator.md index d627d2e8..8aa332f2 100644 --- a/docs/data-sources/freeform_resource_generator.md +++ b/docs/data-sources/freeform_resource_generator.md @@ -2,13 +2,13 @@ page_title: "apstra_freeform_resource_generator Data Source - terraform-provider-apstra" subcategory: "Reference Design: Freeform" description: |- - This data source provides details of a specific Freeform Resource. + This data source provides details of a specific Freeform Resource Generator. At least one optional attribute is required. --- # apstra_freeform_resource_generator (Data Source) -This data source provides details of a specific Freeform Resource. +This data source provides details of a specific Freeform Resource Generator. At least one optional attribute is required. @@ -21,54 +21,54 @@ At least one optional attribute is required. # # After creating the Resource Generator, the data source is invoked to look up # the details. -resource "apstra_freeform_resource_group" "fizz_grp" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "fizz_grp" -} -resource "apstra_asn_pool" "rfc5398" { - name = "RFC5398 ASN" - ranges = [ - { - first = 64496 - last = 64511 - }, - { - first = 65536 - last = 65551 - }, - ] +# Create a resource group in a preexisting blueprint. +resource "apstra_freeform_resource_group" "fizz_grp" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "fizz_grp" } -resource "apstra_freeform_alloc_group" "test" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "test_alloc_group2" - type = "asn" - pool_ids = [apstra_asn_pool.rfc5398.id] +# Create an allocation group in a preexisting blueprint +# using a preexisting ASN pool. +resource "apstra_freeform_allocation_group" "test" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "test_allocation_group2" + type = "asn" + pool_ids = ["Private-64512-65534"] } +# Create a resource generator scoped to target all systems in the blueprint. resource "apstra_freeform_resource_generator" "test_res_gen" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "test_res_gen" - type = "asn" - scope = "node('system', name='target')" - allocated_from = apstra_freeform_alloc_group.test.id - container_id = apstra_freeform_resource_group.fizz_grp.id + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "test_res_gen" + type = "asn" + scope = "node('system', name='target')" + allocated_from = apstra_freeform_allocation_group.test.id + container_id = apstra_freeform_resource_group.fizz_grp.id } +# Invoke the resource generator data source +data "apstra_freeform_resource_generator" "test_res_gen" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + id = apstra_freeform_resource_generator.test_res_gen.id +} +# Output the data source so that it prints on screen +output "test_resource_generator_out" { + value = data.apstra_freeform_resource_generator.test_res_gen +} -# The output looks like: -#test_resource_generator_out = { -# "allocated_from" = "rag_asn_test_alloc_group2" -# "blueprint_id" = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" -# "container_id" = "gPJtXP7_SM31CYWDJ0g" -# "id" = "EkrP9avh6pgqRqRCm44" -# "name" = "test_res_gen" -# "scope" = "node('system', name='target')" -# "subnet_prefix_len" = tonumber(null) -# "type" = "asn" -#} +# The output looks like this: +# test_resource_generator_out = { +# "allocated_from" = "rag_asn_test_allocation_group2" +# "blueprint_id" = "f1b86583-9139-49ed-8a3c-0490253e006e" +# "container_id" = "NbzITYcIjPZN4ZBqS2Q" +# "id" = "pwJ9EOiVR8z6qbj2Ou8" +# "name" = "test_res_gen" +# "scope" = "node('system', name='target')" +# "subnet_prefix_len" = tonumber(null) +# "type" = "asn" +# } ``` @@ -85,8 +85,9 @@ resource "apstra_freeform_resource_generator" "test_res_gen" { ### Read-Only -- `allocated_from` (String) ID of the node from which this resource generator has been sourced. This could be an ID of resource generator or another resource (in case of IP or Host IP allocations). This also can be empty. In that case it is required that value for this resource is provided by the user. +- `allocated_from` (String) Selects the Allocation Group, parent Resource, or Local Resource Pool from which to source generated Resources. In the case of a Local Resource Pool, this value must be the name (label) of the pool. Allocation Groups and parent Resources are specified by ID. - `container_id` (String) ID of the group used to organize the generated resources -- `scope` (String) Scope the Resource Generator uses for resource generation +- `scope` (String) Scope is a graph query which selects target nodes for which Resources should be generated. +Example: `node('system', name='target', label=aeq('*prod*'))` - `subnet_prefix_len` (Number) Length of the subnet for the generated resources, if any. - `type` (String) Type of the Resource Generator diff --git a/docs/resources/freeform_resource_generator.md b/docs/resources/freeform_resource_generator.md index 8aa783c5..b0f4700f 100644 --- a/docs/resources/freeform_resource_generator.md +++ b/docs/resources/freeform_resource_generator.md @@ -2,12 +2,12 @@ page_title: "apstra_freeform_resource_generator Resource - terraform-provider-apstra" subcategory: "Reference Design: Freeform" description: |- - This resource creates a Resource in a Freeform Blueprint. + This resource creates a Resource Generator in a Freeform Blueprint. --- # apstra_freeform_resource_generator (Resource) -This resource creates a Resource in a Freeform Blueprint. +This resource creates a Resource Generator in a Freeform Blueprint. ## Example Usage @@ -18,54 +18,54 @@ This resource creates a Resource in a Freeform Blueprint. # # After creating the Resource Generator, the data source is invoked to look up # the details. -resource "apstra_freeform_resource_group" "fizz_grp" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "fizz_grp" -} -resource "apstra_asn_pool" "rfc5398" { - name = "RFC5398 ASN" - ranges = [ - { - first = 64496 - last = 64511 - }, - { - first = 65536 - last = 65551 - }, - ] +# Create a resource group in a preexisting blueprint. +resource "apstra_freeform_resource_group" "fizz_grp" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "fizz_grp" } -resource "apstra_freeform_alloc_group" "test" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "test_alloc_group2" - type = "asn" - pool_ids = [apstra_asn_pool.rfc5398.id] +# Create an allocation group in a preexisting blueprint +# using a preexisting ASN pool. +resource "apstra_freeform_allocation_group" "test" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "test_allocation_group2" + type = "asn" + pool_ids = ["Private-64512-65534"] } +# Create a resource generator scoped to target all systems in the blueprint. resource "apstra_freeform_resource_generator" "test_res_gen" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "test_res_gen" - type = "asn" - scope = "node('system', name='target')" - allocated_from = apstra_freeform_alloc_group.test.id - container_id = apstra_freeform_resource_group.fizz_grp.id + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "test_res_gen" + type = "asn" + scope = "node('system', name='target')" + allocated_from = apstra_freeform_allocation_group.test.id + container_id = apstra_freeform_resource_group.fizz_grp.id } +# Invoke the resource generator data source +data "apstra_freeform_resource_generator" "test_res_gen" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + id = apstra_freeform_resource_generator.test_res_gen.id +} +# Output the data source so that it prints on screen +output "test_resource_generator_out" { + value = data.apstra_freeform_resource_generator.test_res_gen +} -# The output looks like: -#test_resource_generator_out = { -# "allocated_from" = "rag_asn_test_alloc_group2" -# "blueprint_id" = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" -# "container_id" = "gPJtXP7_SM31CYWDJ0g" -# "id" = "EkrP9avh6pgqRqRCm44" -# "name" = "test_res_gen" -# "scope" = "node('system', name='target')" -# "subnet_prefix_len" = tonumber(null) -# "type" = "asn" -#} +# The output looks like this: +# test_resource_generator_out = { +# "allocated_from" = "rag_asn_test_allocation_group2" +# "blueprint_id" = "f1b86583-9139-49ed-8a3c-0490253e006e" +# "container_id" = "NbzITYcIjPZN4ZBqS2Q" +# "id" = "pwJ9EOiVR8z6qbj2Ou8" +# "name" = "test_res_gen" +# "scope" = "node('system', name='target')" +# "subnet_prefix_len" = tonumber(null) +# "type" = "asn" +# } ``` @@ -73,11 +73,12 @@ resource "apstra_freeform_resource_generator" "test_res_gen" { ### Required -- `allocated_from` (String) ID of the node to be used as a source for this resource. This could be an ID of resource group or another resource (in case of IP or Host IP allocations). This also can be empty. In that case it is required that value for this resource is provided by the user. +- `allocated_from` (String) Selects the Allocation Group, parent Resource, or Local Resource Pool from which to source generated Resources. In the case of a Local Resource Pool, this value must be the name (label) of the pool. Allocation Groups and parent Resources are specified by ID. - `blueprint_id` (String) Apstra Blueprint ID. -- `container_id` (String) ID of the group where resources are generated. +- `container_id` (String) ID of the group where Resources are generated. - `name` (String) Freeform Resource Generator name as shown in the Web UI. -- `scope` (String) Scope the Resource Generator uses for resource generation. +- `scope` (String) Scope is a graph query which selects target nodes for which Resources should be generated. +Example: `node('system', name='target', label=aeq('*prod*'))` - `type` (String) type of the Resource Generator, must be one of : - `asn` - `host_ipv4` @@ -90,7 +91,7 @@ resource "apstra_freeform_resource_generator" "test_res_gen" { ### Optional -- `subnet_prefix_len` (Number) Length of the subnet for the generated resources, if any. +- `subnet_prefix_len` (Number) Length of the subnet for the generated Resources. Only applicable when `type` is `ipv4` or `ipv6` ### Read-Only diff --git a/examples/data-sources/apstra_freeform_resource_generator/example.tf b/examples/data-sources/apstra_freeform_resource_generator/example.tf index a6de71d9..3f14f5f5 100644 --- a/examples/data-sources/apstra_freeform_resource_generator/example.tf +++ b/examples/data-sources/apstra_freeform_resource_generator/example.tf @@ -3,51 +3,51 @@ # # After creating the Resource Generator, the data source is invoked to look up # the details. -resource "apstra_freeform_resource_group" "fizz_grp" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "fizz_grp" -} -resource "apstra_asn_pool" "rfc5398" { - name = "RFC5398 ASN" - ranges = [ - { - first = 64496 - last = 64511 - }, - { - first = 65536 - last = 65551 - }, - ] +# Create a resource group in a preexisting blueprint. +resource "apstra_freeform_resource_group" "fizz_grp" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "fizz_grp" } -resource "apstra_freeform_alloc_group" "test" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "test_alloc_group2" - type = "asn" - pool_ids = [apstra_asn_pool.rfc5398.id] +# Create an allocation group in a preexisting blueprint +# using a preexisting ASN pool. +resource "apstra_freeform_allocation_group" "test" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "test_allocation_group2" + type = "asn" + pool_ids = ["Private-64512-65534"] } +# Create a resource generator scoped to target all systems in the blueprint. resource "apstra_freeform_resource_generator" "test_res_gen" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "test_res_gen" - type = "asn" - scope = "node('system', name='target')" - allocated_from = apstra_freeform_alloc_group.test.id - container_id = apstra_freeform_resource_group.fizz_grp.id + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "test_res_gen" + type = "asn" + scope = "node('system', name='target')" + allocated_from = apstra_freeform_allocation_group.test.id + container_id = apstra_freeform_resource_group.fizz_grp.id } +# Invoke the resource generator data source +data "apstra_freeform_resource_generator" "test_res_gen" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + id = apstra_freeform_resource_generator.test_res_gen.id +} +# Output the data source so that it prints on screen +output "test_resource_generator_out" { + value = data.apstra_freeform_resource_generator.test_res_gen +} -# The output looks like: -#test_resource_generator_out = { -# "allocated_from" = "rag_asn_test_alloc_group2" -# "blueprint_id" = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" -# "container_id" = "gPJtXP7_SM31CYWDJ0g" -# "id" = "EkrP9avh6pgqRqRCm44" -# "name" = "test_res_gen" -# "scope" = "node('system', name='target')" -# "subnet_prefix_len" = tonumber(null) -# "type" = "asn" -#} +# The output looks like this: +# test_resource_generator_out = { +# "allocated_from" = "rag_asn_test_allocation_group2" +# "blueprint_id" = "f1b86583-9139-49ed-8a3c-0490253e006e" +# "container_id" = "NbzITYcIjPZN4ZBqS2Q" +# "id" = "pwJ9EOiVR8z6qbj2Ou8" +# "name" = "test_res_gen" +# "scope" = "node('system', name='target')" +# "subnet_prefix_len" = tonumber(null) +# "type" = "asn" +# } diff --git a/examples/resources/apstra_freeform_resource_generator/example.tf b/examples/resources/apstra_freeform_resource_generator/example.tf index a6de71d9..3f14f5f5 100644 --- a/examples/resources/apstra_freeform_resource_generator/example.tf +++ b/examples/resources/apstra_freeform_resource_generator/example.tf @@ -3,51 +3,51 @@ # # After creating the Resource Generator, the data source is invoked to look up # the details. -resource "apstra_freeform_resource_group" "fizz_grp" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "fizz_grp" -} -resource "apstra_asn_pool" "rfc5398" { - name = "RFC5398 ASN" - ranges = [ - { - first = 64496 - last = 64511 - }, - { - first = 65536 - last = 65551 - }, - ] +# Create a resource group in a preexisting blueprint. +resource "apstra_freeform_resource_group" "fizz_grp" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "fizz_grp" } -resource "apstra_freeform_alloc_group" "test" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "test_alloc_group2" - type = "asn" - pool_ids = [apstra_asn_pool.rfc5398.id] +# Create an allocation group in a preexisting blueprint +# using a preexisting ASN pool. +resource "apstra_freeform_allocation_group" "test" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "test_allocation_group2" + type = "asn" + pool_ids = ["Private-64512-65534"] } +# Create a resource generator scoped to target all systems in the blueprint. resource "apstra_freeform_resource_generator" "test_res_gen" { - blueprint_id = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" - name = "test_res_gen" - type = "asn" - scope = "node('system', name='target')" - allocated_from = apstra_freeform_alloc_group.test.id - container_id = apstra_freeform_resource_group.fizz_grp.id + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + name = "test_res_gen" + type = "asn" + scope = "node('system', name='target')" + allocated_from = apstra_freeform_allocation_group.test.id + container_id = apstra_freeform_resource_group.fizz_grp.id } +# Invoke the resource generator data source +data "apstra_freeform_resource_generator" "test_res_gen" { + blueprint_id = "f1b86583-9139-49ed-8a3c-0490253e006e" + id = apstra_freeform_resource_generator.test_res_gen.id +} +# Output the data source so that it prints on screen +output "test_resource_generator_out" { + value = data.apstra_freeform_resource_generator.test_res_gen +} -# The output looks like: -#test_resource_generator_out = { -# "allocated_from" = "rag_asn_test_alloc_group2" -# "blueprint_id" = "631f8832-ae59-40ca-b4f6-9c19b411aeaf" -# "container_id" = "gPJtXP7_SM31CYWDJ0g" -# "id" = "EkrP9avh6pgqRqRCm44" -# "name" = "test_res_gen" -# "scope" = "node('system', name='target')" -# "subnet_prefix_len" = tonumber(null) -# "type" = "asn" -#} +# The output looks like this: +# test_resource_generator_out = { +# "allocated_from" = "rag_asn_test_allocation_group2" +# "blueprint_id" = "f1b86583-9139-49ed-8a3c-0490253e006e" +# "container_id" = "NbzITYcIjPZN4ZBqS2Q" +# "id" = "pwJ9EOiVR8z6qbj2Ou8" +# "name" = "test_res_gen" +# "scope" = "node('system', name='target')" +# "subnet_prefix_len" = tonumber(null) +# "type" = "asn" +# }