Now works - more or less fully
This commit is contained in:
1 parent
fb8d468943
commit
92701aab92
13 files changed
+1938
-12
No files matched your search
@@ -0,0 +1,273 @@
|
||||
// Port of LLDPConfig.html's "Global Mode" table only. The page also has a
|
||||
// per-port "Interface Mode" table (Transmit/Receive Enable etc, one row per
|
||||
// port with per-port field names like "1.0.24.v_2_1_2") -- that's a
|
||||
// separate, more involved write target (needs the same per-port-field-name
|
||||
// handling as resource_port.go) and isn't built yet; only requested was
|
||||
// "LLDP Configuration" which maps to the global settings.
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
|
||||
"terraform-provider-hpe1810/internal/provider/client"
|
||||
)
|
||||
|
||||
const (
|
||||
lldpConfigPath = "/LLDPConfig.html"
|
||||
lldpGlobalModeCaption = "Global Mode"
|
||||
lldpTransmitIntervalLabel = "Transmit Interval"
|
||||
lldpTransmitHoldLabel = "Transmit Hold"
|
||||
lldpReinitDelayLabel = "Re-Initialization Delay"
|
||||
lldpNotificationIntervalLabel = "Notification Interval"
|
||||
)
|
||||
|
||||
var (
|
||||
_ resource.Resource = &lldpConfigurationResource{}
|
||||
_ resource.ResourceWithConfigure = &lldpConfigurationResource{}
|
||||
)
|
||||
|
||||
func NewLLDPConfigurationResource() resource.Resource {
|
||||
return &lldpConfigurationResource{}
|
||||
}
|
||||
|
||||
type lldpConfigurationResource struct {
|
||||
client *client.Client
|
||||
}
|
||||
|
||||
type lldpConfigurationResourceModel struct {
|
||||
ID types.String `tfsdk:"id"`
|
||||
TransmitInterval types.Int64 `tfsdk:"transmit_interval"`
|
||||
TransmitHold types.Int64 `tfsdk:"transmit_hold"`
|
||||
ReinitDelay types.Int64 `tfsdk:"reinit_delay"`
|
||||
NotificationInterval types.Int64 `tfsdk:"notification_interval"`
|
||||
}
|
||||
|
||||
func (r *lldpConfigurationResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_lldp_configuration"
|
||||
}
|
||||
|
||||
func (r *lldpConfigurationResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Controls the switch's LLDP Global Mode settings (LLDPConfig.html). Singleton -- there is only ever one of these per switch. Does NOT cover the page's per-port Interface Mode table -- see the package doc comment. Delete resets all four fields to their documented factory defaults.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: "Always \"lldp_configuration\" -- this is a singleton resource.",
|
||||
},
|
||||
"transmit_interval": schema.Int64Attribute{
|
||||
Required: true,
|
||||
Description: "Seconds between LLDP transmissions. Range 5-32768 (switch default: 30).",
|
||||
},
|
||||
"transmit_hold": schema.Int64Attribute{
|
||||
Required: true,
|
||||
Description: "Multiplier for how long a receiver holds LLDP info before aging it out. Range 2-10 (switch default: 4).",
|
||||
},
|
||||
"reinit_delay": schema.Int64Attribute{
|
||||
Required: true,
|
||||
Description: "Seconds to wait before re-initializing LLDP on a port after it's disabled. Range 1-10 (switch default: 2).",
|
||||
},
|
||||
"notification_interval": schema.Int64Attribute{
|
||||
Required: true,
|
||||
Description: "Minimum seconds between LLDP change notifications. Range 5-3600 (switch default: 5).",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *lldpConfigurationResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
c, ok := req.ProviderData.(*client.Client)
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError("Unexpected resource configure type", fmt.Sprintf("expected *client.Client, got %T", req.ProviderData))
|
||||
return
|
||||
}
|
||||
r.client = c
|
||||
}
|
||||
|
||||
type lldpConfigurationState struct {
|
||||
TransmitInterval int64
|
||||
TransmitHold int64
|
||||
ReinitDelay int64
|
||||
NotificationInterval int64
|
||||
}
|
||||
|
||||
func (r *lldpConfigurationResource) readState() (lldpConfigurationState, error) {
|
||||
tables, err := r.client.FetchTables(lldpConfigPath)
|
||||
if err != nil {
|
||||
return lldpConfigurationState{}, err
|
||||
}
|
||||
table, ok := tables[lldpGlobalModeCaption]
|
||||
if !ok {
|
||||
return lldpConfigurationState{}, fmt.Errorf("table captioned %q not found on %s", lldpGlobalModeCaption, lldpConfigPath)
|
||||
}
|
||||
|
||||
parse := func(label string) (int64, error) {
|
||||
v, err := strconv.ParseInt(table.Record[label], 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("parsing %q (%q) as int: %w", label, table.Record[label], err)
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
transmitInterval, err := parse(lldpTransmitIntervalLabel)
|
||||
if err != nil {
|
||||
return lldpConfigurationState{}, err
|
||||
}
|
||||
transmitHold, err := parse(lldpTransmitHoldLabel)
|
||||
if err != nil {
|
||||
return lldpConfigurationState{}, err
|
||||
}
|
||||
reinitDelay, err := parse(lldpReinitDelayLabel)
|
||||
if err != nil {
|
||||
return lldpConfigurationState{}, err
|
||||
}
|
||||
notificationInterval, err := parse(lldpNotificationIntervalLabel)
|
||||
if err != nil {
|
||||
return lldpConfigurationState{}, err
|
||||
}
|
||||
|
||||
return lldpConfigurationState{
|
||||
TransmitInterval: transmitInterval,
|
||||
TransmitHold: transmitHold,
|
||||
ReinitDelay: reinitDelay,
|
||||
NotificationInterval: notificationInterval,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *lldpConfigurationResource) setState(desired lldpConfigurationState) error {
|
||||
tables, err := r.client.FetchTables(lldpConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
table, ok := tables[lldpGlobalModeCaption]
|
||||
if !ok {
|
||||
return fmt.Errorf("table captioned %q not found on %s", lldpGlobalModeCaption, lldpConfigPath)
|
||||
}
|
||||
|
||||
field := func(label string) (string, error) {
|
||||
f, ok := table.FieldNames[label]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("field %q not found in table %q", label, lldpGlobalModeCaption)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
transmitIntervalField, err := field(lldpTransmitIntervalLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
transmitHoldField, err := field(lldpTransmitHoldLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reinitDelayField, err := field(lldpReinitDelayLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
notificationIntervalField, err := field(lldpNotificationIntervalLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.client.SubmitForm(lldpConfigPath, map[string]string{
|
||||
transmitIntervalField: strconv.FormatInt(desired.TransmitInterval, 10),
|
||||
transmitHoldField: strconv.FormatInt(desired.TransmitHold, 10),
|
||||
reinitDelayField: strconv.FormatInt(desired.ReinitDelay, 10),
|
||||
notificationIntervalField: strconv.FormatInt(desired.NotificationInterval, 10),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func lldpConfigStateToModel(s lldpConfigurationState) lldpConfigurationResourceModel {
|
||||
return lldpConfigurationResourceModel{
|
||||
ID: types.StringValue("lldp_configuration"),
|
||||
TransmitInterval: types.Int64Value(s.TransmitInterval),
|
||||
TransmitHold: types.Int64Value(s.TransmitHold),
|
||||
ReinitDelay: types.Int64Value(s.ReinitDelay),
|
||||
NotificationInterval: types.Int64Value(s.NotificationInterval),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *lldpConfigurationResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var plan lldpConfigurationResourceModel
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
desired := lldpConfigurationState{
|
||||
TransmitInterval: plan.TransmitInterval.ValueInt64(),
|
||||
TransmitHold: plan.TransmitHold.ValueInt64(),
|
||||
ReinitDelay: plan.ReinitDelay.ValueInt64(),
|
||||
NotificationInterval: plan.NotificationInterval.ValueInt64(),
|
||||
}
|
||||
if err := r.setState(desired); err != nil {
|
||||
resp.Diagnostics.AddError("Unable to set LLDP Configuration state", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
actual, err := r.readState()
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Unable to read back LLDP Configuration state", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
state := lldpConfigStateToModel(actual)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
|
||||
}
|
||||
|
||||
func (r *lldpConfigurationResource) Read(ctx context.Context, _ resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
actual, err := r.readState()
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Unable to read LLDP Configuration state", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
state := lldpConfigStateToModel(actual)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
|
||||
}
|
||||
|
||||
func (r *lldpConfigurationResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var plan lldpConfigurationResourceModel
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
desired := lldpConfigurationState{
|
||||
TransmitInterval: plan.TransmitInterval.ValueInt64(),
|
||||
TransmitHold: plan.TransmitHold.ValueInt64(),
|
||||
ReinitDelay: plan.ReinitDelay.ValueInt64(),
|
||||
NotificationInterval: plan.NotificationInterval.ValueInt64(),
|
||||
}
|
||||
if err := r.setState(desired); err != nil {
|
||||
resp.Diagnostics.AddError("Unable to set LLDP Configuration state", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
actual, err := r.readState()
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Unable to read back LLDP Configuration state", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
state := lldpConfigStateToModel(actual)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
|
||||
}
|
||||
|
||||
// Delete resets all four fields to their documented factory defaults --
|
||||
// safe, no traffic impact.
|
||||
func (r *lldpConfigurationResource) Delete(_ context.Context, _ resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
defaults := lldpConfigurationState{TransmitInterval: 30, TransmitHold: 4, ReinitDelay: 2, NotificationInterval: 5}
|
||||
if err := r.setState(defaults); err != nil {
|
||||
resp.Diagnostics.AddError("Unable to reset LLDP Configuration state on delete", err.Error())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user