Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feta: Add IP Cloud #234

Merged
merged 1 commit into from
Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/resources/routeros_ip_cloud/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import routeros_ip_cloud.test .
5 changes: 5 additions & 0 deletions examples/resources/routeros_ip_cloud/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "routeros_ip_cloud" "test" {
ddns_enabled = true
update_time = false
ddns_update_interval = "11m"
}
1 change: 1 addition & 0 deletions routeros/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func Provider() *schema.Provider {
"routeros_wireguard_peer": ResourceInterfaceWireguardPeer(),

// System Objects
"routeros_ip_cloud": ResourceIpCloud(),
"routeros_system_identity": ResourceSystemIdentity(),
"routeros_system_scheduler": ResourceSystemScheduler(),
"routeros_system_certificate": ResourceSystemCertificate(),
Expand Down
113 changes: 113 additions & 0 deletions routeros/resource_ip_cloud.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package routeros

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

/*
{
"ddns-enabled": "true",
"ddns-update-interval": "1m",
"dns-name": "ad8a0be701ea.sn.mynetname.net",
"public-address": "31.173.86.120",
"status": "updated",
"update-time": "true",
"warning": "Router is behind a NAT. Remote connection might not work."
}
*/

// https://wiki.mikrotik.com/wiki/Manual:IP/Cloud
func ResourceIpCloud() *schema.Resource {
resSchema := map[string]*schema.Schema{
MetaResourcePath: PropResourcePath("/ip/cloud"),
MetaId: PropId(Id),

"ddns_enabled": {
Type: schema.TypeBool,
Optional: true,
Description: "If set to yes, then the device will send an encrypted message to the MikroTik's Cloud " +
"server. The server will then decrypt the message and verify that the sender is an " +
"authentic MikroTik device. If all is OK, then the MikroTik's Cloud server will create a " +
"DDNS record for this device and send a response to the device. Every minute the IP/Cloud " +
"service on the router will check if WAN IP address matches the one sent to MikroTik's " +
"Cloud server and will send encrypted update to cloud server if IP address changes.",
},
"ddns_update_interval": {
Type: schema.TypeString,
Optional: true,
Default: "none",
Description: "If set DDNS will attempt to connect IP Cloud servers at the set interval. If set to none " +
"it will continue to internally check IP address update and connect to IP Cloud servers " +
"as needed. Useful if IP address used is not on the router itself and thus, cannot be " +
"checked as a value internal to the router.",
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if old == new {
return true
}

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

return TimeEquall(k, old, new, d)
},
},
"dns_name": {
Type: schema.TypeString,
Computed: true,
Description: "Shows DNS name assigned to the rdevice. Name consists of 12 character serial number " +
"appended by .sn.mynetname.net. This field is visible only after at least one " +
"ddns-request is successfully completed.",
},
"public_address": {
Type: schema.TypeString,
Computed: true,
Description: "Shows device's IPv4 address that was sent to cloud server. This field is visible only " +
"after at least one IP Cloud request was successfully completed.",
},
"public_address_ivp6": {
Type: schema.TypeString,
Computed: true,
Description: "Shows device's IPv6 address that was sent to cloud server. This field is visible only " +
"after at least one IP Cloud request was successfully completed.",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Contains text string that describes current dns-service state. The messages are self " +
"explanatory updating... updated Error: no Internet connection Error: request timed out " +
"Error: REJECTED. Contact MikroTik support Error: internal error - should not happen. One " +
"possible cause is if router runs out of memory.",
},
"update_time": {
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "If set to yes then router clock will be set to time, provided by cloud server IF there " +
"is no NTP or SNTP client enabled. If set to no, then IP/Cloud service will never update " +
"the device's clock. If update-time is set to yes, Clock will be updated even when " +
"ddns-enabled is set to no.",
},
"warning": {
Type: schema.TypeString,
Computed: true,
Description: "Shows a warning message if IP address sent by the device differs from the IP address in " +
"UDP packet header as visible by the MikroTik's Cloud server. Typically this happens if " +
"the device is behind NAT. Example: 'DDNS server received request from IP 123.123.123.123 " +
"but your local IP was 192.168.88.23; DDNS service might not work'",
},
}

return &schema.Resource{
CreateContext: DefaultSystemCreate(resSchema),
ReadContext: DefaultSystemRead(resSchema),
UpdateContext: DefaultSystemUpdate(resSchema),
DeleteContext: DefaultSystemDelete(resSchema),

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

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

import (
"fmt"
"testing"

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

const testIpCloudAddress = "routeros_ip_cloud.test"

func TestAccIpCloudTest_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,
Steps: []resource.TestStep{
{
Config: testAccIpCloudConfig(0),
Check: resource.ComposeTestCheckFunc(
testAccCheckIpCloudExists(testIpCloudAddress),
resource.TestCheckResourceAttr(testIpCloudAddress, "ddns_update_interval", "none"),
),
},
{
Config: testAccIpCloudConfig(1),
Check: resource.ComposeTestCheckFunc(
testAccCheckIpCloudExists(testIpCloudAddress),
resource.TestCheckResourceAttr(testIpCloudAddress, "ddns_update_interval", "15m"),
),
},
{
Config: testAccIpCloudConfig(2),
Check: resource.ComposeTestCheckFunc(
testAccCheckIpCloudExists(testIpCloudAddress),
resource.TestCheckResourceAttr(testIpCloudAddress, "ddns_update_interval", "10m"),
),
},
{
Config: testAccIpCloudConfig(3),
Check: resource.ComposeTestCheckFunc(
testAccCheckIpCloudExists(testIpCloudAddress),
resource.TestCheckResourceAttr(testIpCloudAddress, "ddns_update_interval", "none"),
),
},
},
})
})
}
}

func testAccCheckIpCloudExists(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 testAccIpCloudConfig(n int) string {
var conf = []string{
`
resource "routeros_ip_cloud" "test" {
ddns_enabled = true
ddns_update_interval = "none"
}`,
`
resource "routeros_ip_cloud" "test" {
ddns_enabled = true
ddns_update_interval = "15m"
}`,
`
resource "routeros_ip_cloud" "test" {
ddns_enabled = true
ddns_update_interval = "600"
}`,
`
resource "routeros_ip_cloud" "test" {
ddns_enabled = true
}`,
}
return providerConfig + conf[n]
}