60
docs/resources/static_route.md
Normal file
60
docs/resources/static_route.md
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "unifi_static_route Resource - terraform-provider-unifi"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
unifi_static_route manages a static route.
|
||||
---
|
||||
|
||||
# unifi_static_route (Resource)
|
||||
|
||||
`unifi_static_route` manages a static route.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "unifi_static_route" "nexthop" {
|
||||
type = "nexthop-route"
|
||||
network = "172.17.0.0/16"
|
||||
name = "basic nexthop"
|
||||
distance = 1
|
||||
next_hop = "172.16.0.1"
|
||||
}
|
||||
|
||||
resource "unifi_static_route" "blackhole" {
|
||||
type = "blackhole"
|
||||
network = var.blackhole_cidr
|
||||
name = "blackhole traffice to cidr"
|
||||
distance = 1
|
||||
}
|
||||
|
||||
resource "unifi_static_route" "interface" {
|
||||
type = "interface-route"
|
||||
network = var.wan2_cidr
|
||||
name = "send traffic over wan2"
|
||||
distance = 1
|
||||
interface = "WAN2"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- **distance** (Number) The distance of the static route.
|
||||
- **name** (String) The name of the static route.
|
||||
- **network** (String) The network subnet address.
|
||||
- **type** (String) The type of static route. Can be `interface-route`, `nexthop-route`, or `blackhole`.
|
||||
|
||||
### Optional
|
||||
|
||||
- **interface** (String) The interface of the static route (only valid for `interface-route` type). This can be `WAN1`, `WAN2`, or a network ID.
|
||||
- **next_hop** (String) The next hop of the static route (only valid for `nexthop-route` type).
|
||||
- **site** (String) The name of the site to associate the static route with.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- **id** (String) The ID of the static route.
|
||||
|
||||
|
||||
22
examples/resources/unifi_static_route/resource.tf
Normal file
22
examples/resources/unifi_static_route/resource.tf
Normal file
@@ -0,0 +1,22 @@
|
||||
resource "unifi_static_route" "nexthop" {
|
||||
type = "nexthop-route"
|
||||
network = "172.17.0.0/16"
|
||||
name = "basic nexthop"
|
||||
distance = 1
|
||||
next_hop = "172.16.0.1"
|
||||
}
|
||||
|
||||
resource "unifi_static_route" "blackhole" {
|
||||
type = "blackhole"
|
||||
network = var.blackhole_cidr
|
||||
name = "blackhole traffice to cidr"
|
||||
distance = 1
|
||||
}
|
||||
|
||||
resource "unifi_static_route" "interface" {
|
||||
type = "interface-route"
|
||||
network = var.wan2_cidr
|
||||
name = "send traffic over wan2"
|
||||
distance = 1
|
||||
interface = "WAN2"
|
||||
}
|
||||
@@ -424,3 +424,38 @@ func (c *lazyClient) UpdatePortProfile(ctx context.Context, site string, d *unif
|
||||
}
|
||||
return c.inner.UpdatePortProfile(ctx, site, d)
|
||||
}
|
||||
|
||||
func (c *lazyClient) ListRouting(ctx context.Context, site string) ([]unifi.Routing, error) {
|
||||
if err := c.init(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.inner.ListRouting(ctx, site)
|
||||
}
|
||||
|
||||
func (c *lazyClient) GetRouting(ctx context.Context, site, id string) (*unifi.Routing, error) {
|
||||
if err := c.init(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.inner.GetRouting(ctx, site, id)
|
||||
}
|
||||
|
||||
func (c *lazyClient) DeleteRouting(ctx context.Context, site, id string) error {
|
||||
if err := c.init(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.inner.DeleteRouting(ctx, site, id)
|
||||
}
|
||||
|
||||
func (c *lazyClient) CreateRouting(ctx context.Context, site string, d *unifi.Routing) (*unifi.Routing, error) {
|
||||
if err := c.init(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.inner.CreateRouting(ctx, site, d)
|
||||
}
|
||||
|
||||
func (c *lazyClient) UpdateRouting(ctx context.Context, site string, d *unifi.Routing) (*unifi.Routing, error) {
|
||||
if err := c.init(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.inner.UpdateRouting(ctx, site, d)
|
||||
}
|
||||
|
||||
@@ -88,10 +88,11 @@ func New(version string) func() *schema.Provider {
|
||||
"unifi_network": resourceNetwork(),
|
||||
"unifi_port_forward": resourcePortForward(),
|
||||
"unifi_port_profile": resourcePortProfile(),
|
||||
"unifi_site": resourceSite(),
|
||||
"unifi_static_route": resourceStaticRoute(),
|
||||
"unifi_user_group": resourceUserGroup(),
|
||||
"unifi_user": resourceUser(),
|
||||
"unifi_wlan": resourceWLAN(),
|
||||
"unifi_site": resourceSite(),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -194,6 +195,12 @@ type unifiClient interface {
|
||||
DeletePortProfile(ctx context.Context, site, id string) error
|
||||
CreatePortProfile(ctx context.Context, site string, d *unifi.PortProfile) (*unifi.PortProfile, error)
|
||||
UpdatePortProfile(ctx context.Context, site string, d *unifi.PortProfile) (*unifi.PortProfile, error)
|
||||
|
||||
ListRouting(ctx context.Context, site string) ([]unifi.Routing, error)
|
||||
GetRouting(ctx context.Context, site, id string) (*unifi.Routing, error)
|
||||
DeleteRouting(ctx context.Context, site, id string) error
|
||||
CreateRouting(ctx context.Context, site string, d *unifi.Routing) (*unifi.Routing, error)
|
||||
UpdateRouting(ctx context.Context, site string, d *unifi.Routing) (*unifi.Routing, error)
|
||||
}
|
||||
|
||||
type client struct {
|
||||
|
||||
212
internal/provider/resource_static_route.go
Normal file
212
internal/provider/resource_static_route.go
Normal file
@@ -0,0 +1,212 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
"github.com/paultyng/go-unifi/unifi"
|
||||
)
|
||||
|
||||
func resourceStaticRoute() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Description: "`unifi_static_route` manages a static route.",
|
||||
|
||||
Create: resourceStaticRouteCreate,
|
||||
Read: resourceStaticRouteRead,
|
||||
Update: resourceStaticRouteUpdate,
|
||||
Delete: resourceStaticRouteDelete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: importSiteAndID,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"id": {
|
||||
Description: "The ID of the static route.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"site": {
|
||||
Description: "The name of the site to associate the static route with.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"name": {
|
||||
Description: "The name of the static route.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"network": {
|
||||
Description: "The network subnet address.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: cidrValidate,
|
||||
DiffSuppressFunc: cidrDiffSuppress,
|
||||
},
|
||||
"type": {
|
||||
Description: "The type of static route. Can be `interface-route`, `nexthop-route`, or `blackhole`.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{"interface-route", "nexthop-route", "blackhole"}, false),
|
||||
},
|
||||
"distance": {
|
||||
Description: "The distance of the static route.",
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"next_hop": {
|
||||
Description: "The next hop of the static route (only valid for `nexthop-route` type).",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ValidateFunc: validation.IsIPv4Address,
|
||||
},
|
||||
"interface": {
|
||||
Description: "The interface of the static route (only valid for `interface-route` type). This can be `WAN1`, `WAN2`, or a network ID.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceStaticRouteCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
c := meta.(*client)
|
||||
|
||||
req, err := resourceStaticRouteGetResourceData(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
site := d.Get("site").(string)
|
||||
if site == "" {
|
||||
site = c.site
|
||||
}
|
||||
|
||||
resp, err := c.c.CreateRouting(context.TODO(), site, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(resp.ID)
|
||||
|
||||
return resourceStaticRouteSetResourceData(resp, d, site)
|
||||
}
|
||||
|
||||
func resourceStaticRouteGetResourceData(d *schema.ResourceData) (*unifi.Routing, error) {
|
||||
t := d.Get("type").(string)
|
||||
|
||||
r := &unifi.Routing{
|
||||
Enabled: true,
|
||||
Type: "static-route",
|
||||
|
||||
Name: d.Get("name").(string),
|
||||
StaticRouteNetwork: cidrZeroBased(d.Get("network").(string)),
|
||||
StaticRouteDistance: d.Get("distance").(int),
|
||||
StaticRouteType: t,
|
||||
}
|
||||
|
||||
switch t {
|
||||
case "interface-route":
|
||||
r.StaticRouteInterface = d.Get("interface").(string)
|
||||
case "nexthop-route":
|
||||
r.StaticRouteNexthop = d.Get("next_hop").(string)
|
||||
case "blackhole":
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected route type: %q", t)
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func resourceStaticRouteSetResourceData(resp *unifi.Routing, d *schema.ResourceData, site string) error {
|
||||
d.Set("site", site)
|
||||
d.Set("name", resp.Name)
|
||||
d.Set("network", cidrZeroBased(resp.StaticRouteNetwork))
|
||||
d.Set("distance", resp.StaticRouteDistance)
|
||||
|
||||
t := resp.StaticRouteType
|
||||
d.Set("type", t)
|
||||
|
||||
d.Set("next_hop", "")
|
||||
d.Set("interface", "")
|
||||
|
||||
switch t {
|
||||
case "interface-route":
|
||||
d.Set("interface", resp.StaticRouteInterface)
|
||||
case "nexthop-route":
|
||||
d.Set("next_hop", resp.StaticRouteNexthop)
|
||||
case "blackhole":
|
||||
// no additional attributes
|
||||
default:
|
||||
return fmt.Errorf("unexpected static route type: %q", t)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceStaticRouteRead(d *schema.ResourceData, meta interface{}) error {
|
||||
c := meta.(*client)
|
||||
|
||||
id := d.Id()
|
||||
|
||||
site := d.Get("site").(string)
|
||||
if site == "" {
|
||||
site = c.site
|
||||
}
|
||||
|
||||
resp, err := c.c.GetRouting(context.TODO(), site, id)
|
||||
if _, ok := err.(*unifi.NotFoundError); ok {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceStaticRouteSetResourceData(resp, d, site)
|
||||
}
|
||||
|
||||
func resourceStaticRouteUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
c := meta.(*client)
|
||||
|
||||
req, err := resourceStaticRouteGetResourceData(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.ID = d.Id()
|
||||
|
||||
site := d.Get("site").(string)
|
||||
if site == "" {
|
||||
site = c.site
|
||||
}
|
||||
req.SiteID = site
|
||||
|
||||
resp, err := c.c.UpdateRouting(context.TODO(), site, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceStaticRouteSetResourceData(resp, d, site)
|
||||
}
|
||||
|
||||
func resourceStaticRouteDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
c := meta.(*client)
|
||||
|
||||
id := d.Id()
|
||||
|
||||
site := d.Get("site").(string)
|
||||
if site == "" {
|
||||
site = c.site
|
||||
}
|
||||
err := c.c.DeleteRouting(context.TODO(), site, id)
|
||||
if _, ok := err.(*unifi.NotFoundError); ok {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
87
internal/provider/resource_static_route_test.go
Normal file
87
internal/provider/resource_static_route_test.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccStaticRoute_nextHop(t *testing.T) {
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
PreCheck: func() { preCheck(t) },
|
||||
ProviderFactories: providerFactories,
|
||||
// TODO: CheckDestroy: ,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccStaticRouteConfig_nextHop,
|
||||
// Check: resource.ComposeTestCheckFunc(
|
||||
// // testCheckFirewallGroupExists(t, "name"),
|
||||
// ),
|
||||
},
|
||||
importStep("unifi_static_route.test"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccStaticRoute_blackhole(t *testing.T) {
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
PreCheck: func() { preCheck(t) },
|
||||
ProviderFactories: providerFactories,
|
||||
// TODO: CheckDestroy: ,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccStaticRouteConfig_blackhole,
|
||||
// Check: resource.ComposeTestCheckFunc(
|
||||
// // testCheckFirewallGroupExists(t, "name"),
|
||||
// ),
|
||||
},
|
||||
importStep("unifi_static_route.test"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccStaticRoute_interface(t *testing.T) {
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
PreCheck: func() { preCheck(t) },
|
||||
ProviderFactories: providerFactories,
|
||||
// TODO: CheckDestroy: ,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccStaticRouteConfig_interface,
|
||||
// Check: resource.ComposeTestCheckFunc(
|
||||
// // testCheckFirewallGroupExists(t, "name"),
|
||||
// ),
|
||||
},
|
||||
importStep("unifi_static_route.test"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const testAccStaticRouteConfig_nextHop = `
|
||||
resource "unifi_static_route" "test" {
|
||||
type = "nexthop-route"
|
||||
network = "172.17.0.0/16"
|
||||
name = "tf-acc basic nexthop"
|
||||
distance = 1
|
||||
next_hop = "172.16.0.1"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccStaticRouteConfig_blackhole = `
|
||||
resource "unifi_static_route" "test" {
|
||||
type = "blackhole"
|
||||
network = "172.17.0.0/16"
|
||||
name = "tf-acc basic blackhole"
|
||||
distance = 1
|
||||
}
|
||||
`
|
||||
|
||||
const testAccStaticRouteConfig_interface = `
|
||||
resource "unifi_static_route" "test" {
|
||||
type = "interface-route"
|
||||
network = "172.17.0.0/16"
|
||||
name = "tf-acc basic interface"
|
||||
distance = 1
|
||||
interface = "WAN2"
|
||||
}
|
||||
`
|
||||
Reference in New Issue
Block a user