test cron job
This commit is contained in:
@@ -30,6 +30,7 @@ A few different technologies are configured to help getting off the ground easie
|
||||
- The script `upgrade_htmx.sh` is available to make upgrading easier
|
||||
- [goose](https://github.com/pressly/goose) for DB migrations
|
||||
|
||||
TODO: investigate https://github.com/DATA-DOG/go-sqlmock for testing
|
||||
|
||||
Technologies we're no longer using:
|
||||
- [golang migrate](https://github.com/golang-migrate/migrate) for DB migrations
|
||||
|
17
db/migrations/20240913043145_extend_events.sql
Normal file
17
db/migrations/20240913043145_extend_events.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE "Events" RENAME COLUMN Datacenter to DatacenterName;
|
||||
ALTER TABLE "Events" RENAME COLUMN ComputeResource to ComputeResourceName;
|
||||
ALTER TABLE "Events" ADD COLUMN DatacenterId TEXT;
|
||||
ALTER TABLE "Events" ADD COLUMN ComputeResourceId TEXT;
|
||||
ALTER TABLE "Events" ADD COLUMN VmName TEXT;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE "Events" DROP COLUMN VmName;
|
||||
ALTER TABLE "Updates" DROP COLUMN ComputeResourceId;
|
||||
ALTER TABLE "Updates" DROP COLUMN DatacenterId;
|
||||
ALTER TABLE "Events" RENAME COLUMN ComputeResourceName to ComputeResource;
|
||||
ALTER TABLE "Events" RENAME COLUMN DatacenterName to Datacenter;
|
||||
-- +goose StatementEnd
|
@@ -9,17 +9,20 @@ import (
|
||||
)
|
||||
|
||||
type Events struct {
|
||||
Eid int64
|
||||
CloudId string
|
||||
Source string
|
||||
EventTime sql.NullInt64
|
||||
ChainId string
|
||||
VmId sql.NullString
|
||||
EventKey sql.NullString
|
||||
Datacenter sql.NullString
|
||||
ComputeResource sql.NullString
|
||||
UserName sql.NullString
|
||||
Processed int64
|
||||
Eid int64
|
||||
CloudId string
|
||||
Source string
|
||||
EventTime sql.NullInt64
|
||||
ChainId string
|
||||
VmId sql.NullString
|
||||
EventKey sql.NullString
|
||||
DatacenterName sql.NullString
|
||||
ComputeResourceName sql.NullString
|
||||
UserName sql.NullString
|
||||
Processed int64
|
||||
DatacenterId sql.NullString
|
||||
ComputeResourceId sql.NullString
|
||||
VmName sql.NullString
|
||||
}
|
||||
|
||||
type Inventory struct {
|
||||
|
@@ -32,9 +32,9 @@ RETURNING *;
|
||||
|
||||
-- name: CreateEvent :one
|
||||
INSERT INTO "Events" (
|
||||
"CloudId", "Source", "EventTime", "ChainId", "VmId", "EventKey", "Datacenter", "ComputeResource", "UserName"
|
||||
"CloudId", "Source", "EventTime", "ChainId", "VmId", "VmName", "EventKey", "DatacenterId", "DatacenterName", "ComputeResourceId", "ComputeResourceName", "UserName"
|
||||
) VALUES(
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
|
@@ -12,23 +12,26 @@ import (
|
||||
|
||||
const createEvent = `-- name: CreateEvent :one
|
||||
INSERT INTO "Events" (
|
||||
"CloudId", "Source", "EventTime", "ChainId", "VmId", "EventKey", "Datacenter", "ComputeResource", "UserName"
|
||||
"CloudId", "Source", "EventTime", "ChainId", "VmId", "VmName", "EventKey", "DatacenterId", "DatacenterName", "ComputeResourceId", "ComputeResourceName", "UserName"
|
||||
) VALUES(
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||
)
|
||||
RETURNING Eid, CloudId, Source, EventTime, ChainId, VmId, EventKey, Datacenter, ComputeResource, UserName, Processed
|
||||
RETURNING Eid, CloudId, Source, EventTime, ChainId, VmId, EventKey, DatacenterName, ComputeResourceName, UserName, Processed, DatacenterId, ComputeResourceId, VmName
|
||||
`
|
||||
|
||||
type CreateEventParams struct {
|
||||
CloudId string
|
||||
Source string
|
||||
EventTime sql.NullInt64
|
||||
ChainId string
|
||||
VmId sql.NullString
|
||||
EventKey sql.NullString
|
||||
Datacenter sql.NullString
|
||||
ComputeResource sql.NullString
|
||||
UserName sql.NullString
|
||||
CloudId string
|
||||
Source string
|
||||
EventTime sql.NullInt64
|
||||
ChainId string
|
||||
VmId sql.NullString
|
||||
VmName sql.NullString
|
||||
EventKey sql.NullString
|
||||
DatacenterId sql.NullString
|
||||
DatacenterName sql.NullString
|
||||
ComputeResourceId sql.NullString
|
||||
ComputeResourceName sql.NullString
|
||||
UserName sql.NullString
|
||||
}
|
||||
|
||||
func (q *Queries) CreateEvent(ctx context.Context, arg CreateEventParams) (Events, error) {
|
||||
@@ -38,9 +41,12 @@ func (q *Queries) CreateEvent(ctx context.Context, arg CreateEventParams) (Event
|
||||
arg.EventTime,
|
||||
arg.ChainId,
|
||||
arg.VmId,
|
||||
arg.VmName,
|
||||
arg.EventKey,
|
||||
arg.Datacenter,
|
||||
arg.ComputeResource,
|
||||
arg.DatacenterId,
|
||||
arg.DatacenterName,
|
||||
arg.ComputeResourceId,
|
||||
arg.ComputeResourceName,
|
||||
arg.UserName,
|
||||
)
|
||||
var i Events
|
||||
@@ -52,10 +58,13 @@ func (q *Queries) CreateEvent(ctx context.Context, arg CreateEventParams) (Event
|
||||
&i.ChainId,
|
||||
&i.VmId,
|
||||
&i.EventKey,
|
||||
&i.Datacenter,
|
||||
&i.ComputeResource,
|
||||
&i.DatacenterName,
|
||||
&i.ComputeResourceName,
|
||||
&i.UserName,
|
||||
&i.Processed,
|
||||
&i.DatacenterId,
|
||||
&i.ComputeResourceId,
|
||||
&i.VmName,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -281,7 +290,7 @@ func (q *Queries) GetInventoryVmId(ctx context.Context, vmid sql.NullString) (In
|
||||
}
|
||||
|
||||
const listEvents = `-- name: ListEvents :many
|
||||
SELECT Eid, CloudId, Source, EventTime, ChainId, VmId, EventKey, Datacenter, ComputeResource, UserName, Processed FROM "Events"
|
||||
SELECT Eid, CloudId, Source, EventTime, ChainId, VmId, EventKey, DatacenterName, ComputeResourceName, UserName, Processed, DatacenterId, ComputeResourceId, VmName FROM "Events"
|
||||
ORDER BY "EventTime"
|
||||
`
|
||||
|
||||
@@ -302,10 +311,13 @@ func (q *Queries) ListEvents(ctx context.Context) ([]Events, error) {
|
||||
&i.ChainId,
|
||||
&i.VmId,
|
||||
&i.EventKey,
|
||||
&i.Datacenter,
|
||||
&i.ComputeResource,
|
||||
&i.DatacenterName,
|
||||
&i.ComputeResourceName,
|
||||
&i.UserName,
|
||||
&i.Processed,
|
||||
&i.DatacenterId,
|
||||
&i.ComputeResourceId,
|
||||
&i.VmName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -367,7 +379,7 @@ func (q *Queries) ListInventory(ctx context.Context) ([]Inventory, error) {
|
||||
}
|
||||
|
||||
const listUnprocessedEvents = `-- name: ListUnprocessedEvents :many
|
||||
SELECT Eid, CloudId, Source, EventTime, ChainId, VmId, EventKey, Datacenter, ComputeResource, UserName, Processed FROM "Events"
|
||||
SELECT Eid, CloudId, Source, EventTime, ChainId, VmId, EventKey, DatacenterName, ComputeResourceName, UserName, Processed, DatacenterId, ComputeResourceId, VmName FROM "Events"
|
||||
WHERE "Processed" = 0
|
||||
ORDER BY "EventTime"
|
||||
`
|
||||
@@ -389,10 +401,13 @@ func (q *Queries) ListUnprocessedEvents(ctx context.Context) ([]Events, error) {
|
||||
&i.ChainId,
|
||||
&i.VmId,
|
||||
&i.EventKey,
|
||||
&i.Datacenter,
|
||||
&i.ComputeResource,
|
||||
&i.DatacenterName,
|
||||
&i.ComputeResourceName,
|
||||
&i.UserName,
|
||||
&i.Processed,
|
||||
&i.DatacenterId,
|
||||
&i.ComputeResourceId,
|
||||
&i.VmName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
4
go.mod
4
go.mod
@@ -4,6 +4,7 @@ go 1.23.1
|
||||
|
||||
require (
|
||||
github.com/a-h/templ v0.2.778
|
||||
github.com/go-co-op/gocron/v2 v2.11.0
|
||||
github.com/jmoiron/sqlx v1.4.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/pressly/goose/v3 v3.22.0
|
||||
@@ -15,12 +16,15 @@ require (
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mfridman/interpolate v0.0.2 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/sethvargo/go-retry v0.3.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/tools v0.25.0 // indirect
|
||||
|
10
go.sum
10
go.sum
@@ -6,6 +6,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/go-co-op/gocron/v2 v2.11.0 h1:IOowNA6SzwdRFnD4/Ol3Kj6G2xKfsoiiGq2Jhhm9bvE=
|
||||
github.com/go-co-op/gocron/v2 v2.11.0/go.mod h1:xY7bJxGazKam1cz04EebrlP4S9q4iWdiAylMGP3jY9w=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
@@ -20,6 +22,8 @@ github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
|
||||
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
@@ -36,14 +40,20 @@ github.com/pressly/goose/v3 v3.22.0 h1:wd/7kNiPTuNAztWun7iaB98DrhulbWPrzMAaw2DEZ
|
||||
github.com/pressly/goose/v3 v3.22.0/go.mod h1:yJM3qwSj2pp7aAaCvso096sguezamNb2OBgxCnh/EYg=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
|
||||
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/vmware/govmomi v0.43.0 h1:7Kg3Bkdly+TrE67BYXzRq7ZrDnn7xqpKX95uEh2f9Go=
|
||||
github.com/vmware/govmomi v0.43.0/go.mod h1:IOv5nTXCPqH9qVJAlRuAGffogaLsNs8aF+e7vLgsHJU=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
|
@@ -1,3 +1,76 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"time"
|
||||
"vctp/db"
|
||||
"vctp/internal/vcenter"
|
||||
)
|
||||
|
||||
// Handler handles requests.
|
||||
type CronTask struct {
|
||||
Logger *slog.Logger
|
||||
Database db.Database
|
||||
}
|
||||
|
||||
// use gocron to check events in the Events table
|
||||
func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error {
|
||||
var (
|
||||
//unixTimestamp int64
|
||||
numVcpus int32
|
||||
numRam int32
|
||||
datacenter string
|
||||
)
|
||||
|
||||
logger.Debug("Started Events processing", "time", time.Now())
|
||||
|
||||
// Query events table
|
||||
events, err := c.Database.Queries().ListUnprocessedEvents(ctx)
|
||||
if err != nil {
|
||||
logger.Error("Unable to query for unprocessed events", "error", err)
|
||||
return nil // TODO - what to do with this error?
|
||||
}
|
||||
|
||||
for _, evt := range events {
|
||||
logger.Debug("Checking event", "event", evt)
|
||||
|
||||
c.Logger.Debug("connecting to vcenter")
|
||||
vc := vcenter.New(c.Logger)
|
||||
vc.Login(evt.Source)
|
||||
//vmObject, err := vc.FindVMByName(vm.CloudEvent.Data.VM.Name)
|
||||
//vmObject, err := vc.FindVMByID(vm.CloudEvent.Data.VM.VM.Value)
|
||||
vmObject, err := vc.FindVMByIDWithDatacenter(evt.VmId.String, evt.DatacenterId.String)
|
||||
|
||||
if err != nil {
|
||||
c.Logger.Error("Can't locate vm in vCenter", "vmID", evt.VmId.String, "error", err)
|
||||
} else if vmObject == nil {
|
||||
c.Logger.Debug("didn't find VM", "vm_id", evt.VmId.String)
|
||||
numRam = 0
|
||||
numVcpus = 0
|
||||
datacenter = evt.DatacenterName.String
|
||||
} else {
|
||||
c.Logger.Debug("found VM")
|
||||
//prettyPrint(vmObject)
|
||||
|
||||
// calculate VM properties we want to store
|
||||
if vmObject.Vm.Config != nil {
|
||||
numRam = vmObject.Vm.Config.Hardware.MemoryMB
|
||||
numVcpus = vmObject.Vm.Config.Hardware.NumCPU * vmObject.Vm.Config.Hardware.NumCoresPerSocket
|
||||
} else {
|
||||
c.Logger.Error("Empty VM config")
|
||||
}
|
||||
|
||||
}
|
||||
err = vc.Logout()
|
||||
if err != nil {
|
||||
c.Logger.Error("unable to logout of vcenter", "error", err)
|
||||
}
|
||||
|
||||
c.Logger.Debug("Simulate adding to Inventory", "vm_name", evt.VmName.String, "vcpus", numVcpus, "ram", numRam, "dc", datacenter)
|
||||
|
||||
}
|
||||
|
||||
//fmt.Printf("processing at %s", time.Now())
|
||||
return nil
|
||||
}
|
||||
|
@@ -24,8 +24,8 @@ type Vcenter struct {
|
||||
}
|
||||
|
||||
type VmProperties struct {
|
||||
Vm mo.VirtualMachine
|
||||
Datacenter string
|
||||
Vm mo.VirtualMachine
|
||||
//Datacenter string
|
||||
}
|
||||
|
||||
// New creates a new Vcenter with the given logger
|
||||
@@ -159,14 +159,14 @@ func (v *Vcenter) FindVMByID(vmID string) (*VmProperties, error) {
|
||||
|
||||
if err == nil {
|
||||
return &VmProperties{
|
||||
Datacenter: dc.Name(),
|
||||
Vm: vm,
|
||||
//Datacenter: dc.Name(),
|
||||
Vm: vm,
|
||||
}, nil
|
||||
} else if _, ok := err.(*find.NotFoundError); !ok {
|
||||
// If the error is not a NotFoundError, return it
|
||||
//return nil, fmt.Errorf("failed to retrieve VM with ID %s in datacenter %s: %w", vmID, dc.Name(), err)
|
||||
v.Logger.Debug("Couldn't find vm in datacenter", "vm_id", vmID, "datacenter_name", dc.Name())
|
||||
} else if err != nil {
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to retrieve VM: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,7 @@ func (v *Vcenter) FindVMByID(vmID string) (*VmProperties, error) {
|
||||
}
|
||||
|
||||
func (v *Vcenter) FindVMByIDWithDatacenter(vmID string, dcID string) (*VmProperties, error) {
|
||||
var dcName string
|
||||
//var dcName string
|
||||
var err error
|
||||
v.Logger.Debug("searching for vm id", "vm_id", vmID, "datacenter_id", dcID)
|
||||
|
||||
@@ -196,11 +196,13 @@ func (v *Vcenter) FindVMByIDWithDatacenter(vmID string, dcID string) (*VmPropert
|
||||
// Use finder.SetDatacenter to set the datacenter
|
||||
finder.SetDatacenter(datacenter)
|
||||
|
||||
dcName, err = datacenter.ObjectName(v.ctx)
|
||||
if err != nil {
|
||||
v.Logger.Error("Couldn't find the name of the datacenter", "error", err)
|
||||
dcName = ""
|
||||
}
|
||||
/*
|
||||
dcName, err = datacenter.ObjectName(v.ctx)
|
||||
if err != nil {
|
||||
v.Logger.Error("Couldn't find the name of the datacenter", "error", err)
|
||||
dcName = ""
|
||||
}
|
||||
*/
|
||||
|
||||
// Create a ManagedObjectReference for the VM
|
||||
vmRef := types.ManagedObjectReference{
|
||||
@@ -214,14 +216,14 @@ func (v *Vcenter) FindVMByIDWithDatacenter(vmID string, dcID string) (*VmPropert
|
||||
if err == nil {
|
||||
v.Logger.Debug("Found VM", "vm", vm)
|
||||
return &VmProperties{
|
||||
Datacenter: dcName,
|
||||
Vm: vm,
|
||||
//Datacenter: dcName,
|
||||
Vm: vm,
|
||||
}, nil
|
||||
} else if _, ok := err.(*find.NotFoundError); !ok {
|
||||
// If the error is not a NotFoundError, return it
|
||||
//return nil, fmt.Errorf("failed to retrieve VM with ID %s in datacenter %s: %w", vmID, dc.Name(), err)
|
||||
v.Logger.Debug("Couldn't find vm in datacenter", "vm_id", vmID, "datacenter_name", dcName)
|
||||
} else if err != nil {
|
||||
v.Logger.Debug("Couldn't find vm in datacenter", "vm_id", vmID, "datacenter_id", dcID)
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to retrieve VM: %w", err)
|
||||
}
|
||||
|
||||
|
52
main.go
52
main.go
@@ -1,15 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"time"
|
||||
"vctp/db"
|
||||
"vctp/internal/tasks"
|
||||
utils "vctp/internal/utils"
|
||||
"vctp/log"
|
||||
"vctp/server"
|
||||
"vctp/server/router"
|
||||
|
||||
"github.com/go-co-op/gocron/v2"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
@@ -17,6 +21,7 @@ var (
|
||||
bindDisableTls bool
|
||||
sha1ver string // sha1 revision used to build the program
|
||||
buildTime string // when the executable was built
|
||||
cronFrequency time.Duration
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -32,6 +37,8 @@ func main() {
|
||||
log.GetOutput(),
|
||||
)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
// Configure database
|
||||
database, err := db.New(logger, "./db.sqlite3")
|
||||
if err != nil {
|
||||
@@ -45,6 +52,19 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// Prepare the task scheduler
|
||||
s, err := gocron.NewScheduler()
|
||||
if err != nil {
|
||||
logger.Error("failed to create scheduler", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Pass useful information to the cron jobs
|
||||
c := &tasks.CronTask{
|
||||
Logger: logger,
|
||||
Database: database,
|
||||
}
|
||||
|
||||
// Determine bind IP
|
||||
bindIP := os.Getenv("BIND_IP")
|
||||
if bindIP == "" {
|
||||
@@ -85,9 +105,41 @@ func main() {
|
||||
utils.GenerateCerts(tlsCertFilename, tlsKeyFilename)
|
||||
}
|
||||
|
||||
cronFrequencyString := os.Getenv("VCENTER_POLLING_SECONDS")
|
||||
if cronFrequencyString != "" {
|
||||
cronFrequency, err = time.ParseDuration(cronFrequencyString)
|
||||
if err != nil {
|
||||
slog.Error("Can't convert VCENTER_POLLING_SECONDS value to time duration. Defaulting to 60s", "value", cronFrequencyString, "error", err)
|
||||
cronFrequency = time.Second * 60
|
||||
}
|
||||
} else {
|
||||
cronFrequency = time.Second * 60
|
||||
}
|
||||
logger.Debug("Setting VM polling cronjob frequency to", "frequency", cronFrequency)
|
||||
|
||||
// start background processing
|
||||
startsAt := time.Now().Add(time.Second * 10)
|
||||
job, err := s.NewJob(
|
||||
gocron.DurationJob(cronFrequency),
|
||||
gocron.NewTask(func() {
|
||||
c.RunVmCheck(ctx, logger)
|
||||
}), gocron.WithSingletonMode(gocron.LimitModeReschedule),
|
||||
gocron.WithStartAt(gocron.WithStartDateTime(startsAt)),
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error("failed to start cron jobs", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
slog.Debug("Created cron job", "job", job)
|
||||
|
||||
s.Start()
|
||||
|
||||
// Start server
|
||||
svr := server.New(
|
||||
logger,
|
||||
s,
|
||||
cancel,
|
||||
bindAddress,
|
||||
server.WithRouter(router.New(logger, database)),
|
||||
)
|
||||
|
@@ -44,6 +44,8 @@ func (h *Handler) VmCreate(w http.ResponseWriter, r *http.Request) {
|
||||
prettyPrint(event)
|
||||
}
|
||||
|
||||
e := event.CloudEvent.Data
|
||||
|
||||
// Convert vmModel to CreateInventoryParams using the utility function
|
||||
//var params queries.CreateInventoryParams
|
||||
//db.ConvertToSQLParams(&vm, ¶ms)
|
||||
@@ -65,15 +67,15 @@ func (h *Handler) VmCreate(w http.ResponseWriter, r *http.Request) {
|
||||
vc.Login(event.CloudEvent.Source)
|
||||
//vmObject, err := vc.FindVMByName(vm.CloudEvent.Data.VM.Name)
|
||||
//vmObject, err := vc.FindVMByID(vm.CloudEvent.Data.VM.VM.Value)
|
||||
vmObject, err := vc.FindVMByIDWithDatacenter(event.CloudEvent.Data.VM.VM.Value, event.CloudEvent.Data.Datacenter.Datacenter.Value)
|
||||
vmObject, err := vc.FindVMByIDWithDatacenter(e.VM.VM.Value, e.Datacenter.Datacenter.Value)
|
||||
|
||||
if err != nil {
|
||||
h.Logger.Error("Can't locate vm in vCenter", "vmID", event.CloudEvent.Data.VM.VM.Value, "error", err)
|
||||
h.Logger.Error("Can't locate vm in vCenter", "vmID", e.VM.VM.Value, "error", err)
|
||||
} else if vmObject == nil {
|
||||
h.Logger.Debug("didn't find VM", "vm_id", event.CloudEvent.Data.VM.VM.Value)
|
||||
h.Logger.Debug("didn't find VM", "vm_id", e.VM.VM.Value)
|
||||
numRam = 0
|
||||
numVcpus = 0
|
||||
datacenter = event.CloudEvent.Data.Datacenter.Name
|
||||
datacenter = e.Datacenter.Name
|
||||
} else {
|
||||
h.Logger.Debug("found VM")
|
||||
//prettyPrint(vmObject)
|
||||
@@ -95,15 +97,16 @@ func (h *Handler) VmCreate(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Create an instance of CreateInventoryParams
|
||||
h.Logger.Debug("Creating database parameters")
|
||||
|
||||
/*
|
||||
params := queries.CreateInventoryParams{
|
||||
Name: event.CloudEvent.Data.VM.Name,
|
||||
Name: e.VM.Name,
|
||||
Vcenter: event.CloudEvent.Source,
|
||||
EventId: sql.NullString{String: event.CloudEvent.ID, Valid: event.CloudEvent.ID != ""},
|
||||
EventKey: sql.NullString{String: strconv.Itoa(event.CloudEvent.Data.Key), Valid: strconv.Itoa(event.CloudEvent.Data.Key) != ""},
|
||||
VmId: sql.NullString{String: event.CloudEvent.Data.VM.VM.Value, Valid: event.CloudEvent.Data.VM.VM.Value != ""},
|
||||
EventKey: sql.NullString{String: strconv.Itoa(e.Key), Valid: strconv.Itoa(e.Key) != ""},
|
||||
VmId: sql.NullString{String: e.VM.VM.Value, Valid: e.VM.VM.Value != ""},
|
||||
Datacenter: sql.NullString{String: datacenter, Valid: datacenter != ""},
|
||||
Cluster: sql.NullString{String: event.CloudEvent.Data.ComputeResource.Name, Valid: event.CloudEvent.Data.ComputeResource.Name != ""},
|
||||
Cluster: sql.NullString{String: e.ComputeResource.Name, Valid: e.ComputeResource.Name != ""},
|
||||
CreationTime: sql.NullInt64{Int64: unixTimestamp, Valid: unixTimestamp > 0},
|
||||
InitialVcpus: sql.NullInt64{Int64: int64(numVcpus), Valid: numVcpus > 0},
|
||||
InitialRam: sql.NullInt64{Int64: int64(numRam), Valid: numRam > 0},
|
||||
@@ -111,15 +114,18 @@ func (h *Handler) VmCreate(w http.ResponseWriter, r *http.Request) {
|
||||
*/
|
||||
|
||||
params2 := queries.CreateEventParams{
|
||||
Source: event.CloudEvent.Source,
|
||||
CloudId: event.CloudEvent.ID,
|
||||
EventTime: sql.NullInt64{Int64: unixTimestamp, Valid: unixTimestamp > 0},
|
||||
ChainId: strconv.Itoa(event.CloudEvent.Data.ChainID),
|
||||
VmId: sql.NullString{String: event.CloudEvent.Data.VM.VM.Value, Valid: event.CloudEvent.Data.VM.VM.Value != ""},
|
||||
EventKey: sql.NullString{String: strconv.Itoa(event.CloudEvent.Data.Key), Valid: strconv.Itoa(event.CloudEvent.Data.Key) != ""},
|
||||
Datacenter: sql.NullString{String: event.CloudEvent.Data.Datacenter.Name, Valid: event.CloudEvent.Data.Datacenter.Name != ""},
|
||||
ComputeResource: sql.NullString{String: event.CloudEvent.Data.ComputeResource.Name, Valid: event.CloudEvent.Data.ComputeResource.Name != ""},
|
||||
UserName: sql.NullString{String: event.CloudEvent.Data.UserName, Valid: event.CloudEvent.Data.UserName != ""},
|
||||
Source: event.CloudEvent.Source,
|
||||
CloudId: event.CloudEvent.ID,
|
||||
EventTime: sql.NullInt64{Int64: unixTimestamp, Valid: unixTimestamp > 0},
|
||||
ChainId: strconv.Itoa(e.ChainID),
|
||||
VmId: sql.NullString{String: e.VM.VM.Value, Valid: e.VM.VM.Value != ""},
|
||||
VmName: sql.NullString{String: e.VM.Name, Valid: e.VM.Name != ""},
|
||||
EventKey: sql.NullString{String: strconv.Itoa(e.Key), Valid: strconv.Itoa(e.Key) != ""},
|
||||
DatacenterName: sql.NullString{String: e.Datacenter.Name, Valid: e.Datacenter.Name != ""},
|
||||
DatacenterId: sql.NullString{String: e.Datacenter.Datacenter.Value, Valid: e.Datacenter.Datacenter.Value != ""},
|
||||
ComputeResourceName: sql.NullString{String: e.ComputeResource.Name, Valid: e.ComputeResource.Name != ""},
|
||||
ComputeResourceId: sql.NullString{String: e.ComputeResource.ComputeResource.Value, Valid: e.ComputeResource.ComputeResource.Value != ""},
|
||||
UserName: sql.NullString{String: e.UserName, Valid: e.UserName != ""},
|
||||
}
|
||||
|
||||
h.Logger.Debug("database params", "params", params2)
|
||||
@@ -140,6 +146,7 @@ func (h *Handler) VmCreate(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Create Request : %v\n", result)
|
||||
}
|
||||
|
||||
// prettyPrint comes from https://gist.github.com/sfate/9d45f6c5405dc4c9bf63bf95fe6d1a7c
|
||||
func prettyPrint(args ...interface{}) {
|
||||
var caller string
|
||||
|
||||
|
@@ -8,19 +8,23 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/go-co-op/gocron/v2"
|
||||
)
|
||||
|
||||
// Server represents an HTTP server.
|
||||
type Server struct {
|
||||
srv *http.Server
|
||||
logger *slog.Logger
|
||||
cron gocron.Scheduler
|
||||
cancel context.CancelFunc
|
||||
disableTls bool
|
||||
tlsCertFilename string
|
||||
tlsKeyFilename string
|
||||
}
|
||||
|
||||
// New creates a new server with the given logger, address and options.
|
||||
func New(logger *slog.Logger, addr string, opts ...Option) *Server {
|
||||
func New(logger *slog.Logger, cron gocron.Scheduler, cancel context.CancelFunc, addr string, opts ...Option) *Server {
|
||||
|
||||
// Set some options for TLS
|
||||
tlsConfig := &tls.Config{
|
||||
@@ -50,6 +54,8 @@ func New(logger *slog.Logger, addr string, opts ...Option) *Server {
|
||||
return &Server{
|
||||
srv: srv,
|
||||
logger: logger,
|
||||
cron: cron,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +119,6 @@ func (s *Server) Start() {
|
||||
s.logger.Warn("failed to start server", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -133,6 +138,16 @@ func (s *Server) GracefulShutdown() {
|
||||
// Doesn't block if no connections, but will otherwise wait
|
||||
// until the timeout deadline.
|
||||
_ = s.srv.Shutdown(ctx)
|
||||
|
||||
s.logger.Info("runing cron shutdown")
|
||||
err := s.cron.Shutdown()
|
||||
if err != nil {
|
||||
s.logger.Error("error shutting cron", "error", err)
|
||||
}
|
||||
|
||||
s.logger.Info("runing cancel")
|
||||
s.cancel()
|
||||
|
||||
// Optionally, you could run srv.Shutdown in a goroutine and block on
|
||||
// <-ctx.Done() if your application should wait for other services
|
||||
// to finalize based on context cancellation.
|
||||
|
Reference in New Issue
Block a user