Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ This project uses [pre-commit](https://pre-commit.io/) for code quality checks.
- **[Database](docs/database.md)** - Schema, migrations, and data model
- **[Deployment](docs/deployment.md)** - Container images, Kubernetes deployment, and configuration
- **[Authentication](docs/authentication.md)** - Development and production auth
- **[Logging](docs/logging.md)** - Structured logging, OpenTelemetry integration, and data masking

### Additional Resources

Expand Down
40 changes: 26 additions & 14 deletions cmd/hyperfleet-api/environments/framework.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package environments

import (
"context"
"os"
"strings"

"github.com/golang/glog"
"github.com/spf13/pflag"

"github.com/openshift-hyperfleet/hyperfleet-api/cmd/hyperfleet-api/environments/registry"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/client/ocm"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/config"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/errors"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/logger"
)

func init() {
Expand Down Expand Up @@ -64,38 +65,45 @@ func (e *Env) AddFlags(flags *pflag.FlagSet) error {
// This should be called after the e.Config has been set appropriately though AddFlags and pasing, done elsewhere
// The environment does NOT handle flag parsing
func (e *Env) Initialize() error {
glog.Infof("Initializing %s environment", e.Name)
ctx := context.Background()
logger.Infof(ctx, "Initializing %s environment", e.Name)

envImpl, found := environments[e.Name]
if !found {
glog.Fatalf("Unknown runtime environment: %s", e.Name)
logger.Errorf(ctx, "Unknown runtime environment: %s", e.Name)
os.Exit(1)
}

if err := envImpl.OverrideConfig(e.Config); err != nil {
glog.Fatalf("Failed to configure ApplicationConfig: %s", err)
logger.Errorf(ctx, "Failed to configure ApplicationConfig: %s", err)
os.Exit(1)
}

messages := environment.Config.ReadFiles()
if len(messages) != 0 {
glog.Fatalf("unable to read configuration files:\n%s", strings.Join(messages, "\n"))
logger.Errorf(ctx, "unable to read configuration files:\n%s", strings.Join(messages, "\n"))
os.Exit(1)
}

// each env will set db explicitly because the DB impl has a `once` init section
if err := envImpl.OverrideDatabase(&e.Database); err != nil {
glog.Fatalf("Failed to configure Database: %s", err)
logger.Errorf(ctx, "Failed to configure Database: %s", err)
os.Exit(1)
}

err := e.LoadClients()
if err != nil {
return err
}
if err := envImpl.OverrideClients(&e.Clients); err != nil {
glog.Fatalf("Failed to configure Clients: %s", err)
logger.Errorf(ctx, "Failed to configure Clients: %s", err)
os.Exit(1)
}

e.LoadServices()
if err := envImpl.OverrideServices(&e.Services); err != nil {
glog.Fatalf("Failed to configure Services: %s", err)
logger.Errorf(ctx, "Failed to configure Services: %s", err)
os.Exit(1)
}

seedErr := e.Seed()
Expand All @@ -104,7 +112,8 @@ func (e *Env) Initialize() error {
}

if err := envImpl.OverrideHandlers(&e.Handlers); err != nil {
glog.Fatalf("Failed to configure Handlers: %s", err)
logger.Errorf(ctx, "Failed to configure Handlers: %s", err)
os.Exit(1)
}

return nil
Expand All @@ -123,6 +132,7 @@ func (e *Env) LoadServices() {
}

func (e *Env) LoadClients() error {
ctx := context.Background()
var err error

ocmConfig := ocm.Config{
Expand All @@ -136,36 +146,38 @@ func (e *Env) LoadClients() error {

// Create OCM Authz client
if e.Config.OCM.EnableMock {
glog.Infof("Using Mock OCM Authz Client")
logger.Info(ctx, "Using Mock OCM Authz Client")
e.Clients.OCM, err = ocm.NewClientMock(ocmConfig)
} else {
e.Clients.OCM, err = ocm.NewClient(ocmConfig)
}
if err != nil {
glog.Errorf("Unable to create OCM Authz client: %s", err.Error())
logger.Errorf(ctx, "Unable to create OCM Authz client: %s", err)
return err
}

return nil
}

func (e *Env) Teardown() {
ctx := context.Background()
if e.Database.SessionFactory != nil {
if err := e.Database.SessionFactory.Close(); err != nil {
glog.Errorf("Error closing database session factory: %s", err.Error())
logger.Errorf(ctx, "Error closing database session factory: %s", err)
}
}
if e.Clients.OCM != nil {
if err := e.Clients.OCM.Close(); err != nil {
glog.Errorf("Error closing OCM client: %v", err)
logger.Errorf(ctx, "Error closing OCM client: %v", err)
}
}
}

func setConfigDefaults(flags *pflag.FlagSet, defaults map[string]string) error {
ctx := context.Background()
for name, value := range defaults {
if err := flags.Set(name, value); err != nil {
glog.Errorf("Error setting flag %s: %v", name, err)
logger.Error(ctx, "Error setting flag", "flag", name, "error", err)
return err
}
}
Expand Down
48 changes: 35 additions & 13 deletions cmd/hyperfleet-api/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package main

import (
"context"
"flag"
"log/slog"
"os"

"github.com/golang/glog"
"github.com/spf13/cobra"

"github.com/openshift-hyperfleet/hyperfleet-api/cmd/hyperfleet-api/migrate"
"github.com/openshift-hyperfleet/hyperfleet-api/cmd/hyperfleet-api/servecmd"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/logger"

// Import plugins to trigger their init() functions
// _ "github.com/openshift-hyperfleet/hyperfleet-api/plugins/events" // REMOVED: Events plugin no longer exists
Expand All @@ -20,18 +23,14 @@ import (
// nolint

func main() {
// This is needed to make `glog` believe that the flags have already been parsed, otherwise
// every log messages is prefixed by an error message stating the the flags haven't been
// parsed.
if err := flag.CommandLine.Parse([]string{}); err != nil {
glog.Fatalf("Failed to parse flags: %v", err)
}

//pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
// Initialize logger first (before any logging occurs)
initDefaultLogger()
ctx := context.Background()

// Always log to stderr by default
if err := flag.Set("logtostderr", "true"); err != nil {
glog.Infof("Unable to set logtostderr to true")
// Parse flags (needed for cobra compatibility)
if err := flag.CommandLine.Parse([]string{}); err != nil {
logger.Error(ctx, "Failed to parse flags", "error", err)
os.Exit(1)
}

rootCmd := &cobra.Command{
Expand All @@ -47,6 +46,29 @@ func main() {
rootCmd.AddCommand(migrateCmd, serveCmd)

if err := rootCmd.Execute(); err != nil {
glog.Fatalf("error running command: %v", err)
logger.Error(ctx, "Error running command", "error", err)
os.Exit(1)
}
}

// initDefaultLogger initializes a default logger with INFO level
// This ensures logging works before environment/config is loaded
func initDefaultLogger() {
cfg := &logger.LogConfig{
Level: slog.LevelInfo,
Format: logger.FormatJSON,
Output: os.Stdout,
Component: "hyperfleet-api",
Version: "unknown",
Hostname: getHostname(),
}
logger.InitGlobalLogger(cfg)
}

func getHostname() string {
hostname, err := os.Hostname()
if err != nil {
return "unknown"
}
return hostname
}
26 changes: 21 additions & 5 deletions cmd/hyperfleet-api/migrate/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package migrate
import (
"context"
"flag"
"os"

"github.com/golang/glog"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/db/db_session"
"github.com/spf13/cobra"

"github.com/openshift-hyperfleet/hyperfleet-api/pkg/config"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/db"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/db/db_session"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/logger"
)

var dbConfig = config.NewDatabaseConfig()
Expand All @@ -29,13 +30,28 @@ func NewMigrateCommand() *cobra.Command {
}

func runMigrate(_ *cobra.Command, _ []string) {
ctx := context.Background()
err := dbConfig.ReadFiles()
if err != nil {
glog.Fatal(err)
logger.Error(ctx, "Fatal error", "error", err)
os.Exit(1)
}

connection := db_session.NewProdFactory(dbConfig)
if err := db.Migrate(connection.New(context.Background())); err != nil {
glog.Fatal(err)
defer func() {
if closeErr := connection.Close(); closeErr != nil {
logger.Error(ctx, "Failed to close database connection", "error", closeErr)
}
}()

if err := db.Migrate(connection.New(ctx)); err != nil {
logger.Error(ctx, "Migration failed", "error", err)
// Close connection before exit to avoid resource leak
if closeErr := connection.Close(); closeErr != nil {
logger.Error(ctx, "Failed to close database connection", "error", closeErr)
}
os.Exit(1)
}

logger.Info(ctx, "Migration completed successfully")
}
Loading