From f27d3bfdcee1b7ba3cd8b5b4f099b9f14c077f5d Mon Sep 17 00:00:00 2001 From: Menno Hamburg Date: Tue, 13 Jun 2023 11:54:26 +0200 Subject: [PATCH 01/10] Initial commit for adding ospf instance resource --- routeros/provider.go | 3 + routeros/resource_routing_ospf_instance.go | 129 ++++++++++++++++++ .../resource_routing_ospf_instance_test.go | 66 +++++++++ 3 files changed, 198 insertions(+) create mode 100644 routeros/resource_routing_ospf_instance.go create mode 100644 routeros/resource_routing_ospf_instance_test.go diff --git a/routeros/provider.go b/routeros/provider.go index 92eb456d..740b3da5 100644 --- a/routeros/provider.go +++ b/routeros/provider.go @@ -146,6 +146,9 @@ func Provider() *schema.Provider { // Routing tables "routeros_routing_table": ResourceRoutingTable(), + // OSPF + "routeros_routing_ospf_instance": ResourceRoutingOspfInstance(), + // VPN "routeros_ovpn_server": ResourceOpenVPNServer(), diff --git a/routeros/resource_routing_ospf_instance.go b/routeros/resource_routing_ospf_instance.go new file mode 100644 index 00000000..2b9ad84c --- /dev/null +++ b/routeros/resource_routing_ospf_instance.go @@ -0,0 +1,129 @@ +package routeros + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +/* + { + ".id": "*54", + "name": "", + "domain-id": "", + "domain-tag": "", + "in-filter": "", + "mpls-te-address": "", + "mpls-te-area": "", + "originate-default": "", + "out-filter-chain": "", + "out-filter-select": "", + "redistribute": "", + "router-id": "", + "version": "", + "vrf": "", + "use-dn": "" + } +*/ + +// ResourceRoutingOspfInstance https://help.mikrotik.com/docs/display/ROS/OSPF +func ResourceRoutingOspfInstance() *schema.Resource { + resSchema := map[string]*schema.Schema{ + MetaResourcePath: PropResourcePath("/routing/ospf/instance"), + MetaId: PropId(Name), + + KeyName: PropNameForceNewRw, + KeyComment: PropCommentRw, + KeyDisabled: PropDisabledRw, + "domain-id": { + Type: schema.TypeString, + Optional: true, + Description: "MPLS-related parameter. Identifies the OSPF domain of the instance. " + + "This value is attached to OSPF routes redistributed in BGP as VPNv4 routes as BGP " + + "extended community attribute and used when BGP VPNv4 routes are " + + "redistributed back to OSPF to determine whether to generate " + + "inter-area or AS-external LSA for that route. " + + "By default Null domain-id is used, as described in RFC 4577.", + }, + "domain-tag": { + Type: schema.TypeInt, + Optional: true, + Description: "if set, then used in route redistribution (as route-tag in all external LSAs " + + "generated by this router), and in route calculation (all external LSAs having this route " + + "tag are ignored). Needed for interoperability with older Cisco systems. By default not set.", + }, + "in-filter": { + Type: schema.TypeString, + Optional: true, + Description: "name of the routing filter chain used for incoming prefixes", + }, + "mpls-te-address": { + Type: schema.TypeString, + Optional: true, + Description: "the area used for MPLS traffic engineering. TE Opaque LSAs are generated in this area. " + + "No more than one OSPF instance can have mpls-te-area configured.", + }, + "mpls-te-area": { + Type: schema.TypeString, + Optional: true, + Description: "the area used for MPLS traffic engineering. TE Opaque LSAs are generated in this area. " + + "No more than one OSPF instance can have mpls-te-area configured.", + }, + "originate-default": { + Type: schema.TypeString, + Default: "never", + Description: "Specifies default route (0.0.0.0/0) distribution method.", + }, + "out-filter-chain": { + Type: schema.TypeString, + Optional: true, + Description: "name of the routing filter chain used for outgoing prefixes filtering. " + + "Output operates only with \"external\" routes.", + }, + "out-filter-select": { + Type: schema.TypeString, + Optional: true, + Description: "name of the routing filter select chain, used for output selection. " + + "Output operates only with \"external\" routes.", + }, + "redistribute": { + Type: schema.TypeString, + Optional: true, + Description: "Enable redistribution of specific route types.", + }, + "router-id": { + Type: schema.TypeString, + Default: "main", + Description: "OSPF Router ID. Can be set explicitly as an IP address, or as the name " + + "of the router-id instance.", + }, + "version": { + Type: schema.TypeInt, + Default: 2, + Description: "OSPF version this instance will be running (v2 for IPv4, v3 for IPv6).", + ValidateFunc: validation.IntBetween(2, 3), + }, + "vrf": { + Type: schema.TypeString, + Default: "main", + Description: "the VRF table this OSPF instance operates on", + }, + "use-dn": { + Type: schema.TypeString, + Optional: true, + Description: "", + ValidateFunc: validation.StringInSlice([]string{"yes", "no"}, true), + }, + } + + 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_ospf_instance_test.go b/routeros/resource_routing_ospf_instance_test.go new file mode 100644 index 00000000..17bcf7ab --- /dev/null +++ b/routeros/resource_routing_ospf_instance_test.go @@ -0,0 +1,66 @@ +package routeros + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" +) + +const testRoutingOspfInstance = "routeros_routing_ospf_instance.test_routing_ospf_instance" + +func TestAccRoutingOspfInstanceTest_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/ospf/instance", "routeros_routing_ospf_instance"), + Steps: []resource.TestStep{ + { + Config: testAccCheckRoutingOspfInstanceConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckRoutingOspfInstanceExists(testRoutingOspfInstance), + resource.TestCheckResourceAttr(testRoutingOspfInstance, "name", "test_routing_ospf_instance"), + ), + }, + }, + }) + + }) + } +} + +func testAccCheckRoutingOspfInstanceExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("not found: %s", name) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("no id is set") + } + + return nil + } +} + +func testAccCheckRoutingOspfInstanceConfig() string { + return ` + +provider "routeros" { + insecure = true +} + +resource "routeros_routing_ospf_instance" "test_routing_ospf_instance" { + name = "test_routing_ospf_instance" + disabled = false + } + +` +} From 188345ab7f09ffdf8262894c852079dd375e24db Mon Sep 17 00:00:00 2001 From: Menno Hamburg Date: Tue, 13 Jun 2023 14:49:41 +0200 Subject: [PATCH 02/10] Added additional ospf resources --- routeros/provider.go | 4 +- routeros/resource_routing_ospf_area.go | 76 +++++++++ routeros/resource_routing_ospf_area_test.go | 66 ++++++++ routeros/resource_routing_ospf_instance.go | 41 ++--- ...esource_routing_ospf_interface_template.go | 146 ++++++++++++++++++ ...ce_routing_ospf_interface_template_test.go | 70 +++++++++ 6 files changed, 377 insertions(+), 26 deletions(-) create mode 100644 routeros/resource_routing_ospf_area.go create mode 100644 routeros/resource_routing_ospf_area_test.go create mode 100644 routeros/resource_routing_ospf_interface_template.go create mode 100644 routeros/resource_routing_ospf_interface_template_test.go diff --git a/routeros/provider.go b/routeros/provider.go index 740b3da5..0433cf1d 100644 --- a/routeros/provider.go +++ b/routeros/provider.go @@ -147,7 +147,9 @@ func Provider() *schema.Provider { "routeros_routing_table": ResourceRoutingTable(), // OSPF - "routeros_routing_ospf_instance": ResourceRoutingOspfInstance(), + "routeros_routing_ospf_instance": ResourceRoutingOspfInstance(), + "routeros_routing_ospf_area": ResourceRoutingOspfArea(), + "routeros_routing_ospf_interface_template": ResourceRoutingOspfInterfaceTemplate(), // VPN "routeros_ovpn_server": ResourceOpenVPNServer(), diff --git a/routeros/resource_routing_ospf_area.go b/routeros/resource_routing_ospf_area.go new file mode 100644 index 00000000..d2dbbadc --- /dev/null +++ b/routeros/resource_routing_ospf_area.go @@ -0,0 +1,76 @@ +package routeros + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +/* + { + ".id": "*54", + "name": "", + "area-id": "", + "default-cost": "", + "instance": "", + "no-summaries": "", + "nssa-translate": "", + "type": "", + } +*/ + +// ResourceRoutingOspfArea https://help.mikrotik.com/docs/display/ROS/OSPF +func ResourceRoutingOspfArea() *schema.Resource { + resSchema := map[string]*schema.Schema{ + MetaResourcePath: PropResourcePath("/routing/ospf/area"), + MetaId: PropId(Name), + + KeyName: PropNameForceNewRw, + KeyComment: PropCommentRw, + KeyDisabled: PropDisabledRw, + "area-id": { + Type: schema.TypeString, + Description: "OSPF area identifier.", + }, + "default-cost": { + Type: schema.TypeInt, + Required: false, + Description: "Default cost of injected LSAs into the area.", + }, + "instance": { + Type: schema.TypeString, + Required: true, + Description: "Name of the OSPF instance this area belongs to.", + }, + "no-summaries": { + Type: schema.TypeBool, + Default: false, + Required: false, + Description: "If set then the area will not flood summary LSAs in the stub area.", + }, + "nssa-translate": { + Type: schema.TypeString, + Required: false, + Description: "The parameter indicates which ABR will be used as a translator from type7 to type5 LSA.", + ValidateFunc: validation.StringInSlice([]string{"no", "yes", "candidate"}, false), + }, + "type": { + Type: schema.TypeString, + Required: true, + Default: "default", + Description: "The area type.", + ValidateFunc: validation.StringInSlice([]string{"default", "nssa", "stub"}, true), + }, + } + + 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_ospf_area_test.go b/routeros/resource_routing_ospf_area_test.go new file mode 100644 index 00000000..1ec6ac5b --- /dev/null +++ b/routeros/resource_routing_ospf_area_test.go @@ -0,0 +1,66 @@ +package routeros + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" +) + +const testRoutingOspfArea = "routeros_routing_ospf_area.test_routing_ospf_area" + +func TestAccRoutingOspfInstanceArea_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/ospf/area", "routeros_routing_ospf_area"), + Steps: []resource.TestStep{ + { + Config: testAccCheckRoutingOspfAreaConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckRoutingOspfAreaExists(testRoutingOspfArea), + resource.TestCheckResourceAttr(testRoutingOspfArea, "name", "test_routing_ospf_area"), + ), + }, + }, + }) + + }) + } +} + +func testAccCheckRoutingOspfAreaExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("not found: %s", name) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("no id is set") + } + + return nil + } +} + +func testAccCheckRoutingOspfAreaConfig() string { + return ` + +provider "routeros" { + insecure = true +} + +resource "routeros_routing_ospf_area" "test_routing_ospf_area" { + name = "test_routing_ospf_area" + disabled = true +} + +` +} diff --git a/routeros/resource_routing_ospf_instance.go b/routeros/resource_routing_ospf_instance.go index 2b9ad84c..63a6b0b6 100644 --- a/routeros/resource_routing_ospf_instance.go +++ b/routeros/resource_routing_ospf_instance.go @@ -8,7 +8,7 @@ import ( /* { ".id": "*54", - "name": "", + "name": "", "domain-id": "", "domain-tag": "", "in-filter": "", @@ -35,14 +35,9 @@ func ResourceRoutingOspfInstance() *schema.Resource { KeyComment: PropCommentRw, KeyDisabled: PropDisabledRw, "domain-id": { - Type: schema.TypeString, - Optional: true, - Description: "MPLS-related parameter. Identifies the OSPF domain of the instance. " + - "This value is attached to OSPF routes redistributed in BGP as VPNv4 routes as BGP " + - "extended community attribute and used when BGP VPNv4 routes are " + - "redistributed back to OSPF to determine whether to generate " + - "inter-area or AS-external LSA for that route. " + - "By default Null domain-id is used, as described in RFC 4577.", + Type: schema.TypeString, + Optional: true, + Description: "MPLS-related parameter.", }, "domain-tag": { Type: schema.TypeInt, @@ -57,16 +52,14 @@ func ResourceRoutingOspfInstance() *schema.Resource { Description: "name of the routing filter chain used for incoming prefixes", }, "mpls-te-address": { - Type: schema.TypeString, - Optional: true, - Description: "the area used for MPLS traffic engineering. TE Opaque LSAs are generated in this area. " + - "No more than one OSPF instance can have mpls-te-area configured.", + Type: schema.TypeString, + Optional: true, + Description: "the area used for MPLS traffic engineering.", }, "mpls-te-area": { - Type: schema.TypeString, - Optional: true, - Description: "the area used for MPLS traffic engineering. TE Opaque LSAs are generated in this area. " + - "No more than one OSPF instance can have mpls-te-area configured.", + Type: schema.TypeString, + Optional: true, + Description: "the area used for MPLS traffic engineering.", }, "originate-default": { Type: schema.TypeString, @@ -74,16 +67,14 @@ func ResourceRoutingOspfInstance() *schema.Resource { Description: "Specifies default route (0.0.0.0/0) distribution method.", }, "out-filter-chain": { - Type: schema.TypeString, - Optional: true, - Description: "name of the routing filter chain used for outgoing prefixes filtering. " + - "Output operates only with \"external\" routes.", + Type: schema.TypeString, + Optional: true, + Description: "name of the routing filter chain used for outgoing prefixes filtering.", }, "out-filter-select": { - Type: schema.TypeString, - Optional: true, - Description: "name of the routing filter select chain, used for output selection. " + - "Output operates only with \"external\" routes.", + Type: schema.TypeString, + Optional: true, + Description: "name of the routing filter select chain, used for output selection.", }, "redistribute": { Type: schema.TypeString, diff --git a/routeros/resource_routing_ospf_interface_template.go b/routeros/resource_routing_ospf_interface_template.go new file mode 100644 index 00000000..5400363c --- /dev/null +++ b/routeros/resource_routing_ospf_interface_template.go @@ -0,0 +1,146 @@ +package routeros + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +/* + { + ".id": "*54", + "interfaces": "", + "network": "", + "area": "", + "auth": "", + "auth-id": "", + "authentication-key": "", + "comment": "", + "cost": "", + "dead-interval": "", + "disabled": "", + "hello-interval": "", + "instance-id": "", + "passive": "", + "prefix-list": "", + "priority": "", + "retransmit-interval": "", + "transmit-delay": "", + "type": "", + "vlink-neighbor-id": "", + "vlink-transit-area": "", + } +*/ + +// ResourceRoutingOspfInterfaceTemplate https://help.mikrotik.com/docs/display/ROS/OSPF +func ResourceRoutingOspfInterfaceTemplate() *schema.Resource { + resSchema := map[string]*schema.Schema{ + MetaResourcePath: PropResourcePath("/routing/ospf/interface-template"), + MetaId: PropId(Name), + + KeyComment: PropCommentRw, + KeyDisabled: PropDisabledRw, + "interfaces": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "Interfaces to match.", + }, + "network": { + Type: schema.TypeString, + Description: "The network prefix associated with the area.", + }, + "area": { + Type: schema.TypeString, + Required: true, + Description: "The OSPF area to which the matching interface will be associated.", + }, + "auth": { + Type: schema.TypeString, + Description: "Specifies authentication method for OSPF protocol messages.", + ValidateFunc: validation.StringInSlice([]string{"simple", "md5", "sha1", "sha256", "sha384", "sha512"}, true), + }, + "auth-id": { + Type: schema.TypeInt, + Description: "The key id is used to calculate message digest (used when MD5 or SHA authentication is enabled).", + }, + "authentication-key": { + Type: schema.TypeString, + Description: "The authentication key to be used, should match on all the neighbors of the network segment.", + }, + "cost": { + Type: schema.TypeInt, + Default: 1, + Description: "Interface cost expressed as link state metric.", + ValidateFunc: validation.IntBetween(0, 65535), + }, + "dead-interval": { + Type: schema.TypeString, + Default: "00:00:40", + Description: "Specifies the interval after which a neighbor is declared dead.", + }, + "hello-interval": { + Type: schema.TypeString, + Default: "00:00:10", + Description: "The interval between HELLO packets that the router sends out this interface.", + }, + "instance-id": { + Type: schema.TypeInt, + Description: "Interface cost expressed as link state metric.", + Default: 0, + ValidateFunc: validation.IntBetween(0, 255), + }, + "passive": { + Type: schema.TypeBool, + Default: false, + Description: "If enabled, then do not send or receive OSPF traffic on the matching interfaces", + }, + "prefix-list": { + Type: schema.TypeString, + Description: "Name of the address list containing networks that should be advertised to the v3 interface.", + }, + "priority": { + Type: schema.TypeInt, + Description: "Router's priority. Used to determine the designated router in a broadcast network.", + Default: 128, + ValidateFunc: validation.IntBetween(0, 255), + }, + "retransmit-interval": { + Type: schema.TypeString, + Default: "00:00:05", + Description: "Time interval the lost link state advertisement will be resent.", + }, + "transmit-delay": { + Type: schema.TypeString, + Default: "00:00:01", + Description: "Link-state transmit delay is the estimated time it takes to transmit a link-state update packet on the interface.", + }, + "type": { + Type: schema.TypeString, + Description: "The OSPF network type on this interface.", + Default: "broadcast", + ValidateFunc: validation.StringInSlice([]string{"broadcast", "nbma", "ptp", "ptmp", "ptp-unnumbered", "virtual-link"}, true), + }, + "vlink-neighbor-id": { + Type: schema.TypeString, + Description: "Specifies the router-id of the neighbor which should be connected over the virtual link.", + }, + "vlink-transit-area": { + Type: schema.TypeString, + Description: "A non-backbone area the two routers have in common over which the virtual link will be established.", + }, + } + + 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_ospf_interface_template_test.go b/routeros/resource_routing_ospf_interface_template_test.go new file mode 100644 index 00000000..c76c38dc --- /dev/null +++ b/routeros/resource_routing_ospf_interface_template_test.go @@ -0,0 +1,70 @@ +package routeros + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" +) + +const testRoutingOspfInterfaceTemplate = "routeros_routing_ospf_interface_template.test_routing_ospf_interface_template" + +func TestAccRoutingOspfInterfaceTemplateTest_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/ospf/interface-template", "routeros_routing_ospf_interface_template"), + Steps: []resource.TestStep{ + { + Config: testAccCheckRoutingOspfInterfaceTemplateConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckRoutingOspfInterfaceTemplateExists(testRoutingOspfInterfaceTemplate), + resource.TestCheckResourceAttr(testRoutingOspfInterfaceTemplate, "name", "test_routing_ospf_interface_template"), + ), + }, + }, + }) + + }) + } +} + +func testAccCheckRoutingOspfInterfaceTemplateExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("not found: %s", name) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("no id is set") + } + + return nil + } +} + +func testAccCheckRoutingOspfInterfaceTemplateConfig() string { + return ` + +provider "routeros" { + insecure = true +} + +resource "routeros_routing_ospf_area" "test_routing_ospf_area" { + name = "test_routing_ospf_area" + disabled = true +} + +resource "routeros_routing_ospf_interface_template" "test_routing_ospf_interface_template" { + area = routeros_routing_ospf_area.test_routing_ospf_area.name +} + +` +} From 817ec14513f533ae2d5776f0647965c0238e4832 Mon Sep 17 00:00:00 2001 From: Menno Hamburg Date: Tue, 13 Jun 2023 15:43:25 +0200 Subject: [PATCH 03/10] Fixed tests --- routeros/resource_routing_ospf_area.go | 18 ++-- routeros/resource_routing_ospf_area_test.go | 6 ++ routeros/resource_routing_ospf_instance.go | 28 ++++--- ...esource_routing_ospf_interface_template.go | 84 ++++++++++++------- ...ce_routing_ospf_interface_template_test.go | 10 ++- 5 files changed, 93 insertions(+), 53 deletions(-) diff --git a/routeros/resource_routing_ospf_area.go b/routeros/resource_routing_ospf_area.go index d2dbbadc..efa7a149 100644 --- a/routeros/resource_routing_ospf_area.go +++ b/routeros/resource_routing_ospf_area.go @@ -27,13 +27,15 @@ func ResourceRoutingOspfArea() *schema.Resource { KeyName: PropNameForceNewRw, KeyComment: PropCommentRw, KeyDisabled: PropDisabledRw, - "area-id": { + "area_id": { Type: schema.TypeString, + Default: "0.0.0.0", + Optional: true, Description: "OSPF area identifier.", }, - "default-cost": { + "default_cost": { Type: schema.TypeInt, - Required: false, + Optional: true, Description: "Default cost of injected LSAs into the area.", }, "instance": { @@ -41,21 +43,21 @@ func ResourceRoutingOspfArea() *schema.Resource { Required: true, Description: "Name of the OSPF instance this area belongs to.", }, - "no-summaries": { + "no_summaries": { Type: schema.TypeBool, Default: false, - Required: false, + Optional: true, Description: "If set then the area will not flood summary LSAs in the stub area.", }, - "nssa-translate": { + "nssa_translate": { Type: schema.TypeString, - Required: false, + Optional: true, Description: "The parameter indicates which ABR will be used as a translator from type7 to type5 LSA.", ValidateFunc: validation.StringInSlice([]string{"no", "yes", "candidate"}, false), }, "type": { Type: schema.TypeString, - Required: true, + Optional: true, Default: "default", Description: "The area type.", ValidateFunc: validation.StringInSlice([]string{"default", "nssa", "stub"}, true), diff --git a/routeros/resource_routing_ospf_area_test.go b/routeros/resource_routing_ospf_area_test.go index 1ec6ac5b..45405709 100644 --- a/routeros/resource_routing_ospf_area_test.go +++ b/routeros/resource_routing_ospf_area_test.go @@ -57,9 +57,15 @@ provider "routeros" { insecure = true } +resource "routeros_routing_ospf_instance" "test_routing_ospf_instance" { + name = "test_routing_ospf_instance" + disabled = false + } + resource "routeros_routing_ospf_area" "test_routing_ospf_area" { name = "test_routing_ospf_area" disabled = true + instance = routeros_routing_ospf_instance.test_routing_ospf_instance.name } ` diff --git a/routeros/resource_routing_ospf_instance.go b/routeros/resource_routing_ospf_instance.go index 63a6b0b6..ef170723 100644 --- a/routeros/resource_routing_ospf_instance.go +++ b/routeros/resource_routing_ospf_instance.go @@ -34,44 +34,45 @@ func ResourceRoutingOspfInstance() *schema.Resource { KeyName: PropNameForceNewRw, KeyComment: PropCommentRw, KeyDisabled: PropDisabledRw, - "domain-id": { + "domain_id": { Type: schema.TypeString, Optional: true, Description: "MPLS-related parameter.", }, - "domain-tag": { + "domain_tag": { Type: schema.TypeInt, Optional: true, Description: "if set, then used in route redistribution (as route-tag in all external LSAs " + "generated by this router), and in route calculation (all external LSAs having this route " + "tag are ignored). Needed for interoperability with older Cisco systems. By default not set.", }, - "in-filter": { + "in_filter": { Type: schema.TypeString, Optional: true, Description: "name of the routing filter chain used for incoming prefixes", }, - "mpls-te-address": { + "mpls_te_address": { Type: schema.TypeString, Optional: true, Description: "the area used for MPLS traffic engineering.", }, - "mpls-te-area": { + "mpls_te_area": { Type: schema.TypeString, Optional: true, Description: "the area used for MPLS traffic engineering.", }, - "originate-default": { + "originate_default": { Type: schema.TypeString, Default: "never", + Optional: true, Description: "Specifies default route (0.0.0.0/0) distribution method.", }, - "out-filter-chain": { + "out_filter_chain": { Type: schema.TypeString, Optional: true, Description: "name of the routing filter chain used for outgoing prefixes filtering.", }, - "out-filter-select": { + "out_filter_select": { Type: schema.TypeString, Optional: true, Description: "name of the routing filter select chain, used for output selection.", @@ -81,24 +82,27 @@ func ResourceRoutingOspfInstance() *schema.Resource { Optional: true, Description: "Enable redistribution of specific route types.", }, - "router-id": { - Type: schema.TypeString, - Default: "main", + "router_id": { + Type: schema.TypeString, + Default: "main", + Optional: true, Description: "OSPF Router ID. Can be set explicitly as an IP address, or as the name " + "of the router-id instance.", }, "version": { Type: schema.TypeInt, Default: 2, + Optional: true, Description: "OSPF version this instance will be running (v2 for IPv4, v3 for IPv6).", ValidateFunc: validation.IntBetween(2, 3), }, "vrf": { Type: schema.TypeString, Default: "main", + Optional: true, Description: "the VRF table this OSPF instance operates on", }, - "use-dn": { + "use_dn": { Type: schema.TypeString, Optional: true, Description: "", diff --git a/routeros/resource_routing_ospf_interface_template.go b/routeros/resource_routing_ospf_interface_template.go index 5400363c..4eb97922 100644 --- a/routeros/resource_routing_ospf_interface_template.go +++ b/routeros/resource_routing_ospf_interface_template.go @@ -35,20 +35,19 @@ import ( func ResourceRoutingOspfInterfaceTemplate() *schema.Resource { resSchema := map[string]*schema.Schema{ MetaResourcePath: PropResourcePath("/routing/ospf/interface-template"), - MetaId: PropId(Name), + MetaId: PropId(Id), KeyComment: PropCommentRw, KeyDisabled: PropDisabledRw, "interfaces": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, + Type: schema.TypeString, + Optional: true, + Default: "none", Description: "Interfaces to match.", }, "network": { Type: schema.TypeString, + Optional: true, Description: "The network prefix associated with the area.", }, "area": { @@ -58,76 +57,99 @@ func ResourceRoutingOspfInterfaceTemplate() *schema.Resource { }, "auth": { Type: schema.TypeString, + Optional: true, Description: "Specifies authentication method for OSPF protocol messages.", ValidateFunc: validation.StringInSlice([]string{"simple", "md5", "sha1", "sha256", "sha384", "sha512"}, true), }, - "auth-id": { + "auth_id": { Type: schema.TypeInt, + Optional: true, Description: "The key id is used to calculate message digest (used when MD5 or SHA authentication is enabled).", }, - "authentication-key": { + "authentication_key": { Type: schema.TypeString, + Optional: true, Description: "The authentication key to be used, should match on all the neighbors of the network segment.", }, "cost": { Type: schema.TypeInt, + Optional: true, Default: 1, Description: "Interface cost expressed as link state metric.", ValidateFunc: validation.IntBetween(0, 65535), }, - "dead-interval": { - Type: schema.TypeString, - Default: "00:00:40", - Description: "Specifies the interval after which a neighbor is declared dead.", - }, - "hello-interval": { - Type: schema.TypeString, - Default: "00:00:10", - Description: "The interval between HELLO packets that the router sends out this interface.", - }, - "instance-id": { + "dead_interval": { + Type: schema.TypeString, + Optional: true, + Default: "40s", + ValidateFunc: ValidationTime, + DiffSuppressFunc: TimeEquall, + Description: "Specifies the interval after which a neighbor is declared dead.", + }, + "hello_interval": { + Type: schema.TypeString, + Optional: true, + Default: "10s", + ValidateFunc: ValidationTime, + DiffSuppressFunc: TimeEquall, + Description: "The interval between HELLO packets that the router sends out this interface.", + }, + "instance_id": { Type: schema.TypeInt, + Optional: true, Description: "Interface cost expressed as link state metric.", Default: 0, ValidateFunc: validation.IntBetween(0, 255), }, "passive": { Type: schema.TypeBool, + Optional: true, Default: false, Description: "If enabled, then do not send or receive OSPF traffic on the matching interfaces", }, - "prefix-list": { + "prefix_list": { Type: schema.TypeString, + Optional: true, Description: "Name of the address list containing networks that should be advertised to the v3 interface.", }, "priority": { Type: schema.TypeInt, + Optional: true, Description: "Router's priority. Used to determine the designated router in a broadcast network.", Default: 128, ValidateFunc: validation.IntBetween(0, 255), }, - "retransmit-interval": { - Type: schema.TypeString, - Default: "00:00:05", - Description: "Time interval the lost link state advertisement will be resent.", - }, - "transmit-delay": { - Type: schema.TypeString, - Default: "00:00:01", - Description: "Link-state transmit delay is the estimated time it takes to transmit a link-state update packet on the interface.", + "retransmit_interval": { + Type: schema.TypeString, + Optional: true, + Default: "5s", + ValidateFunc: ValidationTime, + DiffSuppressFunc: TimeEquall, + Description: "Time interval the lost link state advertisement will be resent.", + }, + "transmit_delay": { + Type: schema.TypeString, + Optional: true, + Default: "1s", + ValidateFunc: ValidationTime, + DiffSuppressFunc: TimeEquall, + Description: "Link-state transmit delay is the estimated time it takes to transmit a link-state update packet on the interface.", }, "type": { Type: schema.TypeString, Description: "The OSPF network type on this interface.", + Optional: true, Default: "broadcast", ValidateFunc: validation.StringInSlice([]string{"broadcast", "nbma", "ptp", "ptmp", "ptp-unnumbered", "virtual-link"}, true), }, - "vlink-neighbor-id": { + "vlink_neighbor_id": { Type: schema.TypeString, + Optional: true, Description: "Specifies the router-id of the neighbor which should be connected over the virtual link.", }, - "vlink-transit-area": { + "vlink_transit_area": { Type: schema.TypeString, + Optional: true, Description: "A non-backbone area the two routers have in common over which the virtual link will be established.", }, } diff --git a/routeros/resource_routing_ospf_interface_template_test.go b/routeros/resource_routing_ospf_interface_template_test.go index c76c38dc..a39af541 100644 --- a/routeros/resource_routing_ospf_interface_template_test.go +++ b/routeros/resource_routing_ospf_interface_template_test.go @@ -25,7 +25,7 @@ func TestAccRoutingOspfInterfaceTemplateTest_basic(t *testing.T) { Config: testAccCheckRoutingOspfInterfaceTemplateConfig(), Check: resource.ComposeTestCheckFunc( testAccCheckRoutingOspfInterfaceTemplateExists(testRoutingOspfInterfaceTemplate), - resource.TestCheckResourceAttr(testRoutingOspfInterfaceTemplate, "name", "test_routing_ospf_interface_template"), + resource.TestCheckResourceAttr(testRoutingOspfInterfaceTemplate, "area", "test_routing_ospf_area"), ), }, }, @@ -57,9 +57,15 @@ provider "routeros" { insecure = true } +resource "routeros_routing_ospf_instance" "test_routing_ospf_instance" { + name = "test_routing_ospf_instance" + disabled = false + } + resource "routeros_routing_ospf_area" "test_routing_ospf_area" { name = "test_routing_ospf_area" - disabled = true + disabled = false + instance = routeros_routing_ospf_instance.test_routing_ospf_instance.name } resource "routeros_routing_ospf_interface_template" "test_routing_ospf_interface_template" { From 7a6024b054151d3bb3a7bfb2e21e53fcc1e9c47d Mon Sep 17 00:00:00 2001 From: Menno Hamburg Date: Tue, 13 Jun 2023 23:04:32 +0200 Subject: [PATCH 04/10] Small improvements, where needed --- routeros/resource_routing_ospf_instance.go | 24 ++++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/routeros/resource_routing_ospf_instance.go b/routeros/resource_routing_ospf_instance.go index ef170723..bbbb03f6 100644 --- a/routeros/resource_routing_ospf_instance.go +++ b/routeros/resource_routing_ospf_instance.go @@ -62,10 +62,11 @@ func ResourceRoutingOspfInstance() *schema.Resource { Description: "the area used for MPLS traffic engineering.", }, "originate_default": { - Type: schema.TypeString, - Default: "never", - Optional: true, - Description: "Specifies default route (0.0.0.0/0) distribution method.", + Type: schema.TypeString, + Default: "never", + Optional: true, + Description: "Specifies default route (0.0.0.0/0) distribution method.", + ValidateFunc: validation.StringInSlice([]string{"always", "if-installed", "never"}, true), }, "out_filter_chain": { Type: schema.TypeString, @@ -78,9 +79,13 @@ func ResourceRoutingOspfInstance() *schema.Resource { Description: "name of the routing filter select chain, used for output selection.", }, "redistribute": { - Type: schema.TypeString, + Type: schema.TypeList, Optional: true, Description: "Enable redistribution of specific route types.", + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"bgp", "connected", "copy", "dhcp", "fantasy", "modem", "ospf", "rip", "static", "vpn"}, true), + }, }, "router_id": { Type: schema.TypeString, @@ -100,12 +105,13 @@ func ResourceRoutingOspfInstance() *schema.Resource { Type: schema.TypeString, Default: "main", Optional: true, - Description: "the VRF table this OSPF instance operates on", + Description: "The VRF table this OSPF instance operates on", }, "use_dn": { - Type: schema.TypeString, - Optional: true, - Description: "", + Type: schema.TypeString, + Optional: true, + Description: "Forces to use or ignore DN bit. Useful in some CE PE scenarios to inject intra-area routes into VRF. " + + "If a parameter is unset then the DN bit is used according to RFC. Available since v6rc12.", ValidateFunc: validation.StringInSlice([]string{"yes", "no"}, true), }, } From f0db91e1719b4b6edf8ebf56cbbbd8457a627add Mon Sep 17 00:00:00 2001 From: Vaerh Date: Mon, 19 Jun 2023 10:13:45 +0300 Subject: [PATCH 05/10] docs(ospf): Return the OSPF examples from the 78b05a2 commit --- .../resources/routeros_routing_ospf_area/resource.tf | 8 ++++++++ .../routeros_routing_ospf_instance/resource.tf | 3 +++ .../resource.tf | 12 ++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 examples/resources/routeros_routing_ospf_area/resource.tf create mode 100644 examples/resources/routeros_routing_ospf_instance/resource.tf create mode 100644 examples/resources/routeros_routing_ospf_interface_template/resource.tf diff --git a/examples/resources/routeros_routing_ospf_area/resource.tf b/examples/resources/routeros_routing_ospf_area/resource.tf new file mode 100644 index 00000000..09dff98b --- /dev/null +++ b/examples/resources/routeros_routing_ospf_area/resource.tf @@ -0,0 +1,8 @@ +resource "routeros_routing_ospf_instance" "test_routing_ospf_instance" { + name = "test_routing_ospf_instance" +} + +resource "routeros_routing_ospf_area" "test_routing_ospf_area" { + name = "test_routing_ospf_area" + instance = routeros_routing_ospf_instance.test_routing_ospf_instance.name +} \ No newline at end of file diff --git a/examples/resources/routeros_routing_ospf_instance/resource.tf b/examples/resources/routeros_routing_ospf_instance/resource.tf new file mode 100644 index 00000000..b0fee806 --- /dev/null +++ b/examples/resources/routeros_routing_ospf_instance/resource.tf @@ -0,0 +1,3 @@ +resource "routeros_routing_ospf_instance" "test_routing_ospf_instance" { + name = "test_routing_ospf_instance" +} \ No newline at end of file diff --git a/examples/resources/routeros_routing_ospf_interface_template/resource.tf b/examples/resources/routeros_routing_ospf_interface_template/resource.tf new file mode 100644 index 00000000..b3687fe4 --- /dev/null +++ b/examples/resources/routeros_routing_ospf_interface_template/resource.tf @@ -0,0 +1,12 @@ +resource "routeros_routing_ospf_instance" "test_routing_ospf_instance" { + name = "test_routing_ospf_instance" +} + +resource "routeros_routing_ospf_area" "test_routing_ospf_area" { + name = "test_routing_ospf_area" + instance = routeros_routing_ospf_instance.test_routing_ospf_instance.name +} + +resource "routeros_routing_ospf_interface_template" "test_routing_ospf_interface_template" { + area = routeros_routing_ospf_area.test_routing_ospf_area.name +} \ No newline at end of file From adca988ca08d36d6cab9a839fbad891827e72a81 Mon Sep 17 00:00:00 2001 From: Vaerh Date: Mon, 19 Jun 2023 10:15:37 +0300 Subject: [PATCH 06/10] fix: Add a helper for the attribute 'inactive' --- routeros/provider_schema_helpers.go | 5 +++++ routeros/resource_interface_bridge_port.go | 5 +---- routeros/resource_ip_route.go | 5 +---- routeros/resource_ipv6_route.go | 5 +---- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/routeros/provider_schema_helpers.go b/routeros/provider_schema_helpers.go index 1e22b817..1ae8adf8 100644 --- a/routeros/provider_schema_helpers.go +++ b/routeros/provider_schema_helpers.go @@ -28,6 +28,7 @@ const ( KeyDynamic = "dynamic" KeyDisabled = "disabled" KeyFilter = "filter" + KeyInactive = "inactive" KeyInterface = "interface" KeyInvalid = "invalid" KeyL2Mtu = "l2mtu" @@ -142,6 +143,10 @@ var ( Elem: schema.TypeString, Description: "Additional request filtering options.", } + PropInactiveRo = &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + } PropInterfaceRw = &schema.Schema{ Type: schema.TypeString, Required: true, diff --git a/routeros/resource_interface_bridge_port.go b/routeros/resource_interface_bridge_port.go index f7337c65..03ee8bb9 100644 --- a/routeros/resource_interface_bridge_port.go +++ b/routeros/resource_interface_bridge_port.go @@ -193,10 +193,7 @@ func ResourceInterfaceBridgePort() *schema.Resource { Computed: true, Description: "Switch chip used by the port.", }, - "inactive": { - Type: schema.TypeBool, - Computed: true, - }, + KeyInactive: PropInactiveRo, "ingress_filtering": { Type: schema.TypeBool, Optional: true, diff --git a/routeros/resource_ip_route.go b/routeros/resource_ip_route.go index 84566c58..6fd81e83 100644 --- a/routeros/resource_ip_route.go +++ b/routeros/resource_ip_route.go @@ -71,10 +71,7 @@ func ResourceIPRoute() *schema.Resource { Computed: true, Description: "Shows actual (resolved) gateway and interface that will be used for packet forwarding.", }, - "inactive": { - Type: schema.TypeBool, - Computed: true, - }, + KeyInactive: PropInactiveRo, "pref_src": { Type: schema.TypeString, Optional: true, diff --git a/routeros/resource_ipv6_route.go b/routeros/resource_ipv6_route.go index 07a6a9e8..af256223 100644 --- a/routeros/resource_ipv6_route.go +++ b/routeros/resource_ipv6_route.go @@ -59,10 +59,7 @@ func ResourceIPv6Route() *schema.Resource { Computed: true, Description: "Shows actual (resolved) gateway and interface that will be used for packet forwarding.", }, - "inactive": { - Type: schema.TypeBool, - Computed: true, - }, + KeyInactive: PropInactiveRo, "pref_src": { Type: schema.TypeString, Optional: true, From 4d473ea2e958a52f6544742cf47f0a1190e36508 Mon Sep 17 00:00:00 2001 From: Vaerh Date: Mon, 19 Jun 2023 10:48:15 +0300 Subject: [PATCH 07/10] feat: New OSPF resource Fixed small implementation flaws --- routeros/resource_routing_ospf_area.go | 11 +-- routeros/resource_routing_ospf_instance.go | 37 +++++----- ...esource_routing_ospf_interface_template.go | 70 +++++++++++-------- 3 files changed, 63 insertions(+), 55 deletions(-) diff --git a/routeros/resource_routing_ospf_area.go b/routeros/resource_routing_ospf_area.go index efa7a149..f107bb59 100644 --- a/routeros/resource_routing_ospf_area.go +++ b/routeros/resource_routing_ospf_area.go @@ -22,27 +22,28 @@ import ( func ResourceRoutingOspfArea() *schema.Resource { resSchema := map[string]*schema.Schema{ MetaResourcePath: PropResourcePath("/routing/ospf/area"), - MetaId: PropId(Name), + MetaId: PropId(Id), - KeyName: PropNameForceNewRw, - KeyComment: PropCommentRw, - KeyDisabled: PropDisabledRw, "area_id": { Type: schema.TypeString, Default: "0.0.0.0", Optional: true, Description: "OSPF area identifier.", }, + KeyComment: PropCommentRw, "default_cost": { Type: schema.TypeInt, Optional: true, Description: "Default cost of injected LSAs into the area.", }, + KeyDisabled: PropDisabledRw, + KeyInactive: PropInactiveRo, "instance": { Type: schema.TypeString, Required: true, Description: "Name of the OSPF instance this area belongs to.", }, + KeyName: PropNameForceNewRw, "no_summaries": { Type: schema.TypeBool, Default: false, @@ -60,7 +61,7 @@ func ResourceRoutingOspfArea() *schema.Resource { Optional: true, Default: "default", Description: "The area type.", - ValidateFunc: validation.StringInSlice([]string{"default", "nssa", "stub"}, true), + ValidateFunc: validation.StringInSlice([]string{"default", "nssa", "stub"}, false), }, } diff --git a/routeros/resource_routing_ospf_instance.go b/routeros/resource_routing_ospf_instance.go index bbbb03f6..ae691fb5 100644 --- a/routeros/resource_routing_ospf_instance.go +++ b/routeros/resource_routing_ospf_instance.go @@ -21,7 +21,7 @@ import ( "router-id": "", "version": "", "vrf": "", - "use-dn": "" + "use-dn": "" // is not present in version 7.9 } */ @@ -29,9 +29,8 @@ import ( func ResourceRoutingOspfInstance() *schema.Resource { resSchema := map[string]*schema.Schema{ MetaResourcePath: PropResourcePath("/routing/ospf/instance"), - MetaId: PropId(Name), + MetaId: PropId(Id), - KeyName: PropNameForceNewRw, KeyComment: PropCommentRw, KeyDisabled: PropDisabledRw, "domain_id": { @@ -46,7 +45,8 @@ func ResourceRoutingOspfInstance() *schema.Resource { "generated by this router), and in route calculation (all external LSAs having this route " + "tag are ignored). Needed for interoperability with older Cisco systems. By default not set.", }, - "in_filter": { + KeyInactive: PropInactiveRo, + "in_filter_chain": { Type: schema.TypeString, Optional: true, Description: "name of the routing filter chain used for incoming prefixes", @@ -61,12 +61,12 @@ func ResourceRoutingOspfInstance() *schema.Resource { Optional: true, Description: "the area used for MPLS traffic engineering.", }, + KeyName: PropNameForceNewRw, "originate_default": { Type: schema.TypeString, - Default: "never", Optional: true, Description: "Specifies default route (0.0.0.0/0) distribution method.", - ValidateFunc: validation.StringInSlice([]string{"always", "if-installed", "never"}, true), + ValidateFunc: validation.StringInSlice([]string{"always", "if-installed", "never"}, false), }, "out_filter_chain": { Type: schema.TypeString, @@ -79,41 +79,40 @@ func ResourceRoutingOspfInstance() *schema.Resource { Description: "name of the routing filter select chain, used for output selection.", }, "redistribute": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Description: "Enable redistribution of specific route types.", Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringInSlice([]string{"bgp", "connected", "copy", "dhcp", "fantasy", "modem", "ospf", "rip", "static", "vpn"}, true), + Type: schema.TypeString, + ValidateDiagFunc: ValidationMultiValInSlice([]string{"bgp", "connected", "copy", "dhcp", "fantasy", "modem", + "ospf", "rip", "static", "vpn"}, false, false), }, }, "router_id": { Type: schema.TypeString, - Default: "main", Optional: true, + Default: "main", Description: "OSPF Router ID. Can be set explicitly as an IP address, or as the name " + "of the router-id instance.", }, + "routing_table": { + Type: schema.TypeString, + Optional: true, + Description: "Name of the routing table in use.", + }, "version": { Type: schema.TypeInt, - Default: 2, Optional: true, + Default: 2, Description: "OSPF version this instance will be running (v2 for IPv4, v3 for IPv6).", ValidateFunc: validation.IntBetween(2, 3), }, "vrf": { Type: schema.TypeString, - Default: "main", Optional: true, + Default: "main", Description: "The VRF table this OSPF instance operates on", }, - "use_dn": { - Type: schema.TypeString, - Optional: true, - Description: "Forces to use or ignore DN bit. Useful in some CE PE scenarios to inject intra-area routes into VRF. " + - "If a parameter is unset then the DN bit is used according to RFC. Available since v6rc12.", - ValidateFunc: validation.StringInSlice([]string{"yes", "no"}, true), - }, } return &schema.Resource{ diff --git a/routeros/resource_routing_ospf_interface_template.go b/routeros/resource_routing_ospf_interface_template.go index 4eb97922..2894f701 100644 --- a/routeros/resource_routing_ospf_interface_template.go +++ b/routeros/resource_routing_ospf_interface_template.go @@ -37,19 +37,6 @@ func ResourceRoutingOspfInterfaceTemplate() *schema.Resource { MetaResourcePath: PropResourcePath("/routing/ospf/interface-template"), MetaId: PropId(Id), - KeyComment: PropCommentRw, - KeyDisabled: PropDisabledRw, - "interfaces": { - Type: schema.TypeString, - Optional: true, - Default: "none", - Description: "Interfaces to match.", - }, - "network": { - Type: schema.TypeString, - Optional: true, - Description: "The network prefix associated with the area.", - }, "area": { Type: schema.TypeString, Required: true, @@ -62,15 +49,18 @@ func ResourceRoutingOspfInterfaceTemplate() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{"simple", "md5", "sha1", "sha256", "sha384", "sha512"}, true), }, "auth_id": { - Type: schema.TypeInt, - Optional: true, - Description: "The key id is used to calculate message digest (used when MD5 or SHA authentication is enabled).", + Type: schema.TypeInt, + Optional: true, + Description: "The key id is used to calculate message digest (used when MD5 or SHA authentication is enabled).", + ValidateFunc: validation.IntBetween(0, 255), }, "authentication_key": { Type: schema.TypeString, Optional: true, + Sensitive: true, Description: "The authentication key to be used, should match on all the neighbors of the network segment.", }, + KeyComment: PropCommentRw, "cost": { Type: schema.TypeInt, Optional: true, @@ -82,17 +72,27 @@ func ResourceRoutingOspfInterfaceTemplate() *schema.Resource { Type: schema.TypeString, Optional: true, Default: "40s", + Description: "Specifies the interval after which a neighbor is declared dead.", ValidateFunc: ValidationTime, DiffSuppressFunc: TimeEquall, - Description: "Specifies the interval after which a neighbor is declared dead.", }, + KeyDisabled: PropDisabledRw, "hello_interval": { Type: schema.TypeString, Optional: true, Default: "10s", + Description: "The interval between HELLO packets that the router sends out this interface.", ValidateFunc: ValidationTime, DiffSuppressFunc: TimeEquall, - Description: "The interval between HELLO packets that the router sends out this interface.", + }, + KeyInactive: PropInactiveRo, + "interfaces": { + Type: schema.TypeSet, + Optional: true, + Description: "Interfaces to match.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, "instance_id": { Type: schema.TypeInt, @@ -101,6 +101,11 @@ func ResourceRoutingOspfInterfaceTemplate() *schema.Resource { Default: 0, ValidateFunc: validation.IntBetween(0, 255), }, + "network": { + Type: schema.TypeString, + Optional: true, + Description: "The network prefix associated with the area.", + }, "passive": { Type: schema.TypeBool, Optional: true, @@ -123,24 +128,26 @@ func ResourceRoutingOspfInterfaceTemplate() *schema.Resource { Type: schema.TypeString, Optional: true, Default: "5s", + Description: "Time interval the lost link state advertisement will be resent.", ValidateFunc: ValidationTime, DiffSuppressFunc: TimeEquall, - Description: "Time interval the lost link state advertisement will be resent.", }, "transmit_delay": { - Type: schema.TypeString, - Optional: true, - Default: "1s", + Type: schema.TypeString, + Optional: true, + Default: "1s", + Description: "Link-state transmit delay is the estimated time it takes to transmit a link-state " + + "update packet on the interface.", ValidateFunc: ValidationTime, DiffSuppressFunc: TimeEquall, - Description: "Link-state transmit delay is the estimated time it takes to transmit a link-state update packet on the interface.", }, "type": { - Type: schema.TypeString, - Description: "The OSPF network type on this interface.", - Optional: true, - Default: "broadcast", - ValidateFunc: validation.StringInSlice([]string{"broadcast", "nbma", "ptp", "ptmp", "ptp-unnumbered", "virtual-link"}, true), + Type: schema.TypeString, + Description: "The OSPF network type on this interface.", + Optional: true, + Default: "broadcast", + ValidateFunc: validation.StringInSlice( + []string{"broadcast", "nbma", "ptp", "ptmp", "ptp-unnumbered", "virtual-link"}, true), }, "vlink_neighbor_id": { Type: schema.TypeString, @@ -148,9 +155,10 @@ func ResourceRoutingOspfInterfaceTemplate() *schema.Resource { Description: "Specifies the router-id of the neighbor which should be connected over the virtual link.", }, "vlink_transit_area": { - Type: schema.TypeString, - Optional: true, - Description: "A non-backbone area the two routers have in common over which the virtual link will be established.", + Type: schema.TypeString, + Optional: true, + Description: "A non-backbone area the two routers have in common over which the virtual link will " + + "be established.", }, } From d9a2bd030f7dc9c593bfa74b94bfaeb15b71fc00 Mon Sep 17 00:00:00 2001 From: Vaerh Date: Mon, 19 Jun 2023 10:49:56 +0300 Subject: [PATCH 08/10] test: Small improvements --- routeros/resource_routing_ospf_area_test.go | 7 +------ routeros/resource_routing_ospf_instance_test.go | 8 +------- routeros/resource_routing_ospf_interface_template_test.go | 3 ++- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/routeros/resource_routing_ospf_area_test.go b/routeros/resource_routing_ospf_area_test.go index 45405709..0edb12e0 100644 --- a/routeros/resource_routing_ospf_area_test.go +++ b/routeros/resource_routing_ospf_area_test.go @@ -51,12 +51,7 @@ func testAccCheckRoutingOspfAreaExists(name string) resource.TestCheckFunc { } func testAccCheckRoutingOspfAreaConfig() string { - return ` - -provider "routeros" { - insecure = true -} - + return providerConfig + ` resource "routeros_routing_ospf_instance" "test_routing_ospf_instance" { name = "test_routing_ospf_instance" disabled = false diff --git a/routeros/resource_routing_ospf_instance_test.go b/routeros/resource_routing_ospf_instance_test.go index 17bcf7ab..4746b8fd 100644 --- a/routeros/resource_routing_ospf_instance_test.go +++ b/routeros/resource_routing_ospf_instance_test.go @@ -51,16 +51,10 @@ func testAccCheckRoutingOspfInstanceExists(name string) resource.TestCheckFunc { } func testAccCheckRoutingOspfInstanceConfig() string { - return ` - -provider "routeros" { - insecure = true -} - + return providerConfig + ` resource "routeros_routing_ospf_instance" "test_routing_ospf_instance" { name = "test_routing_ospf_instance" disabled = false } - ` } diff --git a/routeros/resource_routing_ospf_interface_template_test.go b/routeros/resource_routing_ospf_interface_template_test.go index a39af541..04034cad 100644 --- a/routeros/resource_routing_ospf_interface_template_test.go +++ b/routeros/resource_routing_ospf_interface_template_test.go @@ -69,7 +69,8 @@ resource "routeros_routing_ospf_area" "test_routing_ospf_area" { } resource "routeros_routing_ospf_interface_template" "test_routing_ospf_interface_template" { - area = routeros_routing_ospf_area.test_routing_ospf_area.name + area = routeros_routing_ospf_area.test_routing_ospf_area.name + interfaces = ["ether3"] } ` From fb76fc8ba7d58fccafce80de693ba59d59c51463 Mon Sep 17 00:00:00 2001 From: Vaerh Date: Mon, 19 Jun 2023 10:50:28 +0300 Subject: [PATCH 09/10] docs: Add import examples --- examples/resources/routeros_routing_ospf_area/import.sh | 3 +++ examples/resources/routeros_routing_ospf_instance/import.sh | 3 +++ .../routeros_routing_ospf_interface_template/import.sh | 3 +++ 3 files changed, 9 insertions(+) create mode 100644 examples/resources/routeros_routing_ospf_area/import.sh create mode 100644 examples/resources/routeros_routing_ospf_instance/import.sh create mode 100644 examples/resources/routeros_routing_ospf_interface_template/import.sh diff --git a/examples/resources/routeros_routing_ospf_area/import.sh b/examples/resources/routeros_routing_ospf_area/import.sh new file mode 100644 index 00000000..2fa79683 --- /dev/null +++ b/examples/resources/routeros_routing_ospf_area/import.sh @@ -0,0 +1,3 @@ +#The ID can be found via API or the terminal +#The command for the terminal is -> /routing/ospf/area/print show-ids +terraform import routeros_routing_ospf_area.test_routing_ospf_area "*0" \ No newline at end of file diff --git a/examples/resources/routeros_routing_ospf_instance/import.sh b/examples/resources/routeros_routing_ospf_instance/import.sh new file mode 100644 index 00000000..479733ea --- /dev/null +++ b/examples/resources/routeros_routing_ospf_instance/import.sh @@ -0,0 +1,3 @@ +#The ID can be found via API or the terminal +#The command for the terminal is -> /routing/ospf/instance/print show-ids +terraform import routeros_routing_ospf_instance.test_routing_ospf_instance "*0" \ No newline at end of file diff --git a/examples/resources/routeros_routing_ospf_interface_template/import.sh b/examples/resources/routeros_routing_ospf_interface_template/import.sh new file mode 100644 index 00000000..625eac18 --- /dev/null +++ b/examples/resources/routeros_routing_ospf_interface_template/import.sh @@ -0,0 +1,3 @@ +#The ID can be found via API or the terminal +#The command for the terminal is -> /routing/ospf/interface-template/print show-ids +terraform import routeros_routing_ospf_interface_template.test_routing_ospf_interface_template "*0" From f222f71691fd6e67b9967d66ef541e9d88376cea Mon Sep 17 00:00:00 2001 From: Vaerh Date: Mon, 19 Jun 2023 18:01:06 +0300 Subject: [PATCH 10/10] fix: Fix for error "no-summaries only valid for stubby areas" --- routeros/resource_routing_ospf_area.go | 1 - 1 file changed, 1 deletion(-) diff --git a/routeros/resource_routing_ospf_area.go b/routeros/resource_routing_ospf_area.go index f107bb59..e60ea650 100644 --- a/routeros/resource_routing_ospf_area.go +++ b/routeros/resource_routing_ospf_area.go @@ -46,7 +46,6 @@ func ResourceRoutingOspfArea() *schema.Resource { KeyName: PropNameForceNewRw, "no_summaries": { Type: schema.TypeBool, - Default: false, Optional: true, Description: "If set then the area will not flood summary LSAs in the stub area.", },