From 65b9717b8afa7d218012f613af88c53fe0a21063 Mon Sep 17 00:00:00 2001 From: Michael Dokolin Date: Thu, 28 Mar 2024 08:16:32 +0100 Subject: [PATCH] feat: Add `routeros_capsman_interface` resource to manage CAPsMAN interfaces --- .../routeros_capsman_interface/import.sh | 3 + .../routeros_capsman_interface/resource.tf | 13 ++ routeros/provider.go | 3 +- routeros/resource_capsman_interface.go | 140 ++++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 examples/resources/routeros_capsman_interface/import.sh create mode 100644 examples/resources/routeros_capsman_interface/resource.tf create mode 100644 routeros/resource_capsman_interface.go diff --git a/examples/resources/routeros_capsman_interface/import.sh b/examples/resources/routeros_capsman_interface/import.sh new file mode 100644 index 00000000..f06884ae --- /dev/null +++ b/examples/resources/routeros_capsman_interface/import.sh @@ -0,0 +1,3 @@ +#The ID can be found via API or the terminal +#The command for the terminal is -> :put [/caps-man/interface get [print show-ids]] +terraform import routeros_capsman_interface.cap1 '*1' diff --git a/examples/resources/routeros_capsman_interface/resource.tf b/examples/resources/routeros_capsman_interface/resource.tf new file mode 100644 index 00000000..654eeefd --- /dev/null +++ b/examples/resources/routeros_capsman_interface/resource.tf @@ -0,0 +1,13 @@ +resource "routeros_capsman_channel" "channel1" { + name = "1" + band = "2ghz-g/n" + frequency = 2412 +} + +resource "routeros_capsman_interface" "cap1" { + name = "cap1" + + channel = { + config = routeros_capsman_channel.channel1.name + } +} diff --git a/routeros/provider.go b/routeros/provider.go index cfd02370..5883659c 100644 --- a/routeros/provider.go +++ b/routeros/provider.go @@ -184,11 +184,12 @@ func Provider() *schema.Provider { "routeros_scheduler": ResourceSystemScheduler(), // CAPsMAN Objects + "routeros_capsman_aaa": ResourceCapsManAaa(), "routeros_capsman_access_list": ResourceCapsManAccessList(), "routeros_capsman_channel": ResourceCapsManChannel(), "routeros_capsman_configuration": ResourceCapsManConfiguration(), "routeros_capsman_datapath": ResourceCapsManDatapath(), - "routeros_capsman_aaa": ResourceCapsManAaa(), + "routeros_capsman_interface": ResourceCapsManInterface(), "routeros_capsman_manager": ResourceCapsManManager(), "routeros_capsman_manager_interface": ResourceCapsManManagerInterface(), "routeros_capsman_provisioning": ResourceCapsManProvisioning(), diff --git a/routeros/resource_capsman_interface.go b/routeros/resource_capsman_interface.go new file mode 100644 index 00000000..dd5a4bd2 --- /dev/null +++ b/routeros/resource_capsman_interface.go @@ -0,0 +1,140 @@ +package routeros + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +/* +{ + ".id": "*1", + "arp-timeout": "auto", + "bound": "true", + "configuration": "test", + "current-authorized-clients": "0", + "current-basic-rate-set": "OFDM:6", + "current-channel": "2462/20/gn(30dBm)", + "current-rate-set": "OFDM:6-54 BW:1x SGI:1x HT:0-15", + "current-registered-clients": "0", + "current-state": "running-ap", + "disabled": "false", + "inactive": "false", + "l2mtu": "1600", + "mac-address": "00:00:00:00:00:00", + "master": "true", + "master-interface": "none", + "name": "cap1", + "radio-mac": "00:00:00:00:00:00", + "radio-name": "000000000000", + "running": "false" +} +*/ + +// https://help.mikrotik.com/docs/display/ROS/CAPsMAN +func ResourceCapsManInterface() *schema.Resource { + resSchema := map[string]*schema.Schema{ + MetaResourcePath: PropResourcePath("/caps-man/interface"), + MetaId: PropId(Id), + MetaSkipFields: PropSkipFields("current_authorized_clients", "current_basic_rate_set", "current_channel", + "current_rate_set", "current_registered_clients", "current_state"), + MetaTransformSet: PropTransformSet("channel: channel.config", "configuration: configuration.config", + "datapath: datapath.config", "rates: rates.config", "security: security.config"), + + KeyArpTimeout: PropArpTimeoutRw, + "bound": { + Type: schema.TypeBool, + Computed: true, + Description: "A flag whether the interface is currently available for the CAPsMAN.", + }, + "channel": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Channel inline settings.", + DiffSuppressFunc: AlwaysPresentNotUserProvided, + }, + "configuration": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Configuration inline settings.", + DiffSuppressFunc: AlwaysPresentNotUserProvided, + }, + KeyComment: PropCommentRw, + "datapath": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Datapath inline settings.", + DiffSuppressFunc: AlwaysPresentNotUserProvided, + }, + KeyDisabled: PropDisabledRw, + "inactive": { + Type: schema.TypeBool, + Computed: true, + Description: "A flag whether the interface is currently inactive.", + }, + KeyL2Mtu: PropL2MtuRo, + "mac_address": { + Type: schema.TypeString, + Description: "MAC address (BSSID) to use for the interface.", + Optional: true, + DiffSuppressFunc: AlwaysPresentNotUserProvided, + }, + "master": { + Type: schema.TypeBool, + Computed: true, + Description: "A flag whether the interface is not a virtual one.", + }, + "master_interface": { + Type: schema.TypeString, + Optional: true, + Default: "none", + Description: "The corresponding master interface of the virtual one.", + }, + KeyName: PropName("Name of the interface."), + "radio_mac": { + Type: schema.TypeString, + Optional: true, + Description: "The MAC address of the associated radio.", + DiffSuppressFunc: AlwaysPresentNotUserProvided, + }, + "radio_name": { + Type: schema.TypeString, + Optional: true, + Description: "Name of the associated radio.", + DiffSuppressFunc: AlwaysPresentNotUserProvided, + }, + "rates": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Rates inline settings.", + DiffSuppressFunc: AlwaysPresentNotUserProvided, + }, + "running": { + Type: schema.TypeBool, + Computed: true, + Description: "A flag whether the interface has established a link to another device.", + }, + "security": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Security inline settings.", + DiffSuppressFunc: AlwaysPresentNotUserProvided, + }, + } + + return &schema.Resource{ + CreateContext: DefaultCreate(resSchema), + ReadContext: DefaultRead(resSchema), + UpdateContext: DefaultUpdate(resSchema), + DeleteContext: DefaultDelete(resSchema), + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: resSchema, + } +}