From 093a6d26558786504938ee3c21dd0cb45c6a279b Mon Sep 17 00:00:00 2001 From: Chris Marget Date: Wed, 30 Aug 2023 19:32:04 -0400 Subject: [PATCH 1/3] convert as and gs `links` from map to set --- apstra/design/rack_type_access_switch.go | 64 +++++----- apstra/design/rack_type_generic_system.go | 65 +++++----- apstra/design/rack_type_link.go | 29 ++++- apstra/resource_rack_type.go | 138 ++++++++++++++++++++++ 4 files changed, 215 insertions(+), 81 deletions(-) diff --git a/apstra/design/rack_type_access_switch.go b/apstra/design/rack_type_access_switch.go index 1fa2de70..e1e1714a 100644 --- a/apstra/design/rack_type_access_switch.go +++ b/apstra/design/rack_type_access_switch.go @@ -6,7 +6,6 @@ import ( "github.com/Juniper/apstra-go-sdk/apstra" "github.com/Juniper/terraform-provider-apstra/apstra/utils" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" - "github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" @@ -41,7 +40,7 @@ type AccessSwitch struct { EsiLagInfo types.Object `tfsdk:"esi_lag_info"` RedundancyProtocol types.String `tfsdk:"redundancy_protocol"` Count types.Int64 `tfsdk:"count"` - Links types.Map `tfsdk:"links"` + Links types.Set `tfsdk:"links"` TagIds types.Set `tfsdk:"tag_ids"` Tags types.Set `tfsdk:"tags"` } @@ -70,10 +69,9 @@ func (o AccessSwitch) DataSourceAttributes() map[string]dataSourceSchema.Attribu MarkdownDescription: "Count of Access Switches of this type.", Computed: true, }, - "links": dataSourceSchema.MapNestedAttribute{ + "links": dataSourceSchema.SetNestedAttribute{ MarkdownDescription: "Details links from this Access Switch to upstream switches within this Rack Type.", Computed: true, - Validators: []validator.Map{mapvalidator.SizeAtLeast(1)}, NestedObject: dataSourceSchema.NestedAttributeObject{ Attributes: RackLink{}.DataSourceAttributes(), }, @@ -119,10 +117,10 @@ func (o AccessSwitch) ResourceAttributes() map[string]resourceSchema.Attribute { Required: true, Validators: []validator.Int64{int64validator.AtLeast(1)}, }, - "links": resourceSchema.MapNestedAttribute{ + "links": resourceSchema.SetNestedAttribute{ MarkdownDescription: "Each Access Switch is required to have at least one Link to a Leaf Switch.", Required: true, - Validators: []validator.Map{mapvalidator.SizeAtLeast(1)}, + Validators: []validator.Set{setvalidator.SizeAtLeast(1)}, NestedObject: resourceSchema.NestedAttributeObject{ Attributes: RackLink{}.ResourceAttributes(), }, @@ -168,7 +166,7 @@ func (o AccessSwitch) ResourceAttributesNested() map[string]resourceSchema.Attri MarkdownDescription: "Number of Access Switches of this type.", Computed: true, }, - "links": resourceSchema.MapNestedAttribute{ + "links": resourceSchema.SetNestedAttribute{ MarkdownDescription: "Each Access Switch is required to have at least one Link to a Leaf Switch.", Computed: true, NestedObject: resourceSchema.NestedAttributeObject{ @@ -197,7 +195,7 @@ func (o AccessSwitch) AttrTypes() map[string]attr.Type { "esi_lag_info": types.ObjectType{AttrTypes: EsiLagInfo{}.AttrTypes()}, "redundancy_protocol": types.StringType, "count": types.Int64Type, - "links": types.MapType{ElemType: types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}}, + "links": types.SetType{ElemType: types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}}, "tag_ids": types.SetType{ElemType: types.StringType}, "tags": types.SetType{ElemType: types.ObjectType{AttrTypes: Tag{}.AttrTypes()}}, } @@ -217,20 +215,14 @@ func (o *AccessSwitch) Request(ctx context.Context, path path.Path, rack *RackTy } linkRequests := make([]apstra.RackLinkRequest, len(links)) - i := 0 - for name, link := range links { + for i, link := range links { link.LagMode = types.StringValue(lacpActive) - lr := link.Request(ctx, path.AtName("links").AtMapKey(name), rack, diags) - if diags.HasError() { - return nil - } - lr.Label = name + lr := link.Request(ctx, path.AtName("links").AtListIndex(i), rack, diags) if diags.HasError() { return nil } linkRequests[i] = *lr - i++ } tagIds := make([]apstra.ObjectId, len(o.TagIds.Elements())) @@ -265,22 +257,21 @@ func (o *AccessSwitch) LoadApiData(ctx context.Context, in *apstra.RackElementAc o.EsiLagInfo = NewEsiLagInfo(ctx, in.EsiLagInfo, diags) o.RedundancyProtocol = utils.StringValueWithNull(ctx, in.RedundancyProtocol.String(), apstra.AccessRedundancyProtocolNone.String(), diags) o.Count = types.Int64Value(int64(in.InstanceCount)) - o.Links = NewLinkMap(ctx, in.Links, diags) + o.Links = NewLinkSet(ctx, in.Links, diags) o.TagIds = types.SetNull(types.StringType) o.Tags = NewTagSet(ctx, in.Tags, diags) } -func (o *AccessSwitch) GetLinks(ctx context.Context, diags *diag.Diagnostics) map[string]RackLink { - links := make(map[string]RackLink, len(o.Links.Elements())) - d := o.Links.ElementsAs(ctx, &links, false) - diags.Append(d...) +func (o *AccessSwitch) GetLinks(ctx context.Context, diags *diag.Diagnostics) []RackLink { + links := make([]RackLink, len(o.Links.Elements())) + diags.Append(o.Links.ElementsAs(ctx, &links, false)...) if diags.HasError() { return nil } // copy the link name from the map key into the object's Name field - for name, link := range links { - links[name] = link + for i, link := range links { + links[i] = link } return links } @@ -294,30 +285,29 @@ func (o *AccessSwitch) CopyWriteOnlyElements(ctx context.Context, src *AccessSwi o.LogicalDeviceId = types.StringValue(src.LogicalDeviceId.ValueString()) o.TagIds = utils.SetValueOrNull(ctx, types.StringType, src.TagIds.Elements(), diags) - var d diag.Diagnostics - - srcLinks := make(map[string]RackLink, len(src.Links.Elements())) - d = src.Links.ElementsAs(ctx, &srcLinks, false) - diags.Append(d...) + // extract the source links because we need the tag IDs + srcLinks := make([]RackLink, len(src.Links.Elements())) + diags.Append(src.Links.ElementsAs(ctx, &srcLinks, false)...) if diags.HasError() { return } - dstLinks := make(map[string]RackLink, len(o.Links.Elements())) - d = o.Links.ElementsAs(ctx, &dstLinks, false) - diags.Append(d...) + // extract the destination links because we'll copy the tag IDs here + dstLinks := make([]RackLink, len(o.Links.Elements())) + diags.Append(o.Links.ElementsAs(ctx, &dstLinks, false)...) if diags.HasError() { return } - for name, dstLink := range dstLinks { - if srcLink, ok := srcLinks[name]; ok { - dstLink.CopyWriteOnlyElements(ctx, &srcLink, diags) - dstLinks[name] = dstLink - } + // copy from each source to each destination + for i := range dstLinks[:utils.Min(len(srcLinks), len(dstLinks))] { + dstLinks[i].CopyWriteOnlyElements(ctx, &srcLinks[i], diags) + } + if diags.HasError() { + return } - o.Links = utils.MapValueOrNull(ctx, types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}, dstLinks, diags) + o.Links = utils.SetValueOrNull(ctx, types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}, dstLinks, diags) if diags.HasError() { return } diff --git a/apstra/design/rack_type_generic_system.go b/apstra/design/rack_type_generic_system.go index 85938475..be322d0f 100644 --- a/apstra/design/rack_type_generic_system.go +++ b/apstra/design/rack_type_generic_system.go @@ -6,7 +6,6 @@ import ( "github.com/Juniper/apstra-go-sdk/apstra" "github.com/Juniper/terraform-provider-apstra/apstra/utils" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" - "github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" @@ -34,7 +33,7 @@ type GenericSystem struct { PortChannelIdMin types.Int64 `tfsdk:"port_channel_id_min"` PortChannelIdMax types.Int64 `tfsdk:"port_channel_id_max"` Count types.Int64 `tfsdk:"count"` - Links types.Map `tfsdk:"links"` + Links types.Set `tfsdk:"links"` TagIds types.Set `tfsdk:"tag_ids"` Tags types.Set `tfsdk:"tags"` } @@ -62,10 +61,9 @@ func (o GenericSystem) DataSourceAttributes() map[string]dataSourceSchema.Attrib MarkdownDescription: "Number of Generic Systems of this type.", Computed: true, }, - "links": dataSourceSchema.MapNestedAttribute{ + "links": dataSourceSchema.SetNestedAttribute{ MarkdownDescription: "Details links from this Generic System to upstream switches within this Rack Type.", Computed: true, - Validators: []validator.Map{mapvalidator.SizeAtLeast(1)}, NestedObject: dataSourceSchema.NestedAttributeObject{ Attributes: RackLink{}.DataSourceAttributes(), }, @@ -122,10 +120,10 @@ func (o GenericSystem) ResourceAttributes() map[string]resourceSchema.Attribute Required: true, Validators: []validator.Int64{int64validator.AtLeast(1)}, }, - "links": resourceSchema.MapNestedAttribute{ + "links": resourceSchema.SetNestedAttribute{ MarkdownDescription: "Each Generic System is required to have at least one Link to a Leaf Switch or Access Switch.", Required: true, - Validators: []validator.Map{mapvalidator.SizeAtLeast(1)}, + Validators: []validator.Set{setvalidator.SizeAtLeast(1)}, NestedObject: resourceSchema.NestedAttributeObject{ Attributes: RackLink{}.ResourceAttributes(), }, @@ -169,7 +167,7 @@ func (o GenericSystem) ResourceAttributesNested() map[string]resourceSchema.Attr MarkdownDescription: "Number of Generic Systems of this type.", Computed: true, }, - "links": resourceSchema.MapNestedAttribute{ + "links": resourceSchema.SetNestedAttribute{ MarkdownDescription: "Each Generic System is required to have at least one Link to a Leaf Switch or Access Switch.", Computed: true, NestedObject: resourceSchema.NestedAttributeObject{ @@ -198,7 +196,7 @@ func (o GenericSystem) AttrTypes() map[string]attr.Type { "port_channel_id_min": types.Int64Type, "port_channel_id_max": types.Int64Type, "count": types.Int64Type, - "links": types.MapType{ElemType: types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}}, + "links": types.SetType{ElemType: types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}}, "tag_ids": types.SetType{ElemType: types.StringType}, "tags": types.SetType{ElemType: types.ObjectType{AttrTypes: Tag{}.AttrTypes()}}, } @@ -219,19 +217,13 @@ func (o *GenericSystem) Request(ctx context.Context, path path.Path, rack *RackT } linkRequests := make([]apstra.RackLinkRequest, len(links)) - i := 0 - for name, link := range links { - lr := link.Request(ctx, path.AtName("links").AtMapKey(name), rack, diags) - if diags.HasError() { - return nil - } - lr.Label = name + for i, link := range links { + lr := link.Request(ctx, path.AtName("links").AtListIndex(i), rack, diags) if diags.HasError() { return nil } linkRequests[i] = *lr - i++ } tagIds := make([]apstra.ObjectId, len(o.TagIds.Elements())) @@ -256,22 +248,21 @@ func (o *GenericSystem) LoadApiData(ctx context.Context, in *apstra.RackElementG o.PortChannelIdMin = types.Int64Value(int64(in.PortChannelIdMin)) o.PortChannelIdMax = types.Int64Value(int64(in.PortChannelIdMax)) o.Count = types.Int64Value(int64(in.Count)) - o.Links = NewLinkMap(ctx, in.Links, diags) + o.Links = NewLinkSet(ctx, in.Links, diags) o.TagIds = types.SetNull(types.StringType) o.Tags = NewTagSet(ctx, in.Tags, diags) } -func (o *GenericSystem) GetLinks(ctx context.Context, diags *diag.Diagnostics) map[string]RackLink { - links := make(map[string]RackLink, len(o.Links.Elements())) - d := o.Links.ElementsAs(ctx, &links, false) - diags.Append(d...) +func (o *GenericSystem) GetLinks(ctx context.Context, diags *diag.Diagnostics) []RackLink { + links := make([]RackLink, len(o.Links.Elements())) + diags.Append(o.Links.ElementsAs(ctx, &links, false)...) if diags.HasError() { return nil } // copy the link name from the map key into the object's Name field - for name, link := range links { - links[name] = link + for i, link := range links { + links[i] = link } return links } @@ -285,34 +276,32 @@ func (o *GenericSystem) CopyWriteOnlyElements(ctx context.Context, src *GenericS o.LogicalDeviceId = types.StringValue(src.LogicalDeviceId.ValueString()) o.TagIds = utils.SetValueOrNull(ctx, types.StringType, src.TagIds.Elements(), diags) - var d diag.Diagnostics - - srcLinks := make(map[string]RackLink, len(src.Links.Elements())) - d = src.Links.ElementsAs(ctx, &srcLinks, false) - diags.Append(d...) + // extract the source links because we need the tag IDs + srcLinks := make([]RackLink, len(src.Links.Elements())) + diags.Append(src.Links.ElementsAs(ctx, &srcLinks, false)...) if diags.HasError() { return } - dstLinks := make(map[string]RackLink, len(o.Links.Elements())) - d = o.Links.ElementsAs(ctx, &dstLinks, false) - diags.Append(d...) + // extract the destination links because we'll copy the tag IDs here + dstLinks := make([]RackLink, len(o.Links.Elements())) + diags.Append(o.Links.ElementsAs(ctx, &dstLinks, false)...) if diags.HasError() { return } - for name, dstLink := range dstLinks { - if srcLink, ok := srcLinks[name]; ok { - dstLink.CopyWriteOnlyElements(ctx, &srcLink, diags) - dstLinks[name] = dstLink - } + // copy from each source to each destination + for i := range dstLinks[:utils.Min(len(srcLinks), len(dstLinks))] { + dstLinks[i].CopyWriteOnlyElements(ctx, &srcLinks[i], diags) } - - o.Links = utils.MapValueOrNull(ctx, types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}, dstLinks, diags) if diags.HasError() { return } + o.Links = utils.SetValueOrNull(ctx, types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}, dstLinks, diags) + if diags.HasError() { + return + } } func NewGenericSystemMap(ctx context.Context, in []apstra.RackElementGenericSystem, diags *diag.Diagnostics) types.Map { diff --git a/apstra/design/rack_type_link.go b/apstra/design/rack_type_link.go index e53b70ec..26180b2e 100644 --- a/apstra/design/rack_type_link.go +++ b/apstra/design/rack_type_link.go @@ -21,6 +21,7 @@ import ( ) type RackLink struct { + Name types.String `tfsdk:"name"` TargetSwitchName types.String `tfsdk:"target_switch_name"` LagMode types.String `tfsdk:"lag_mode"` LinksPerSwitch types.Int64 `tfsdk:"links_per_switch"` @@ -32,6 +33,10 @@ type RackLink struct { func (o RackLink) DataSourceAttributes() map[string]dataSourceSchema.Attribute { return map[string]dataSourceSchema.Attribute{ + "name": dataSourceSchema.StringAttribute{ + MarkdownDescription: "Link name", + Computed: true, + }, "target_switch_name": dataSourceSchema.StringAttribute{ MarkdownDescription: "The `name` of the switch in this Rack Type to which this Link connects.", Computed: true, @@ -69,6 +74,11 @@ func (o RackLink) DataSourceAttributes() map[string]dataSourceSchema.Attribute { func (o RackLink) ResourceAttributes() map[string]resourceSchema.Attribute { return map[string]resourceSchema.Attribute{ + "name": resourceSchema.StringAttribute{ + MarkdownDescription: "Link name", + Required: true, + Validators: []validator.String{stringvalidator.LengthAtLeast(1)}, + }, "target_switch_name": resourceSchema.StringAttribute{ MarkdownDescription: "The `name` of the switch in this Rack Type to which this Link connects.", Required: true, @@ -123,6 +133,10 @@ func (o RackLink) ResourceAttributes() map[string]resourceSchema.Attribute { func (o RackLink) ResourceAttributesNested() map[string]resourceSchema.Attribute { return map[string]resourceSchema.Attribute{ + "name": resourceSchema.StringAttribute{ + MarkdownDescription: "Link name", + Computed: true, + }, "target_switch_name": resourceSchema.StringAttribute{ MarkdownDescription: "The `name` of the switch in this Rack Type to which this Link connects.", Computed: true, @@ -160,6 +174,7 @@ func (o RackLink) ResourceAttributesNested() map[string]resourceSchema.Attribute func (o RackLink) AttrTypes() map[string]attr.Type { return map[string]attr.Type{ + "name": types.StringType, "target_switch_name": types.StringType, "lag_mode": types.StringType, "links_per_switch": types.Int64Type, @@ -217,6 +232,7 @@ func (o *RackLink) Request(ctx context.Context, path path.Path, rack *RackType, } return &apstra.RackLinkRequest{ + Label: o.Name.ValueString(), Tags: tagIds, LinkPerSwitchCount: linksPerSwitch, LinkSpeed: apstra.LogicalDevicePortSpeed(o.Speed.ValueString()), @@ -228,6 +244,7 @@ func (o *RackLink) Request(ctx context.Context, path path.Path, rack *RackType, } func (o *RackLink) LoadApiData(ctx context.Context, in *apstra.RackLink, diags *diag.Diagnostics) { + o.Name = types.StringValue(in.Label) o.TargetSwitchName = types.StringValue(in.TargetSwitchLabel) o.LinksPerSwitch = types.Int64Value(int64(in.LinkPerSwitchCount)) o.Speed = types.StringValue(string(in.LinkSpeed)) @@ -272,16 +289,16 @@ func (o *RackLink) LinkAttachmentType(upstreamRedundancyMode fmt.Stringer, _ *di return apstra.RackLinkAttachmentTypeSingle } -func NewLinkMap(ctx context.Context, in []apstra.RackLink, diags *diag.Diagnostics) types.Map { - links := make(map[string]RackLink, len(in)) - for _, link := range in { +func NewLinkSet(ctx context.Context, in []apstra.RackLink, diags *diag.Diagnostics) types.Set { + links := make([]RackLink, len(in)) + for i, link := range in { var l RackLink l.LoadApiData(ctx, &link, diags) if diags.HasError() { - return types.MapNull(types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}) + return types.SetNull(types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}) } - links[link.Label] = l + links[i] = l } - return utils.MapValueOrNull(ctx, types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}, links, diags) + return utils.SetValueOrNull(ctx, types.ObjectType{AttrTypes: RackLink{}.AttrTypes()}, links, diags) } diff --git a/apstra/resource_rack_type.go b/apstra/resource_rack_type.go index a7a493ac..1c7eb6ee 100644 --- a/apstra/resource_rack_type.go +++ b/apstra/resource_rack_type.go @@ -2,15 +2,18 @@ package tfapstra import ( "context" + "fmt" "github.com/Juniper/apstra-go-sdk/apstra" "github.com/Juniper/terraform-provider-apstra/apstra/design" "github.com/Juniper/terraform-provider-apstra/apstra/utils" + "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/types" ) var _ resource.ResourceWithConfigure = &resourceRackType{} +var _ resource.ResourceWithValidateConfig = &resourceRackType{} type resourceRackType struct { client *apstra.Client @@ -31,6 +34,141 @@ func (o *resourceRackType) Schema(_ context.Context, _ resource.SchemaRequest, r } } +func (o *resourceRackType) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) { + // Retrieve values from config + var config design.RackType + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + // access switches must have a value + if config.AccessSwitches.IsUnknown() { + return // cannot proceed + } + + // each access switch must have a value + for _, accessSwitch := range config.AccessSwitches.Elements() { + if accessSwitch.IsUnknown() { + return // cannot proceed + } + } + + // extract access switches + accessSwitches := make(map[string]design.AccessSwitch) + resp.Diagnostics.Append(config.AccessSwitches.ElementsAs(ctx, &accessSwitches, false)...) + if resp.Diagnostics.HasError() { + return + } + + // check each access switch + for name, accessSwitch := range accessSwitches { + // links must have a value + if accessSwitch.Links.IsUnknown() { + return // cannot proceed + } + + // each link must have a value + for _, link := range accessSwitch.Links.Elements() { + if link.IsUnknown() { + return // cannot proceed + } + } + + // extract links from access switches + var links []design.RackLink + resp.Diagnostics.Append(accessSwitch.Links.ElementsAs(ctx, &links, false)...) + if resp.Diagnostics.HasError() { + return + } + + // map keyed by link name to ensure names are unique + linkNameMap := make(map[string]bool, len(links)) + + // check each link + for _, link := range links { + // link name must have a value + if link.Name.IsNull() { + return // cannot proceed + } + + if linkNameMap[link.Name.ValueString()] { + // the name has been seen before! + resp.Diagnostics.AddAttributeError( + path.Root("access_switches"), "Link names must be unique", + fmt.Sprintf("Access Switch with name %q has multiple links with name %q", + name, link.Name.ValueString())) + } else { + // save name in the map + linkNameMap[link.Name.ValueString()] = true + } + } + } + + // generic systems must have a value + if config.GenericSystems.IsUnknown() { + return // cannot proceed + } + + // each generic system must have a value + for _, genericSystem := range config.GenericSystems.Elements() { + if genericSystem.IsUnknown() { + return // cannot proceed + } + } + + // extract generic systems + genericSystems := make(map[string]design.GenericSystem) + resp.Diagnostics.Append(config.GenericSystems.ElementsAs(ctx, &genericSystems, false)...) + if resp.Diagnostics.HasError() { + return + } + + // check each generic system + for name, genericSystem := range genericSystems { + // links must have a value + if genericSystem.Links.IsUnknown() { + return // cannot proceed + } + + // each link must have a value + for _, link := range genericSystem.Links.Elements() { + if link.IsUnknown() { + return // cannot proceed + } + } + + // extract links from generic system + var links []design.RackLink + resp.Diagnostics.Append(genericSystem.Links.ElementsAs(ctx, &links, false)...) + if resp.Diagnostics.HasError() { + return + } + + // map keyed by link name to ensure names are unique + linkNameMap := make(map[string]bool, len(links)) + + // check each link + for _, link := range links { + // link name must have a value + if link.Name.IsNull() { + return // cannot proceed + } + + if linkNameMap[link.Name.ValueString()] { + // the name has been seen before! + resp.Diagnostics.AddAttributeError( + path.Root("generic_systems"), "Link names must be unique", + fmt.Sprintf("Generic System with name %q has multiple links with name %q", + name, link.Name.ValueString())) + } else { + // save name in the map + linkNameMap[link.Name.ValueString()] = true + } + } + } +} + func (o *resourceRackType) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { // Retrieve values from plan var plan design.RackType From 7809f634031a754045535bace9570e60f91d1391 Mon Sep 17 00:00:00 2001 From: Chris Marget Date: Wed, 30 Aug 2023 19:33:45 -0400 Subject: [PATCH 2/3] make docs --- docs/data-sources/rack_type.md | 6 ++++-- docs/data-sources/template_rack_based.md | 6 ++++-- docs/resources/rack_type.md | 6 ++++-- docs/resources/template_rack_based.md | 6 ++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/data-sources/rack_type.md b/docs/data-sources/rack_type.md index 8295673c..e8455735 100644 --- a/docs/data-sources/rack_type.md +++ b/docs/data-sources/rack_type.md @@ -65,7 +65,7 @@ Read-Only: - `count` (Number) Count of Access Switches of this type. - `esi_lag_info` (Attributes) Interconnect information for Access Switches in ESI-LAG redundancy mode. (see [below for nested schema](#nestedatt--access_switches--esi_lag_info)) -- `links` (Attributes Map) Details links from this Access Switch to upstream switches within this Rack Type. (see [below for nested schema](#nestedatt--access_switches--links)) +- `links` (Attributes Set) Details links from this Access Switch to upstream switches within this Rack Type. (see [below for nested schema](#nestedatt--access_switches--links)) - `logical_device` (Attributes) Logical Device attributes as represented in the Global Catalog. (see [below for nested schema](#nestedatt--access_switches--logical_device)) - `logical_device_id` (String) ID will always be `` in data source contexts. - `redundancy_protocol` (String) Indicates whether 'the switch' is actually a LAG-capable redundant pair and if so, what type. @@ -88,6 +88,7 @@ Read-Only: - `lag_mode` (String) LAG negotiation mode of the Link. - `links_per_switch` (Number) Number of Links to each switch. +- `name` (String) Link name - `speed` (String) Speed of this Link. - `switch_peer` (String) For non-LAG connections to redundant switch pairs, this field selects the target switch. - `tag_ids` (Set of String) IDs will always be `` in data source contexts. @@ -152,7 +153,7 @@ Read-Only: Read-Only: - `count` (Number) Number of Generic Systems of this type. -- `links` (Attributes Map) Details links from this Generic System to upstream switches within this Rack Type. (see [below for nested schema](#nestedatt--generic_systems--links)) +- `links` (Attributes Set) Details links from this Generic System to upstream switches within this Rack Type. (see [below for nested schema](#nestedatt--generic_systems--links)) - `logical_device` (Attributes) Logical Device attributes as represented in the Global Catalog. (see [below for nested schema](#nestedatt--generic_systems--logical_device)) - `logical_device_id` (String) ID will always be `` in data source contexts. - `port_channel_id_max` (Number) Port channel IDs are used when rendering leaf device port-channel configuration towards generic systems. @@ -167,6 +168,7 @@ Read-Only: - `lag_mode` (String) LAG negotiation mode of the Link. - `links_per_switch` (Number) Number of Links to each switch. +- `name` (String) Link name - `speed` (String) Speed of this Link. - `switch_peer` (String) For non-LAG connections to redundant switch pairs, this field selects the target switch. - `tag_ids` (Set of String) IDs will always be `` in data source contexts. diff --git a/docs/data-sources/template_rack_based.md b/docs/data-sources/template_rack_based.md index 917693b8..f30c7661 100644 --- a/docs/data-sources/template_rack_based.md +++ b/docs/data-sources/template_rack_based.md @@ -80,7 +80,7 @@ Read-Only: - `count` (Number) Count of Access Switches of this type. - `esi_lag_info` (Attributes) Interconnect information for Access Switches in ESI-LAG redundancy mode. (see [below for nested schema](#nestedatt--rack_infos--rack_type--access_switches--esi_lag_info)) -- `links` (Attributes Map) Details links from this Access Switch to upstream switches within this Rack Type. (see [below for nested schema](#nestedatt--rack_infos--rack_type--access_switches--links)) +- `links` (Attributes Set) Details links from this Access Switch to upstream switches within this Rack Type. (see [below for nested schema](#nestedatt--rack_infos--rack_type--access_switches--links)) - `logical_device` (Attributes) Logical Device attributes as represented in the Global Catalog. (see [below for nested schema](#nestedatt--rack_infos--rack_type--access_switches--logical_device)) - `logical_device_id` (String) ID will always be `` in data source contexts. - `redundancy_protocol` (String) Indicates whether 'the switch' is actually a LAG-capable redundant pair and if so, what type. @@ -103,6 +103,7 @@ Read-Only: - `lag_mode` (String) LAG negotiation mode of the Link. - `links_per_switch` (Number) Number of Links to each switch. +- `name` (String) Link name - `speed` (String) Speed of this Link. - `switch_peer` (String) For non-LAG connections to redundant switch pairs, this field selects the target switch. - `tag_ids` (Set of String) IDs will always be `` in data source contexts. @@ -167,7 +168,7 @@ Read-Only: Read-Only: - `count` (Number) Number of Generic Systems of this type. -- `links` (Attributes Map) Details links from this Generic System to upstream switches within this Rack Type. (see [below for nested schema](#nestedatt--rack_infos--rack_type--generic_systems--links)) +- `links` (Attributes Set) Details links from this Generic System to upstream switches within this Rack Type. (see [below for nested schema](#nestedatt--rack_infos--rack_type--generic_systems--links)) - `logical_device` (Attributes) Logical Device attributes as represented in the Global Catalog. (see [below for nested schema](#nestedatt--rack_infos--rack_type--generic_systems--logical_device)) - `logical_device_id` (String) ID will always be `` in data source contexts. - `port_channel_id_max` (Number) Port channel IDs are used when rendering leaf device port-channel configuration towards generic systems. @@ -182,6 +183,7 @@ Read-Only: - `lag_mode` (String) LAG negotiation mode of the Link. - `links_per_switch` (Number) Number of Links to each switch. +- `name` (String) Link name - `speed` (String) Speed of this Link. - `switch_peer` (String) For non-LAG connections to redundant switch pairs, this field selects the target switch. - `tag_ids` (Set of String) IDs will always be `` in data source contexts. diff --git a/docs/resources/rack_type.md b/docs/resources/rack_type.md index 34eb445b..ffdafb3d 100644 --- a/docs/resources/rack_type.md +++ b/docs/resources/rack_type.md @@ -161,7 +161,7 @@ Read-Only: Required: - `count` (Number) Number of Access Switches of this type. -- `links` (Attributes Map) Each Access Switch is required to have at least one Link to a Leaf Switch. (see [below for nested schema](#nestedatt--access_switches--links)) +- `links` (Attributes Set) Each Access Switch is required to have at least one Link to a Leaf Switch. (see [below for nested schema](#nestedatt--access_switches--links)) - `logical_device_id` (String) Apstra Object ID of the Logical Device used to model this Access Switch. Optional: @@ -180,6 +180,7 @@ Read-Only: Required: +- `name` (String) Link name - `speed` (String) Speed of this Link. - `target_switch_name` (String) The `name` of the switch in this Rack Type to which this Link connects. @@ -267,7 +268,7 @@ Read-Only: Required: - `count` (Number) Number of Generic Systems of this type. -- `links` (Attributes Map) Each Generic System is required to have at least one Link to a Leaf Switch or Access Switch. (see [below for nested schema](#nestedatt--generic_systems--links)) +- `links` (Attributes Set) Each Generic System is required to have at least one Link to a Leaf Switch or Access Switch. (see [below for nested schema](#nestedatt--generic_systems--links)) - `logical_device_id` (String) Apstra Object ID of the Logical Device used to model this Generic System. Optional: @@ -286,6 +287,7 @@ Read-Only: Required: +- `name` (String) Link name - `speed` (String) Speed of this Link. - `target_switch_name` (String) The `name` of the switch in this Rack Type to which this Link connects. diff --git a/docs/resources/template_rack_based.md b/docs/resources/template_rack_based.md index 24f2819c..334e2043 100644 --- a/docs/resources/template_rack_based.md +++ b/docs/resources/template_rack_based.md @@ -91,7 +91,7 @@ Read-Only: - `count` (Number) Number of Access Switches of this type. - `esi_lag_info` (Attributes) Defines connectivity between ESI LAG peers when `redundancy_protocol` is set to `esi`. (see [below for nested schema](#nestedatt--rack_infos--rack_type--access_switches--esi_lag_info)) -- `links` (Attributes Map) Each Access Switch is required to have at least one Link to a Leaf Switch. (see [below for nested schema](#nestedatt--rack_infos--rack_type--access_switches--links)) +- `links` (Attributes Set) Each Access Switch is required to have at least one Link to a Leaf Switch. (see [below for nested schema](#nestedatt--rack_infos--rack_type--access_switches--links)) - `logical_device` (Attributes) Logical Device attributes cloned from the Global Catalog at creation time. (see [below for nested schema](#nestedatt--rack_infos--rack_type--access_switches--logical_device)) - `logical_device_id` (String) ID will always be `` in nested contexts. - `redundancy_protocol` (String) Indicates whether the switch is a redundant pair. @@ -114,6 +114,7 @@ Read-Only: - `lag_mode` (String) LAG negotiation mode of the Link. - `links_per_switch` (Number) Number of Links to each switch. +- `name` (String) Link name - `speed` (String) Speed of this Link. - `switch_peer` (String) For non-lAG connections to redundant switch pairs, this field selects the target switch. - `tag_ids` (Set of String) IDs will always be `` in nested contexts. @@ -184,7 +185,7 @@ Read-Only: Read-Only: - `count` (Number) Number of Generic Systems of this type. -- `links` (Attributes Map) Each Generic System is required to have at least one Link to a Leaf Switch or Access Switch. (see [below for nested schema](#nestedatt--rack_infos--rack_type--generic_systems--links)) +- `links` (Attributes Set) Each Generic System is required to have at least one Link to a Leaf Switch or Access Switch. (see [below for nested schema](#nestedatt--rack_infos--rack_type--generic_systems--links)) - `logical_device` (Attributes) Logical Device attributes cloned from the Global Catalog at creation time. (see [below for nested schema](#nestedatt--rack_infos--rack_type--generic_systems--logical_device)) - `logical_device_id` (String) ID will always be `` in nested contexts. - `port_channel_id_max` (Number) Port channel IDs are used when rendering leaf device port-channel configuration towards generic systems. @@ -197,6 +198,7 @@ Read-Only: Required: +- `name` (String) Link name - `speed` (String) Speed of this Link. - `target_switch_name` (String) The `name` of the switch in this Rack Type to which this Link connects. From 8d088df103ef181d4eb5076c82b97c01f8b585c0 Mon Sep 17 00:00:00 2001 From: Chris Marget Date: Thu, 31 Aug 2023 10:30:42 -0400 Subject: [PATCH 3/3] eliminate unnecessary `GetLinks()` method --- apstra/design/rack_type_access_switch.go | 17 ++--------------- apstra/design/rack_type_generic_system.go | 17 ++--------------- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/apstra/design/rack_type_access_switch.go b/apstra/design/rack_type_access_switch.go index e1e1714a..222ff0ba 100644 --- a/apstra/design/rack_type_access_switch.go +++ b/apstra/design/rack_type_access_switch.go @@ -209,7 +209,8 @@ func (o *AccessSwitch) Request(ctx context.Context, path path.Path, rack *RackTy lacpActive := apstra.RackLinkLagModeActive.String() - links := o.GetLinks(ctx, diags) + links := make([]RackLink, len(o.Links.Elements())) + diags.Append(o.Links.ElementsAs(ctx, &links, false)...) if diags.HasError() { return nil } @@ -262,20 +263,6 @@ func (o *AccessSwitch) LoadApiData(ctx context.Context, in *apstra.RackElementAc o.Tags = NewTagSet(ctx, in.Tags, diags) } -func (o *AccessSwitch) GetLinks(ctx context.Context, diags *diag.Diagnostics) []RackLink { - links := make([]RackLink, len(o.Links.Elements())) - diags.Append(o.Links.ElementsAs(ctx, &links, false)...) - if diags.HasError() { - return nil - } - - // copy the link name from the map key into the object's Name field - for i, link := range links { - links[i] = link - } - return links -} - func (o *AccessSwitch) CopyWriteOnlyElements(ctx context.Context, src *AccessSwitch, diags *diag.Diagnostics) { if src == nil { diags.AddError(errProviderBug, "AccessSwitch.CopyWriteOnlyElements: attempt to copy from nil source") diff --git a/apstra/design/rack_type_generic_system.go b/apstra/design/rack_type_generic_system.go index be322d0f..dbb1cf52 100644 --- a/apstra/design/rack_type_generic_system.go +++ b/apstra/design/rack_type_generic_system.go @@ -211,7 +211,8 @@ func (o *GenericSystem) Request(ctx context.Context, path path.Path, rack *RackT poIdMaxVal = int(o.PortChannelIdMax.ValueInt64()) } - links := o.GetLinks(ctx, diags) + links := make([]RackLink, len(o.Links.Elements())) + diags.Append(o.Links.ElementsAs(ctx, &links, false)...) if diags.HasError() { return nil } @@ -253,20 +254,6 @@ func (o *GenericSystem) LoadApiData(ctx context.Context, in *apstra.RackElementG o.Tags = NewTagSet(ctx, in.Tags, diags) } -func (o *GenericSystem) GetLinks(ctx context.Context, diags *diag.Diagnostics) []RackLink { - links := make([]RackLink, len(o.Links.Elements())) - diags.Append(o.Links.ElementsAs(ctx, &links, false)...) - if diags.HasError() { - return nil - } - - // copy the link name from the map key into the object's Name field - for i, link := range links { - links[i] = link - } - return links -} - func (o *GenericSystem) CopyWriteOnlyElements(ctx context.Context, src *GenericSystem, diags *diag.Diagnostics) { if src == nil { diags.AddError(errProviderBug, "GenericSystem.CopyWriteOnlyElements: attempt to copy from nil source")