Browse Source
This is the first draft of creating layer3domains and ipblocks/containers. This allows some testing with different things, like list building for complex container output, but also how containers should behave.master
4 changed files with 132 additions and 0 deletions
@ -0,0 +1,43 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
|
||||
"dim/types" |
||||
) |
||||
|
||||
type ( |
||||
IPBlockCreateOptions struct { |
||||
Attributes string `json:"attributes"` |
||||
Layer3Domain string `json:"layer3domain"` |
||||
AllowOverlap bool `json:"allow_overlap"` |
||||
} |
||||
) |
||||
|
||||
func ipblockCreate(c *Context, req Request, res *Response) error { |
||||
block := new(types.Subnet) |
||||
options := IPBlockCreateOptions{ |
||||
Attributes: "{}", |
||||
} |
||||
if err := req.ParseAtLeast(1, block, &options); err != nil { |
||||
res.AddMessage(LevelError, "could not parse parameters: %s", err) |
||||
return nil |
||||
} |
||||
|
||||
l3Id := 0 |
||||
err := c.tx.QueryRow(`select id from layer3domains where name = $1 for update`, options.Layer3Domain).Scan(&l3Id) |
||||
if err != nil { |
||||
res.AddMessage(LevelError, "could not get layer3domain") |
||||
return fmt.Errorf("could not resolve layer3domain '%s': %s", options.Layer3Domain, err) |
||||
} |
||||
|
||||
_, err = c.tx.Exec(`insert into containers(layer3domain_id, network, created_by, modified_by, attributes) |
||||
values ($1, $2, $3, $3, $4::jsonb)`, |
||||
l3Id, block, c.username, options.Attributes) |
||||
if err != nil { |
||||
res.AddMessage(LevelError, "could not create ip block") |
||||
return fmt.Errorf("could not create container '%s': %s", block, err) |
||||
} |
||||
|
||||
return nil |
||||
} |
@ -0,0 +1,27 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
) |
||||
|
||||
type ( |
||||
Layer3DomainCreateOptions string |
||||
) |
||||
|
||||
func layer3DomainCreate(c *Context, req Request, res *Response) error { |
||||
name := "" |
||||
options := Layer3DomainCreateOptions("{}") |
||||
if err := req.ParseAtLeast(1, &name, &options); err != nil { |
||||
res.AddMessage(LevelError, "could not parse parameter: %s", err) |
||||
return nil |
||||
} |
||||
|
||||
_, err := c.tx.Exec(`insert into layer3domains(name, attributes, created_by, modified_by) |
||||
values ($1, $2::jsonb, $3, $3)`, name, options, c.username) |
||||
// TODO handle unique constraint violation
|
||||
if err != nil { |
||||
res.AddMessage(LevelError, "could not create layer3domain '%s'", name) |
||||
return fmt.Errorf("could not insert layer3domain '%s': %s", name, err) |
||||
} |
||||
return nil |
||||
} |
@ -0,0 +1,60 @@
|
||||
package types |
||||
|
||||
import ( |
||||
"bytes" |
||||
"database/sql/driver" |
||||
"fmt" |
||||
"net" |
||||
) |
||||
|
||||
type ( |
||||
// Subnet is used to parse a subnet parameter.
|
||||
Subnet net.IPNet |
||||
// IP is used to parse an IP parameter.
|
||||
IP net.IP |
||||
) |
||||
|
||||
// UnmarshalJSON parses a value into a subnet.
|
||||
//
|
||||
// It is also checked if the provided IP matches the network address
|
||||
// of the subnet.
|
||||
func (s *Subnet) UnmarshalJSON(in []byte) error { |
||||
in = bytes.Trim(in, `"`) |
||||
|
||||
ip, ipnet, err := net.ParseCIDR(string(in)) |
||||
if err != nil { |
||||
return fmt.Errorf("not a valid subnet") |
||||
} |
||||
if !ipnet.IP.Equal(ip) { |
||||
return fmt.Errorf("provided IP is not a subnet") |
||||
} |
||||
*s = Subnet(*ipnet) |
||||
return nil |
||||
} |
||||
|
||||
// String returns the string representation of the subnet.
|
||||
//
|
||||
// The subnet is returned as the subnet address and prefix separated by `/`
|
||||
// as defined in RFC 4632 and RFC 4291.
|
||||
func (s *Subnet) String() string { |
||||
return (*net.IPNet)(s).String() |
||||
} |
||||
|
||||
// Value implements the database Value interface.
|
||||
//
|
||||
// This function is needed so that a subnet can be inserted into
|
||||
// the database without much casting.
|
||||
func (s *Subnet) Value() (driver.Value, error) { |
||||
return s.String(), nil |
||||
} |
||||
|
||||
func (i *IP) UnmarshalJSON(in []byte) error { |
||||
in = bytes.Trim(in, `"`) |
||||
|
||||
ip := net.ParseIP(string(in)) |
||||
if ip == nil { |
||||
return fmt.Errorf("not a valid ip") |
||||
} |
||||
*i = IP(ip) |
||||
return nil |
||||
} |
Loading…
Reference in new issue