added sample config
- simplified configuration file - simplified to only use ipv4 and macaddresses for now - added update query - if insert fails with already exists error, try to update instead
This commit is contained in:
parent
8bcb14a8af
commit
e68723738b
55
cmd/root.go
55
cmd/root.go
@ -7,6 +7,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"git.staur.ca/stobbsm/kea-manage/ipv4/reservation"
|
"git.staur.ca/stobbsm/kea-manage/ipv4/reservation"
|
||||||
"git.staur.ca/stobbsm/kea-manage/lib/database"
|
"git.staur.ca/stobbsm/kea-manage/lib/database"
|
||||||
@ -33,15 +34,6 @@ func Execute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Here you will define your flags and configuration settings.
|
|
||||||
// Cobra supports persistent flags, which, if defined here,
|
|
||||||
// will be global for your application.
|
|
||||||
|
|
||||||
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.kea-manage.yaml)")
|
|
||||||
|
|
||||||
// Cobra also supports local flags, which will only run
|
|
||||||
// when this action is called directly.
|
|
||||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manage kea dhcp host reservations in postgresql directly
|
// Manage kea dhcp host reservations in postgresql directly
|
||||||
@ -51,26 +43,33 @@ func init() {
|
|||||||
|
|
||||||
func runMain(cmd *cobra.Command, args []string) {
|
func runMain(cmd *cobra.Command, args []string) {
|
||||||
reslist := []*reservation.ReservationV4{}
|
reslist := []*reservation.ReservationV4{}
|
||||||
vlist := viper.Get("reservationV4").([]any)
|
vlist := viper.Get("reservationV4").(map[string]any)
|
||||||
|
|
||||||
for _, v := range vlist {
|
for k, v := range vlist {
|
||||||
v := v.(map[string]any)
|
v := v.([]any)
|
||||||
r := reservation.ReserveV4MacAddr(
|
ki, err := strconv.ParseInt(k, 10, 0)
|
||||||
v["type"].(string),
|
if err != nil {
|
||||||
v["identifier"].(string),
|
slog.Error("reservation", slog.Any("subnetid", err.Error()))
|
||||||
v["ipv4"].(string),
|
|
||||||
v["hostname"].(string),
|
|
||||||
v["subnetid"].(int),
|
|
||||||
)
|
|
||||||
if !r.Validate() {
|
|
||||||
slog.Error("reservation", slog.Any("validate", r))
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
for _, vi := range v {
|
||||||
|
vi := vi.(map[string]any)
|
||||||
|
r := reservation.ReserveV4MacAddr(
|
||||||
|
vi["identifier"].(string),
|
||||||
|
vi["ipv4"].(string),
|
||||||
|
vi["hostname"].(string),
|
||||||
|
int(ki),
|
||||||
|
)
|
||||||
|
if !r.Validate() {
|
||||||
|
slog.Error("reservation", slog.Any("validate", r))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
reslist = append(
|
reslist = append(
|
||||||
reslist,
|
reslist,
|
||||||
r,
|
r,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("reslist", slog.Any("slice", reslist))
|
slog.Debug("reslist", slog.Any("slice", reslist))
|
||||||
@ -82,7 +81,11 @@ func runMain(cmd *cobra.Command, args []string) {
|
|||||||
v := v
|
v := v
|
||||||
if err := pg.InsertResV4(v); err != nil {
|
if err := pg.InsertResV4(v); err != nil {
|
||||||
if errors.As(err, &database.Exists) {
|
if errors.As(err, &database.Exists) {
|
||||||
slog.Info("exists", slog.Any("reservation", *v))
|
if err := pg.UpdateResV4(v); err != nil {
|
||||||
|
slog.Error("update", slog.Any("reservation", *v))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
slog.Info("updated", slog.Any("hostname", v.Hostname))
|
||||||
} else {
|
} else {
|
||||||
slog.Error(err.Error())
|
slog.Error(err.Error())
|
||||||
}
|
}
|
||||||
|
@ -3,29 +3,24 @@ package reservation
|
|||||||
import (
|
import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"git.staur.ca/stobbsm/kea-manage/lib/types"
|
|
||||||
"git.staur.ca/stobbsm/kea-manage/lib/validators/ipv4"
|
"git.staur.ca/stobbsm/kea-manage/lib/validators/ipv4"
|
||||||
"git.staur.ca/stobbsm/kea-manage/lib/validators/macaddr"
|
"git.staur.ca/stobbsm/kea-manage/lib/validators/macaddr"
|
||||||
typeValidator "git.staur.ca/stobbsm/kea-manage/lib/validators/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ReservationV4 struct {
|
type ReservationV4 struct {
|
||||||
IdentifierType types.Identifier
|
SubnetID int
|
||||||
SubnetID int
|
Identifier string
|
||||||
Identifier string
|
Ipv4 string
|
||||||
Ipv4 string
|
Hostname string
|
||||||
Hostname string
|
typeName string
|
||||||
typeName string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReserveV4MacAddr(identifierType string, identifier string, addr string, hostname string, subnet int) *ReservationV4 {
|
func ReserveV4MacAddr(identifier string, addr string, hostname string, subnet int) *ReservationV4 {
|
||||||
r := &ReservationV4{
|
r := &ReservationV4{
|
||||||
typeName: identifierType,
|
SubnetID: subnet,
|
||||||
IdentifierType: types.LookupIdentifier(identifierType),
|
Identifier: identifier,
|
||||||
SubnetID: subnet,
|
Ipv4: addr,
|
||||||
Identifier: identifier,
|
Hostname: hostname,
|
||||||
Ipv4: addr,
|
|
||||||
Hostname: hostname,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
@ -36,11 +31,6 @@ func ReserveV4MacAddr(identifierType string, identifier string, addr string, hos
|
|||||||
// This does not validate against the database, just validates that the written configuration
|
// This does not validate against the database, just validates that the written configuration
|
||||||
// is correct
|
// is correct
|
||||||
func (r *ReservationV4) Validate() bool {
|
func (r *ReservationV4) Validate() bool {
|
||||||
if !typeValidator.IsValid(r.typeName) {
|
|
||||||
slog.Error("validate", slog.Any("reservationV4.type", "invalid"))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ipv4.IsValid(r.Ipv4) {
|
if !ipv4.IsValid(r.Ipv4) {
|
||||||
slog.Error("validate", slog.Any("reservationV4.ipv4", r.Ipv4))
|
slog.Error("validate", slog.Any("reservationV4.ipv4", r.Ipv4))
|
||||||
return false
|
return false
|
||||||
|
16
kea-manage.sample.yaml
Normal file
16
kea-manage.sample.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
database:
|
||||||
|
type: pgx
|
||||||
|
host: postgres.example.net
|
||||||
|
port: 5432
|
||||||
|
user: keauser
|
||||||
|
password: secure-kea-postgres-password
|
||||||
|
name: kea-database-name
|
||||||
|
reservationV4:
|
||||||
|
<subnetid1>:
|
||||||
|
- identifier: "11:11:11:11:11:11"
|
||||||
|
hostname: hostname-to-reserve
|
||||||
|
ipv4: 192.168.111.2
|
||||||
|
<subnetid2>:
|
||||||
|
- identifier: "11:11:11:11:11:12"
|
||||||
|
hostname: another-hostname-to-reserve
|
||||||
|
ipv4: 192.168.112.2
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"git.staur.ca/stobbsm/kea-manage/ipv4/reservation"
|
"git.staur.ca/stobbsm/kea-manage/ipv4/reservation"
|
||||||
"git.staur.ca/stobbsm/kea-manage/lib/database"
|
"git.staur.ca/stobbsm/kea-manage/lib/database"
|
||||||
|
"git.staur.ca/stobbsm/kea-manage/lib/types"
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,7 +47,35 @@ func (p *Postgres) InsertResV4(r *reservation.ReservationV4) error {
|
|||||||
}
|
}
|
||||||
defer tx.Rollback(context.Background())
|
defer tx.Rollback(context.Background())
|
||||||
|
|
||||||
ct, err := tx.Exec(context.Background(), insertIfNotExists, r.Identifier, r.IdentifierType, r.SubnetID, r.Ipv4, r.Hostname)
|
ct, err := tx.Exec(context.Background(), insertIfNotExists, r.Identifier, types.HwAddress.Int(), r.SubnetID, r.Ipv4, r.Hostname)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tx.Commit(context.Background()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ct.RowsAffected() == 0 {
|
||||||
|
return database.Exists
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Postgres) UpdateResV4(r *reservation.ReservationV4) error {
|
||||||
|
if err := p.connect(context.Background()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer p.close()
|
||||||
|
|
||||||
|
tx, err := p.conn.Begin(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer tx.Rollback(context.Background())
|
||||||
|
|
||||||
|
ct, err := tx.Exec(context.Background(), update, r.Identifier, types.HwAddress.Int(), r.SubnetID, r.Ipv4, r.Hostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -24,3 +24,10 @@ const insertIfNotExists = `INSERT INTO hosts (dhcp_identifier,
|
|||||||
WHERE dhcp4_subnet_id = $3
|
WHERE dhcp4_subnet_id = $3
|
||||||
AND dhcp_identifier_type = $2
|
AND dhcp_identifier_type = $2
|
||||||
AND dhcp_identifier = DECODE(REPLACE($1, ':', ''), 'hex'));`
|
AND dhcp_identifier = DECODE(REPLACE($1, ':', ''), 'hex'));`
|
||||||
|
|
||||||
|
const update = `UPDATE hosts
|
||||||
|
SET ipv4_address = (SELECT ($4::inet - '0.0.0.0'::inet)),
|
||||||
|
hostname = $5
|
||||||
|
WHERE dhcp_identifier = (SELECT DECODE(REPLACE($1, ':', ''), 'hex')) AND
|
||||||
|
dhcp_identifier_type = $2 AND
|
||||||
|
dhcp4_subnet_id = $3;`
|
||||||
|
Loading…
Reference in New Issue
Block a user