diff --git a/examples/resources/routeros_routing_rule/import.sh b/examples/resources/routeros_routing_rule/import.sh new file mode 100644 index 00000000..3458ca16 --- /dev/null +++ b/examples/resources/routeros_routing_rule/import.sh @@ -0,0 +1,3 @@ +#The ID can be found via API or the terminal +#The command for the terminal is -> :put [/routing/rule get [print show-ids]] +terraform import routeros_routing_rule.test *3 \ No newline at end of file diff --git a/examples/resources/routeros_routing_rule/resource.tf b/examples/resources/routeros_routing_rule/resource.tf new file mode 100644 index 00000000..fb4da2f0 --- /dev/null +++ b/examples/resources/routeros_routing_rule/resource.tf @@ -0,0 +1,5 @@ +resource "routeros_routing_rule" "test" { + dst_address = "192.168.1.0/24" + action = "lookup-only-in-table" + interface = "ether1" +} \ No newline at end of file diff --git a/routeros/provider.go b/routeros/provider.go index 1f5f9798..ba7a9297 100644 --- a/routeros/provider.go +++ b/routeros/provider.go @@ -222,6 +222,7 @@ func Provider() *schema.Provider { "routeros_routing_bgp_template": ResourceRoutingBGPTemplate(), "routeros_routing_filter_rule": ResourceRoutingFilterRule(), "routeros_routing_table": ResourceRoutingTable(), + "routeros_routing_rule": ResourceRoutingRule(), // OSPF "routeros_routing_ospf_instance": ResourceRoutingOspfInstance(), diff --git a/routeros/resource_routing_rule.go b/routeros/resource_routing_rule.go new file mode 100644 index 00000000..87e2bac2 --- /dev/null +++ b/routeros/resource_routing_rule.go @@ -0,0 +1,87 @@ +package routeros + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +/* + { + ".id": "*1", + ".nextid": "*FFFFFFFF", + "action": "lookup", + "disabled": "false", + "dst-address": "2.2.2.0/24", + "inactive": "false", + "interface": "bridge1", + "routing-mark": "main", + "src-address": "1.1.1.1/32", + "table": "main" + } +*/ + +// https://help.mikrotik.com/docs/display/ROS/Policy+Routing +func ResourceRoutingRule() *schema.Resource { + resSchema := map[string]*schema.Schema{ + MetaResourcePath: PropResourcePath("/routing/rule"), + MetaId: PropId(Id), + + "action": { + Type: schema.TypeString, + Optional: true, + Description: "An action to take on the matching packet:drop - silently drop the packet.lookup - perform a " + + "lookup in routing tables.lookup-only-in-table - perform lookup only in the specified routing table " + + "(see table parameter).unreachable - generate ICMP unreachable message and send it back to the source.", + ValidateFunc: validation.StringInSlice([]string{"drop", "lookup", "lookup-only-in-table", "unreachable"}, false), + DiffSuppressFunc: AlwaysPresentNotUserProvided, + }, + KeyComment: PropCommentRw, + "dst_address": { + Type: schema.TypeString, + Optional: true, + Description: "The destination address of the packet to match.", + }, + KeyDisabled: PropDisabledRw, + KeyInactive: PropInactiveRo, + "interface": { + Type: schema.TypeString, + Optional: true, + Description: "Incoming interface to match.", + }, + "min_prefix": { + Type: schema.TypeInt, + Optional: true, + Description: "Equivalent to Linux IP rule `suppress_prefixlength`. For example to suppress the default route " + + "in the routing decision set the value to 0.", + }, + "routing_mark": { + Type: schema.TypeString, + Optional: true, + Description: "Match specific routing mark.", + }, + "src_address": { + Type: schema.TypeString, + Optional: true, + Description: "The source address of the packet to match.", + }, + "table": { + Type: schema.TypeString, + Optional: true, + Description: "Name of the routing table to use for lookup.", + 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, + } +} diff --git a/routeros/resource_routing_rule_test.go b/routeros/resource_routing_rule_test.go new file mode 100644 index 00000000..78252737 --- /dev/null +++ b/routeros/resource_routing_rule_test.go @@ -0,0 +1,56 @@ +package routeros + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +const testRoutingRule = "routeros_routing_rule.test" + +func TestAccRoutingRuleTest_basic(t *testing.T) { + t.Parallel() + 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, + Steps: []resource.TestStep{ + { + Config: testAccRoutingRuleConfig(), + Check: resource.ComposeTestCheckFunc( + testResourcePrimaryInstanceId(testRoutingRule), + resource.TestCheckResourceAttr(testRoutingRule, "dst_address", "192.168.1.0/24"), + resource.TestCheckResourceAttr(testRoutingRule, "action", "lookup-only-in-table"), + resource.TestCheckResourceAttr(testRoutingRule, "interface", "ether1"), + ), + }, + { + Config: testAccRoutingRuleConfig(), + Check: resource.ComposeTestCheckFunc( + testResourcePrimaryInstanceId(testRoutingRule), + resource.TestCheckResourceAttr(testRoutingRule, "dst_address", "192.168.1.0/24"), + resource.TestCheckResourceAttr(testRoutingRule, "action", "lookup-only-in-table"), + resource.TestCheckResourceAttr(testRoutingRule, "interface", "ether1"), + ), + }, + }, + }) + + }) + } +} + +func testAccRoutingRuleConfig() string { + return fmt.Sprintf(`%v +resource "routeros_routing_rule" "test" { + dst_address = "192.168.1.0/24" + action = "lookup-only-in-table" + interface = "ether1" +} +`, providerConfig) +}