From c691763430ee0b6a27442542fbc5577c5f1062fa Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Fri, 27 Sep 2024 11:07:51 +1000 Subject: [PATCH] update database schema to avoid bool confusion --- .../20240927002029_change_inventory.sql | 56 ++++++++++++ db/queries/models.go | 6 +- db/queries/query.sql | 6 +- db/queries/query.sql.go | 90 ++++++++++++++----- internal/report/create.go | 2 +- internal/tasks/processEvents.go | 39 ++++---- main.go | 46 ++++++---- server/server.go | 41 ++++++--- 8 files changed, 214 insertions(+), 72 deletions(-) create mode 100644 db/migrations/20240927002029_change_inventory.sql diff --git a/db/migrations/20240927002029_change_inventory.sql b/db/migrations/20240927002029_change_inventory.sql new file mode 100644 index 0000000..4638649 --- /dev/null +++ b/db/migrations/20240927002029_change_inventory.sql @@ -0,0 +1,56 @@ +-- +goose Up +-- +goose StatementBegin +ALTER TABLE "Inventory" RENAME COLUMN IsTemplate TO IsTemplate_old; +ALTER TABLE "Inventory" RENAME COLUMN PowerState TO PowerState_old; +ALTER TABLE "Inventory" RENAME COLUMN SrmPlaceholder TO SrmPlaceholder_old; +ALTER TABLE "Inventory" ADD COLUMN IsTemplate TEXT NOT NULL DEFAULT "FALSE"; +ALTER TABLE "Inventory" ADD COLUMN PoweredOn TEXT NOT NULL DEFAULT "FALSE"; +ALTER TABLE "Inventory" ADD COLUMN SrmPlaceholder TEXT NOT NULL DEFAULT "FALSE"; +UPDATE Inventory +SET IsTemplate = CASE + WHEN IsTemplate_old = 1 THEN 'TRUE' + ELSE 'FALSE' +END; +UPDATE Inventory +SET PoweredOn = CASE + WHEN PowerState_old = 1 THEN 'TRUE' + ELSE 'FALSE' +END; +UPDATE Inventory +SET SrmPlaceholder = CASE + WHEN SrmPlaceholder_old = 1 THEN 'TRUE' + ELSE 'FALSE' +END; +ALTER TABLE "Inventory" DROP COLUMN IsTemplate_old; +ALTER TABLE "Inventory" DROP COLUMN PowerState_old; + +ALTER TABLE "Inventory" DROP COLUMN SrmPlaceholder_old; +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +ALTER TABLE "Inventory" RENAME COLUMN IsTemplate TO IsTemplate_old; +ALTER TABLE "Inventory" RENAME COLUMN PoweredOn TO PoweredOn_old; +ALTER TABLE "Inventory" RENAME COLUMN SrmPlaceholder TO SrmPlaceholder_old; +ALTER TABLE "Inventory" ADD COLUMN IsTemplate INTEGER; +ALTER TABLE "Inventory" ADD COLUMN PowerState INTEGER; +ALTER TABLE "Inventory" ADD COLUMN SrmPlaceholder INTEGER; +UPDATE Inventory +SET IsTemplate = CASE + WHEN IsTemplate_old = 'TRUE' THEN 1 + ELSE 0 +END; +UPDATE Inventory +SET PowerState = CASE + WHEN PoweredOn_old = 'TRUE' THEN 1 + ELSE 0 +END; +UPDATE Inventory +SET SrmPlaceholder = CASE + WHEN SrmPlaceholder_old = 'TRUE' THEN 1 + ELSE 0 +END; +ALTER TABLE "Inventory" DROP COLUMN IsTemplate_old; +ALTER TABLE "Inventory" DROP COLUMN PoweredOn_old; +ALTER TABLE "Inventory" DROP COLUMN SrmPlaceholder_old; +-- +goose StatementEnd diff --git a/db/queries/models.go b/db/queries/models.go index fd2913c..0cfcf3d 100644 --- a/db/queries/models.go +++ b/db/queries/models.go @@ -43,9 +43,9 @@ type Inventory struct { ProvisionedDisk sql.NullFloat64 InitialVcpus sql.NullInt64 InitialRam sql.NullInt64 - SrmPlaceholder sql.NullInt64 - IsTemplate sql.NullInt64 - PowerState sql.NullInt64 + IsTemplate interface{} + PoweredOn interface{} + SrmPlaceholder interface{} } type Updates struct { diff --git a/db/queries/query.sql b/db/queries/query.sql index 1b77d8c..89837ff 100644 --- a/db/queries/query.sql +++ b/db/queries/query.sql @@ -2,6 +2,10 @@ SELECT * FROM "Inventory" ORDER BY "Name"; +-- name: GetReportInventory :many +SELECT * FROM "Inventory" +ORDER BY "CreationTime"; + -- name: GetInventoryByName :many SELECT * FROM "Inventory" WHERE "Name" = ?; @@ -16,7 +20,7 @@ WHERE "CloudId" = ? LIMIT 1; -- name: CreateInventory :one INSERT INTO "Inventory" ( - "Name", "Vcenter", "VmId", "EventKey", "CloudId", "CreationTime", "ResourcePool", "VmType", "IsTemplate", "Datacenter", "Cluster", "Folder", "ProvisionedDisk", "InitialVcpus", "InitialRam", "SrmPlaceholder", "PowerState" + "Name", "Vcenter", "VmId", "EventKey", "CloudId", "CreationTime", "ResourcePool", "VmType", "IsTemplate", "Datacenter", "Cluster", "Folder", "ProvisionedDisk", "InitialVcpus", "InitialRam", "SrmPlaceholder", "PoweredOn" ) VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) diff --git a/db/queries/query.sql.go b/db/queries/query.sql.go index 9eb1b98..e2f7151 100644 --- a/db/queries/query.sql.go +++ b/db/queries/query.sql.go @@ -90,11 +90,11 @@ func (q *Queries) CreateEvent(ctx context.Context, arg CreateEventParams) (Event const createInventory = `-- name: CreateInventory :one INSERT INTO "Inventory" ( - "Name", "Vcenter", "VmId", "EventKey", "CloudId", "CreationTime", "ResourcePool", "VmType", "IsTemplate", "Datacenter", "Cluster", "Folder", "ProvisionedDisk", "InitialVcpus", "InitialRam", "SrmPlaceholder", "PowerState" + "Name", "Vcenter", "VmId", "EventKey", "CloudId", "CreationTime", "ResourcePool", "VmType", "IsTemplate", "Datacenter", "Cluster", "Folder", "ProvisionedDisk", "InitialVcpus", "InitialRam", "SrmPlaceholder", "PoweredOn" ) VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) -RETURNING Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, SrmPlaceholder, IsTemplate, PowerState +RETURNING Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, IsTemplate, PoweredOn, SrmPlaceholder ` type CreateInventoryParams struct { @@ -106,15 +106,15 @@ type CreateInventoryParams struct { CreationTime sql.NullInt64 ResourcePool sql.NullString VmType sql.NullString - IsTemplate sql.NullInt64 + IsTemplate interface{} Datacenter sql.NullString Cluster sql.NullString Folder sql.NullString ProvisionedDisk sql.NullFloat64 InitialVcpus sql.NullInt64 InitialRam sql.NullInt64 - SrmPlaceholder sql.NullInt64 - PowerState sql.NullInt64 + SrmPlaceholder interface{} + PoweredOn interface{} } func (q *Queries) CreateInventory(ctx context.Context, arg CreateInventoryParams) (Inventory, error) { @@ -135,7 +135,7 @@ func (q *Queries) CreateInventory(ctx context.Context, arg CreateInventoryParams arg.InitialVcpus, arg.InitialRam, arg.SrmPlaceholder, - arg.PowerState, + arg.PoweredOn, ) var i Inventory err := row.Scan( @@ -155,9 +155,9 @@ func (q *Queries) CreateInventory(ctx context.Context, arg CreateInventoryParams &i.ProvisionedDisk, &i.InitialVcpus, &i.InitialRam, - &i.SrmPlaceholder, &i.IsTemplate, - &i.PowerState, + &i.PoweredOn, + &i.SrmPlaceholder, ) return i, err } @@ -215,7 +215,7 @@ func (q *Queries) CreateUpdate(ctx context.Context, arg CreateUpdateParams) (Upd } const getInventoryByName = `-- name: GetInventoryByName :many -SELECT Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, SrmPlaceholder, IsTemplate, PowerState FROM "Inventory" +SELECT Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, IsTemplate, PoweredOn, SrmPlaceholder FROM "Inventory" WHERE "Name" = ? ` @@ -245,9 +245,9 @@ func (q *Queries) GetInventoryByName(ctx context.Context, name string) ([]Invent &i.ProvisionedDisk, &i.InitialVcpus, &i.InitialRam, - &i.SrmPlaceholder, &i.IsTemplate, - &i.PowerState, + &i.PoweredOn, + &i.SrmPlaceholder, ); err != nil { return nil, err } @@ -263,7 +263,7 @@ func (q *Queries) GetInventoryByName(ctx context.Context, name string) ([]Invent } const getInventoryEventId = `-- name: GetInventoryEventId :one -SELECT Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, SrmPlaceholder, IsTemplate, PowerState FROM "Inventory" +SELECT Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, IsTemplate, PoweredOn, SrmPlaceholder FROM "Inventory" WHERE "CloudId" = ? LIMIT 1 ` @@ -287,15 +287,15 @@ func (q *Queries) GetInventoryEventId(ctx context.Context, cloudid sql.NullStrin &i.ProvisionedDisk, &i.InitialVcpus, &i.InitialRam, - &i.SrmPlaceholder, &i.IsTemplate, - &i.PowerState, + &i.PoweredOn, + &i.SrmPlaceholder, ) return i, err } const getInventoryVmId = `-- name: GetInventoryVmId :one -SELECT Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, SrmPlaceholder, IsTemplate, PowerState FROM "Inventory" +SELECT Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, IsTemplate, PoweredOn, SrmPlaceholder FROM "Inventory" WHERE "VmId" = ?1 AND "Datacenter" = ?2 ` @@ -324,17 +324,65 @@ func (q *Queries) GetInventoryVmId(ctx context.Context, arg GetInventoryVmIdPara &i.ProvisionedDisk, &i.InitialVcpus, &i.InitialRam, - &i.SrmPlaceholder, &i.IsTemplate, - &i.PowerState, + &i.PoweredOn, + &i.SrmPlaceholder, ) return i, err } +const getReportInventory = `-- name: GetReportInventory :many +SELECT Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, IsTemplate, PoweredOn, SrmPlaceholder FROM "Inventory" +ORDER BY "CreationTime" +` + +func (q *Queries) GetReportInventory(ctx context.Context) ([]Inventory, error) { + rows, err := q.db.QueryContext(ctx, getReportInventory) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Inventory + for rows.Next() { + var i Inventory + if err := rows.Scan( + &i.Iid, + &i.Name, + &i.Vcenter, + &i.VmId, + &i.EventKey, + &i.CloudId, + &i.CreationTime, + &i.DeletionTime, + &i.ResourcePool, + &i.VmType, + &i.Datacenter, + &i.Cluster, + &i.Folder, + &i.ProvisionedDisk, + &i.InitialVcpus, + &i.InitialRam, + &i.IsTemplate, + &i.PoweredOn, + &i.SrmPlaceholder, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const inventoryCleanup = `-- name: InventoryCleanup :exec DELETE FROM "Inventory" WHERE "VmId" = ?1 AND "Datacenter" = ?2 -RETURNING Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, SrmPlaceholder, IsTemplate, PowerState +RETURNING Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, IsTemplate, PoweredOn, SrmPlaceholder ` type InventoryCleanupParams struct { @@ -409,7 +457,7 @@ func (q *Queries) ListEvents(ctx context.Context) ([]Events, error) { } const listInventory = `-- name: ListInventory :many -SELECT Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, SrmPlaceholder, IsTemplate, PowerState FROM "Inventory" +SELECT Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, IsTemplate, PoweredOn, SrmPlaceholder FROM "Inventory" ORDER BY "Name" ` @@ -439,9 +487,9 @@ func (q *Queries) ListInventory(ctx context.Context) ([]Inventory, error) { &i.ProvisionedDisk, &i.InitialVcpus, &i.InitialRam, - &i.SrmPlaceholder, &i.IsTemplate, - &i.PowerState, + &i.PoweredOn, + &i.SrmPlaceholder, ); err != nil { return nil, err } diff --git a/internal/report/create.go b/internal/report/create.go index f502580..ed13500 100644 --- a/internal/report/create.go +++ b/internal/report/create.go @@ -20,7 +20,7 @@ func CreateReport(logger *slog.Logger, Database db.Database, ctx context.Context var buffer bytes.Buffer logger.Debug("Querying inventory table") - results, err := Database.Queries().ListInventory(ctx) + results, err := Database.Queries().GetReportInventory(ctx) if err != nil { logger.Error("Unable to query inventory table", "error", err) return nil, err diff --git a/internal/tasks/processEvents.go b/internal/tasks/processEvents.go index f27355b..f46b68a 100644 --- a/internal/tasks/processEvents.go +++ b/internal/tasks/processEvents.go @@ -26,10 +26,10 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error { numVcpus int32 numRam int32 totalDiskGB float64 - srmPlaceholder int + srmPlaceholder string foundVm bool - isTemplate int - poweredOn int + isTemplate string + poweredOn string folderPath string ) @@ -64,11 +64,11 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error { numRam = 0 numVcpus = 0 totalDiskGB = 0 - isTemplate = 0 + isTemplate = "FALSE" folderPath = "" } else { c.Logger.Debug("found VM") - srmPlaceholder = 0 // Default assumption + srmPlaceholder = "FALSE" // Default assumption //prettyPrint(vmObject) // calculate VM properties we want to store @@ -79,6 +79,14 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error { // Calculate the total disk allocated in GB for _, device := range vmObject.Vm.Config.Hardware.Device { if disk, ok := device.(*types.VirtualDisk); ok { + + // Print the filename of the backing device + if backing, ok := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok { + c.Logger.Debug("Adding disk", "size_bytes", disk.CapacityInBytes, "backing_file", backing.FileName) + } else { + c.Logger.Debug("Adding disk, unknown backing type", "size_bytes", disk.CapacityInBytes) + } + totalDiskGB += float64(disk.CapacityInBytes / 1024 / 1024 / 1024) // Convert from bytes to GB } } @@ -86,13 +94,13 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error { // Determine if the VM is a normal VM or an SRM placeholder if vmObject.Vm.Config.ManagedBy != nil && vmObject.Vm.Config.ManagedBy.Type == "com.vmware.vcDr" { c.Logger.Debug("VM ManagedBy indicates managed by SRM") - srmPlaceholder = 1 + srmPlaceholder = "TRUE" } if vmObject.Vm.Config.Template { - isTemplate = 1 + isTemplate = "TRUE" } else { - isTemplate = 0 + isTemplate = "FALSE" } // Retrieve the full folder path of the VM @@ -109,15 +117,12 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error { c.Logger.Error("Empty VM config") } - //if (types.VirtualMachineRuntimeInfo{}) != vmObject.Vm.Runtime { - //if runtime, ok := vmObject.Vm.Runtime.(types.VirtualMachineRuntimeInfo); ok { c.Logger.Debug("VM has runtime data", "power_state", vmObject.Vm.Runtime.PowerState) - if vmObject.Vm.Runtime.PowerState == "" { - poweredOn = 0 + if vmObject.Vm.Runtime.PowerState == "poweredOff" { + poweredOn = "FALSE" } else { - poweredOn = 1 + poweredOn = "TRUE" } - //} } err = vc.Logout() @@ -142,9 +147,9 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error { ProvisionedDisk: sql.NullFloat64{Float64: totalDiskGB, Valid: totalDiskGB > 0}, Folder: sql.NullString{String: folderPath, Valid: folderPath != ""}, ResourcePool: sql.NullString{String: vmObject.ResourcePool, Valid: vmObject.ResourcePool != ""}, - SrmPlaceholder: sql.NullInt64{Int64: int64(srmPlaceholder), Valid: true}, - IsTemplate: sql.NullInt64{Int64: int64(isTemplate), Valid: true}, - PowerState: sql.NullInt64{Int64: int64(poweredOn), Valid: true}, + SrmPlaceholder: srmPlaceholder, + IsTemplate: isTemplate, + PoweredOn: poweredOn, } c.Logger.Debug("database params", "params", params) diff --git a/main.go b/main.go index 1d7cdbf..d5b7ed8 100644 --- a/main.go +++ b/main.go @@ -21,10 +21,11 @@ import ( ) var ( - bindDisableTls bool - sha1ver string // sha1 revision used to build the program - buildTime string // when the executable was built - cronFrequency time.Duration + bindDisableTls bool + sha1ver string // sha1 revision used to build the program + buildTime string // when the executable was built + cronFrequency time.Duration + cronInvFrequency time.Duration ) func main() { @@ -125,17 +126,29 @@ func main() { Settings: s, } - cronFrequencyString := os.Getenv("VCENTER_POLLING_SECONDS") + cronFrequencyString := os.Getenv("VCENTER_EVENT_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) + slog.Error("Can't convert VCENTER_EVENT_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) + logger.Debug("Setting VM event polling cronjob frequency to", "frequency", cronFrequency) + + cronInventoryFrequencyString := os.Getenv("VCENTER_INVENTORY_POLLING_SECONDS") + if cronInventoryFrequencyString != "" { + cronInvFrequency, err = time.ParseDuration(cronInventoryFrequencyString) + if err != nil { + slog.Error("Can't convert VCENTER_INVENTORY_POLLING_SECONDS value to time duration. Defaulting to 3600s", "value", cronInventoryFrequencyString, "error", err) + cronInvFrequency = time.Second * 3600 + } + } else { + cronInvFrequency = time.Second * 3600 + } + logger.Debug("Setting VM inventory polling cronjob frequency to", "frequency", cronInvFrequency) // start background processing for events stored in events table startsAt := time.Now().Add(time.Second * 10) @@ -147,24 +160,25 @@ func main() { gocron.WithStartAt(gocron.WithStartDateTime(startsAt)), ) if err != nil { - logger.Error("failed to start cron jobs", "error", err) + logger.Error("failed to start event processing cron job", "error", err) os.Exit(1) } logger.Debug("Created event processing cron job", "job", job.ID()) - startsAt2 := time.Now().Add(time.Second * 10) + // start background checks of vcenter inventory + startsAt2 := time.Now().Add(time.Second * 300) job2, err := c.NewJob( - gocron.DurationJob(cronFrequency), + gocron.DurationJob(cronInvFrequency), gocron.NewTask(func() { ct.RunVcenterPoll(ctx, logger) }), gocron.WithSingletonMode(gocron.LimitModeReschedule), gocron.WithStartAt(gocron.WithStartDateTime(startsAt2)), ) if err != nil { - logger.Error("failed to start cron jobs", "error", err) + logger.Error("failed to start vcenter inventory cron job", "error", err) os.Exit(1) } - logger.Debug("Created vcenter polling cron job", "job", job2.ID()) + logger.Debug("Created vcenter inventory cron job", "job", job2.ID()) // start cron scheduler c.Start() @@ -176,11 +190,11 @@ func main() { cancel, bindAddress, server.WithRouter(router.New(logger, database, buildTime, sha1ver, runtime.Version())), + server.SetTls(bindDisableTls), + server.SetCertificate(tlsCertFilename), + server.SetPrivateKey(tlsKeyFilename), ) - - svr.DisableTls(bindDisableTls) - svr.SetCertificate(tlsCertFilename) - svr.SetPrivateKey(tlsKeyFilename) + //logger.Debug("Server configured", "object", svr) svr.StartAndWait() diff --git a/server/server.go b/server/server.go index c92a5e6..69742ac 100644 --- a/server/server.go +++ b/server/server.go @@ -3,6 +3,7 @@ package server import ( "context" "crypto/tls" + "fmt" "log/slog" "net/http" "os" @@ -47,16 +48,21 @@ func New(logger *slog.Logger, cron gocron.Scheduler, cancel context.CancelFunc, TLSConfig: tlsConfig, TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)), } - for _, opt := range opts { - opt(&Server{srv: srv}) - } - return &Server{ + // Set the initial server values + server := &Server{ srv: srv, logger: logger, cron: cron, cancel: cancel, } + + // Apply any options + for _, opt := range opts { + opt(server) + } + + return server } // Option represents a server option. @@ -83,19 +89,26 @@ func WithRouter(handler http.Handler) Option { } } -// DisableTls sets the disable tls value -func (s *Server) DisableTls(disableTls bool) { - s.disableTls = disableTls +// SetTls sets the disable tls value +func SetTls(disableTls bool) Option { + return func(s *Server) { + s.disableTls = disableTls + } } // SetCertificate sets the path to the certificate used for TLS, in PEM format -func (s *Server) SetCertificate(tlsCertFilename string) { - s.tlsCertFilename = tlsCertFilename +func SetCertificate(tlsCertFilename string) Option { + return func(s *Server) { + fmt.Printf("Setting tlsCertFilename to '%s'\n", tlsCertFilename) + s.tlsCertFilename = tlsCertFilename + } } // SetPrivateKey sets the path to the private key used for TLS, in PEM format -func (s *Server) SetPrivateKey(tlsKeyFilename string) { - s.tlsKeyFilename = tlsKeyFilename +func SetPrivateKey(tlsKeyFilename string) Option { + return func(s *Server) { + s.tlsKeyFilename = tlsKeyFilename + } } // StartAndWait starts the server and waits for a signal to shut down. @@ -111,12 +124,14 @@ func (s *Server) Start() { if s.disableTls { s.logger.Info("starting server", "port", s.srv.Addr) if err := s.srv.ListenAndServe(); err != nil { - s.logger.Warn("failed to start server", "error", err) + s.logger.Error("failed to start server", "error", err) + os.Exit(1) } } else { s.logger.Info("starting TLS server", "port", s.srv.Addr, "cert", s.tlsCertFilename, "key", s.tlsKeyFilename) if err := s.srv.ListenAndServeTLS(s.tlsCertFilename, s.tlsKeyFilename); err != nil && err != http.ErrServerClosed { - s.logger.Warn("failed to start server", "error", err) + s.logger.Error("failed to start server", "error", err) + os.Exit(1) } } }()