add layer3domain create and ipblock create
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.
This commit is contained in:
parent
5ed6482400
commit
1857bdd05a
43
ipblock_create.go
Normal file
43
ipblock_create.go
Normal file
@ -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
|
||||
}
|
27
layer3domain_create.go
Normal file
27
layer3domain_create.go
Normal file
@ -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
|
||||
}
|
2
main.go
2
main.go
@ -64,6 +64,8 @@ func main() {
|
||||
log.Fatalf("could not create server instance: %s", err)
|
||||
return
|
||||
}
|
||||
s.Register("layer3domain_create", layer3DomainCreate)
|
||||
s.Register("ipblock_create", ipblockCreate)
|
||||
s.Register("zone_create", zoneCreate)
|
||||
s.Register("zone_list", zoneList)
|
||||
|
||||
|
60
types/ip.go
Normal file
60
types/ip.go
Normal file
@ -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
Block a user