Skip to content

Commit

Permalink
feat: Support ipv6 firewall address lists
Browse files Browse the repository at this point in the history
Merge pull request #212 from dmaes/main
  • Loading branch information
vaerh committed May 17, 2023
2 parents c7d9264 + 57a330f commit 878fbf7
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 17 deletions.
41 changes: 41 additions & 0 deletions docs/resources/ipv6_firewall_addr_list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# routeros_ipv6_firewall_addr_list (Resource)


## Example Usage
```terraform
resource "routeros_ipv6_firewall_addr_list" "example_list" {
address = "123:dead:beaf::/64"
list = "Example List"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `address` (String) A single IPv6 address or IPv6 CIDR subnet
- `list` (String) Name for the address list of the added IPv6 address.

### Optional

- `comment` (String)
- `disabled` (Boolean)
- `timeout` (String) Time after address will be removed from address list. If timeout is not specified,
the address will be stored into the address list permanently.
> Please plan your work logic based on the fact that after the timeout
> the resource has been destroyed outside of Terraform.

### Read-Only

- `creation_time` (String) Rule creation time
- `dynamic` (Boolean) Configuration item created by software, not by management interface. It is not exported, and cannot be directly modified.
- `id` (String) The ID of this resource.

## Import
Import is supported using the following syntax:
```shell
#The ID can be found via API or the terminal
#The command for the terminal is -> :put [/ipv6/firewall/address-list get [print show-ids]]
terraform import routeros_ipv6_firewall_addr_list.example_list "*0"
```
3 changes: 3 additions & 0 deletions examples/resources/routeros_ipv6_firewall_addr_list/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#The ID can be found via API or the terminal
#The command for the terminal is -> :put [/ipv6/firewall/address-list get [print show-ids]]
terraform import routeros_ipv6_firewall_addr_list.example_list "*0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resource "routeros_ipv6_firewall_addr_list" "example_list" {
address = "123:dead:beaf::/64"
list = "Example List"
}
35 changes: 18 additions & 17 deletions routeros/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,24 @@ func Provider() *schema.Provider {
ResourcesMap: map[string]*schema.Resource{

// IP objects
"routeros_ip_dhcp_client": ResourceDhcpClient(),
"routeros_ip_dhcp_server": ResourceDhcpServer(),
"routeros_ip_dhcp_server_network": ResourceDhcpServerNetwork(),
"routeros_ip_dhcp_server_lease": ResourceDhcpServerLease(),
"routeros_ip_firewall_addr_list": ResourceIPFirewallAddrList(),
"routeros_ip_firewall_filter": ResourceIPFirewallFilter(),
"routeros_ip_firewall_mangle": ResourceIPFirewallMangle(),
"routeros_ip_firewall_nat": ResourceIPFirewallNat(),
"routeros_ip_address": ResourceIPAddress(),
"routeros_ip_pool": ResourceIPPool(),
"routeros_ip_route": ResourceIPRoute(),
"routeros_ip_dns": ResourceDns(),
"routeros_ip_dns_record": ResourceDnsRecord(),
"routeros_ip_service": ResourceIpService(),
"routeros_ipv6_address": ResourceIPv6Address(),
"routeros_ipv6_firewall_filter": ResourceIPv6FirewallFilter(),
"routeros_ipv6_route": ResourceIPv6Route(),
"routeros_ip_dhcp_client": ResourceDhcpClient(),
"routeros_ip_dhcp_server": ResourceDhcpServer(),
"routeros_ip_dhcp_server_network": ResourceDhcpServerNetwork(),
"routeros_ip_dhcp_server_lease": ResourceDhcpServerLease(),
"routeros_ip_firewall_addr_list": ResourceIPFirewallAddrList(),
"routeros_ip_firewall_filter": ResourceIPFirewallFilter(),
"routeros_ip_firewall_mangle": ResourceIPFirewallMangle(),
"routeros_ip_firewall_nat": ResourceIPFirewallNat(),
"routeros_ip_address": ResourceIPAddress(),
"routeros_ip_pool": ResourceIPPool(),
"routeros_ip_route": ResourceIPRoute(),
"routeros_ip_dns": ResourceDns(),
"routeros_ip_dns_record": ResourceDnsRecord(),
"routeros_ip_service": ResourceIpService(),
"routeros_ipv6_address": ResourceIPv6Address(),
"routeros_ipv6_firewall_addr_list": ResourceIPv6FirewallAddrList(),
"routeros_ipv6_firewall_filter": ResourceIPv6FirewallFilter(),
"routeros_ipv6_route": ResourceIPv6Route(),

// Aliases for IP objects to retain compatibility between original and fork
"routeros_dhcp_client": ResourceDhcpClient(),
Expand Down
89 changes: 89 additions & 0 deletions routeros/resource_ipv6_firewall_addr_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package routeros

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

/*
{
".id": "*1",
"address": "123:dead::beaf/64",
"creation-time": "sep/29/2022 07:09:24",
"disabled": "false",
"dynamic": "true",
"list": "AAA",
"timeout": "0s"
}
*/

// ResourceIPv6FirewallAddrList https://help.mikrotik.com/docs/display/ROS/Address-lists
// They work more or less the same as IPv4 address lists, except no ranges
func ResourceIPv6FirewallAddrList() *schema.Resource {
resSchema := map[string]*schema.Schema{
MetaResourcePath: PropResourcePath("/ipv6/firewall/address-list"),
MetaId: PropId(Id),

"address": {
Type: schema.TypeString,
Required: true,
Description: "A single IPv6 address or IPv6 CIDR subnet",
},
KeyComment: PropCommentRw,
"creation_time": {
Type: schema.TypeString,
Computed: true,
Description: "Rule creation time",
},
KeyDisabled: PropDisabledRw,
KeyDynamic: PropDynamicRo,
"list": {
Type: schema.TypeString,
Required: true,
Description: "Name for the address list of the added IPv6 address.",
},
"timeout": {
Type: schema.TypeString,
Optional: true,
Description: `Time after address will be removed from address list. If timeout is not specified,
the address will be stored into the address list permanently.
> Please plan your work logic based on the fact that after the timeout
> the resource has been destroyed outside of Terraform.
`,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if old == new {
return true
}

if old == "" || new == "" {
return false
}

// Compare intervals:
oDuration, err := ParseDuration(old)
if err != nil {
panic("[FirewallAddrList Timeout] parse 'old' duration error: " + err.Error())
}

nDuration, err := ParseDuration(new)
if err != nil {
panic("[FirewallAddrList Timeout] parse 'new' duration error: " + err.Error())
}

// old new
// ~ timeout = "4m59s" -> "5m"
return nDuration.Seconds() > oDuration.Seconds()
},
},
}
return &schema.Resource{
CreateContext: DefaultCreate(resSchema),
ReadContext: DefaultRead(resSchema),
UpdateContext: DefaultUpdate(resSchema),
DeleteContext: DefaultDelete(resSchema),
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: resSchema,
}
}
68 changes: 68 additions & 0 deletions routeros/resource_ipv6_firewall_addr_list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package routeros

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
)

const testIPv6FirewallAddrList = "routeros_ipv6_firewall_addr_list.data"

func TestAccIPv6FirewallAddrListTest_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("/ipv6/firewall/address-list", "routeros_ipv6_firewall_addr_list"),
Steps: []resource.TestStep{
{
Config: testAccIPv6FirewallAddrListConfig(),
Check: resource.ComposeTestCheckFunc(
testAccCheckIPv6FirewallAddrListExists(testIPv6FirewallAddrList),
resource.TestCheckResourceAttr(testIPv6FirewallAddrList, "list", "test-addr-list"),
resource.TestCheckResourceAttr(testIPv6FirewallAddrList, "address", "123:dead:beaf::/64"),
),
},
},
})

})
}
}

func testAccCheckIPv6FirewallAddrListExists(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 testAccIPv6FirewallAddrListConfig() string {
return `
provider "routeros" {
insecure = true
}
resource "routeros_ipv6_firewall_addr_list" "data" {
list = "test-addr-list"
address = "123:dead:beaf::/64"
timeout = "5m"
}
`
}

0 comments on commit 878fbf7

Please sign in to comment.