From 0c29e531be76e8c322062babd4c082d7e685ff7f Mon Sep 17 00:00:00 2001 From: Felix Date: Fri, 12 Jan 2024 23:27:43 +0300 Subject: [PATCH] feat(routing): Manage Route Filters Fixes #330 --- routeros/provider.go | 48 +++++++++++------ routeros/resource_routing_filter_rule.go | 51 +++++++++++++++++++ routeros/resource_routing_filter_rule_test.go | 48 +++++++++++++++++ 3 files changed, 131 insertions(+), 16 deletions(-) create mode 100644 routeros/resource_routing_filter_rule.go create mode 100644 routeros/resource_routing_filter_rule_test.go diff --git a/routeros/provider.go b/routeros/provider.go index 4ed2fb0c..f9434b7c 100644 --- a/routeros/provider.go +++ b/routeros/provider.go @@ -15,9 +15,12 @@ func Provider() *schema.Provider { return &schema.Provider{ Schema: map[string]*schema.Schema{ "hosturl": { - Type: schema.TypeString, - Required: true, - DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ROS_HOSTURL", "MIKROTIK_HOST"}, nil), + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.MultiEnvDefaultFunc( + []string{"ROS_HOSTURL", "MIKROTIK_HOST"}, + nil, + ), Description: `URL of the MikroTik router, default is TLS connection to REST. * API: api[s]://host[:port] * api://router.local @@ -32,9 +35,12 @@ func Provider() *schema.Provider { `, }, "username": { - Type: schema.TypeString, - Required: true, - DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ROS_USERNAME", "MIKROTIK_USER"}, nil), + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.MultiEnvDefaultFunc( + []string{"ROS_USERNAME", "MIKROTIK_USER"}, + nil, + ), Description: `Username for the MikroTik WEB/Winbox. @@ -42,22 +48,31 @@ func Provider() *schema.Provider { `, }, "password": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ROS_PASSWORD", "MIKROTIK_PASSWORD"}, nil), + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.MultiEnvDefaultFunc( + []string{"ROS_PASSWORD", "MIKROTIK_PASSWORD"}, + nil, + ), Description: "Password for the MikroTik user.", Sensitive: true, }, "ca_certificate": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ROS_CA_CERTIFICATE", "MIKROTIK_CA_CERTIFICATE"}, nil), + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.MultiEnvDefaultFunc( + []string{"ROS_CA_CERTIFICATE", "MIKROTIK_CA_CERTIFICATE"}, + nil, + ), Description: "Path to MikroTik's certificate authority file.", }, "insecure": { - Type: schema.TypeBool, - Optional: true, - DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ROS_INSECURE", "MIKROTIK_INSECURE"}, false), + Type: schema.TypeBool, + Optional: true, + DefaultFunc: schema.MultiEnvDefaultFunc( + []string{"ROS_INSECURE", "MIKROTIK_INSECURE"}, + false, + ), Description: "Whether to verify the SSL certificate or not.", }, }, @@ -166,9 +181,10 @@ func Provider() *schema.Provider { "routeros_capsman_security": ResourceCapsManSecurity(), // Routing - "routeros_routing_table": ResourceRoutingTable(), "routeros_routing_bgp_connection": ResourceRoutingBGPConnection(), "routeros_routing_bgp_template": ResourceRoutingBGPTemplate(), + "routeros_routing_filter_rule": ResourceRoutingFilterRule(), + "routeros_routing_table": ResourceRoutingTable(), // OSPF "routeros_routing_ospf_instance": ResourceRoutingOspfInstance(), diff --git a/routeros/resource_routing_filter_rule.go b/routeros/resource_routing_filter_rule.go new file mode 100644 index 00000000..2faf146d --- /dev/null +++ b/routeros/resource_routing_filter_rule.go @@ -0,0 +1,51 @@ +package routeros + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +/* + { + ".id": "*2", + "chain": "123", + "comment": "test", + "disabled": "true", + "inactive": "true", + "rule": "if (active) {accept}" + } +*/ + +// https://help.mikrotik.com/docs/display/ROS/Route+Selection+and+Filters +func ResourceRoutingFilterRule() *schema.Resource { + resSchema := map[string]*schema.Schema{ + MetaResourcePath: PropResourcePath("/routing/filter/rule"), + MetaId: PropId(Id), + + "chain": { + Type: schema.TypeString, + Required: true, + Description: "Chain name.", + }, + KeyComment: PropCommentRw, + KeyDisabled: PropDisabledRw, + KeyInactive: PropInactiveRo, + "rule": { + Type: schema.TypeString, + Required: true, + Description: "Filter rule.", + }, + } + + return &schema.Resource{ + CreateContext: DefaultCreate(resSchema), + ReadContext: DefaultRead(resSchema), + UpdateContext: DefaultUpdate(resSchema), + DeleteContext: DefaultDelete(resSchema), + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: resSchema, + } +} diff --git a/routeros/resource_routing_filter_rule_test.go b/routeros/resource_routing_filter_rule_test.go new file mode 100644 index 00000000..d3c58cbb --- /dev/null +++ b/routeros/resource_routing_filter_rule_test.go @@ -0,0 +1,48 @@ +package routeros + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +const testRoutingFilterRule = "routeros_routing_filter_rule.test" + +func TestAccRoutingFilterRuleTest_basic(t *testing.T) { + for _, name := range testNames { + t.Run(name, func(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testSetTransportEnv(t, name) + }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testCheckResourceDestroy("/routing/filter/rule", "routeros_routing_filter_rule"), + Steps: []resource.TestStep{ + { + Config: testAccRoutingFilterRuleConfig(), + Check: resource.ComposeTestCheckFunc( + testResourcePrimaryInstanceId(testRoutingFilterRule), + resource.TestCheckResourceAttr(testRoutingFilterRule, "chain", "testChain"), + resource.TestCheckResourceAttr(testRoutingFilterRule, "rule", "if (dst in 192.168.1.0/24 && dst-len>24) {set distance +1; accept} else {set distance -1; accept}"), + resource.TestCheckResourceAttr(testRoutingFilterRule, "comment", "comment"), + resource.TestCheckResourceAttr(testRoutingFilterRule, "disabled", "true"), + ), + }, + }, + }) + + }) + } +} + +func testAccRoutingFilterRuleConfig() string { + return providerConfig + ` +resource "routeros_routing_filter_rule" "test" { + chain = "testChain" + rule = "if (dst in 192.168.1.0/24 && dst-len>24) {set distance +1; accept} else {set distance -1; accept}" + comment = "comment" + disabled = true +} +` +}