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"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"git.staur.ca/stobbsm/kea-manage/ipv4/reservation"
|
||||
"git.staur.ca/stobbsm/kea-manage/lib/database"
|
||||
@ -33,15 +34,6 @@ func Execute() {
|
||||
}
|
||||
|
||||
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
|
||||
@ -51,26 +43,33 @@ func init() {
|
||||
|
||||
func runMain(cmd *cobra.Command, args []string) {
|
||||
reslist := []*reservation.ReservationV4{}
|
||||
vlist := viper.Get("reservationV4").([]any)
|
||||
vlist := viper.Get("reservationV4").(map[string]any)
|
||||
|
||||
for _, v := range vlist {
|
||||
v := v.(map[string]any)
|
||||
r := reservation.ReserveV4MacAddr(
|
||||
v["type"].(string),
|
||||
v["identifier"].(string),
|
||||
v["ipv4"].(string),
|
||||
v["hostname"].(string),
|
||||
v["subnetid"].(int),
|
||||
)
|
||||
if !r.Validate() {
|
||||
slog.Error("reservation", slog.Any("validate", r))
|
||||
for k, v := range vlist {
|
||||
v := v.([]any)
|
||||
ki, err := strconv.ParseInt(k, 10, 0)
|
||||
if err != nil {
|
||||
slog.Error("reservation", slog.Any("subnetid", err.Error()))
|
||||
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,
|
||||
r,
|
||||
)
|
||||
reslist = append(
|
||||
reslist,
|
||||
r,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
slog.Debug("reslist", slog.Any("slice", reslist))
|
||||
@ -82,7 +81,11 @@ func runMain(cmd *cobra.Command, args []string) {
|
||||
v := v
|
||||
if err := pg.InsertResV4(v); err != nil {
|
||||
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 {
|
||||
slog.Error(err.Error())
|
||||
}
|
||||
|
@ -3,29 +3,24 @@ package reservation
|
||||
import (
|
||||
"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/macaddr"
|
||||
typeValidator "git.staur.ca/stobbsm/kea-manage/lib/validators/types"
|
||||
)
|
||||
|
||||
type ReservationV4 struct {
|
||||
IdentifierType types.Identifier
|
||||
SubnetID int
|
||||
Identifier string
|
||||
Ipv4 string
|
||||
Hostname string
|
||||
typeName string
|
||||
SubnetID int
|
||||
Identifier string
|
||||
Ipv4 string
|
||||
Hostname 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{
|
||||
typeName: identifierType,
|
||||
IdentifierType: types.LookupIdentifier(identifierType),
|
||||
SubnetID: subnet,
|
||||
Identifier: identifier,
|
||||
Ipv4: addr,
|
||||
Hostname: hostname,
|
||||
SubnetID: subnet,
|
||||
Identifier: identifier,
|
||||
Ipv4: addr,
|
||||
Hostname: hostname,
|
||||
}
|
||||
|
||||
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
|
||||
// is correct
|
||||
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) {
|
||||
slog.Error("validate", slog.Any("reservationV4.ipv4", r.Ipv4))
|
||||
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/lib/database"
|
||||
"git.staur.ca/stobbsm/kea-manage/lib/types"
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
@ -46,7 +47,35 @@ func (p *Postgres) InsertResV4(r *reservation.ReservationV4) error {
|
||||
}
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
@ -24,3 +24,10 @@ const insertIfNotExists = `INSERT INTO hosts (dhcp_identifier,
|
||||
WHERE dhcp4_subnet_id = $3
|
||||
AND dhcp_identifier_type = $2
|
||||
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