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
|
@ -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
|
||||||
|
}
|
2
main.go
2
main.go
|
@ -64,6 +64,8 @@ func main() {
|
||||||
log.Fatalf("could not create server instance: %s", err)
|
log.Fatalf("could not create server instance: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.Register("layer3domain_create", layer3DomainCreate)
|
||||||
|
s.Register("ipblock_create", ipblockCreate)
|
||||||
s.Register("zone_create", zoneCreate)
|
s.Register("zone_create", zoneCreate)
|
||||||
s.Register("zone_list", zoneList)
|
s.Register("zone_list", zoneList)
|
||||||
|
|
||||||
|
|
|
@ -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