nuts-foundation/nuts-go

View on GitHub
cmd/root.go

Summary

Maintainability
A
0 mins
Test Coverage
/*
 * Nuts go
 * Copyright (C) 2019 Nuts community
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package cmd

import (
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
    bridge "github.com/nuts-foundation/consent-bridge-go-client/engine"
    auth "github.com/nuts-foundation/nuts-auth/engine"
    logic "github.com/nuts-foundation/nuts-consent-logic/engine"
    consent "github.com/nuts-foundation/nuts-consent-store/engine"
    crypto "github.com/nuts-foundation/nuts-crypto/engine"
    octopus "github.com/nuts-foundation/nuts-event-octopus/engine"
    network "github.com/nuts-foundation/nuts-network/engine"
    validation "github.com/nuts-foundation/nuts-fhir-validation/engine"
    core "github.com/nuts-foundation/nuts-go-core"
    registry "github.com/nuts-foundation/nuts-registry/engine"
    "github.com/sirupsen/logrus"
    "github.com/spf13/cobra"
)

func createRootCommand() *cobra.Command {
    return &cobra.Command{
        Use:   "nuts",
        Short: "The Nuts service executable",
        Run: func(cmd *cobra.Command, args []string) {
            cfg := core.NutsConfig()
            if cfg.Mode() != core.GlobalServerMode {
                logrus.Error("Please specify a sub command when running in CLI mode")
                _ = cmd.Help()
                return
            }
            // start interfaces
            echo := echo.New()
            echo.HideBanner = true
            echo.Use(middleware.Logger())

            for _, engine := range core.EngineCtl.Engines {
                if engine.Routes != nil {
                    engine.Routes(echo)
                }
            }

            defer shutdownEngines()
            logrus.Fatal(echo.Start(cfg.ServerAddress()))
        },
    }
}

func CreateCommand() *cobra.Command {
    if core.EngineCtl.Engines == nil {
        registerEngines()
    }
    command := createRootCommand()
    addSubCommands(command)
    addFlagSets(command, core.NutsConfig())
    return command
}

func Execute() {
    command := CreateCommand()

    // Load global Nuts config
    cfg := core.NutsConfig()

    // Load all config and add generic options
    if err := cfg.Load(command); err != nil {
        panic(err)
    }

    // Load config into engines
    injectConfig(cfg)
    cfg.PrintConfig(logrus.StandardLogger())

    // check config on all engines
    configureEngines()

    // start engines
    startEngines()

    // blocking main call
    command.Execute()
}

func addSubCommands(root *cobra.Command) {
    for _, e := range core.EngineCtl.Engines {
        if e.Cmd != nil {
            root.AddCommand(e.Cmd)
        }
    }
}

func registerEngines() {
    core.RegisterEngine(core.NewStatusEngine())
    core.RegisterEngine(core.NewLoggerEngine())
    core.RegisterEngine(core.NewMetricsEngine())
    core.RegisterEngine(crypto.NewCryptoEngine())
    core.RegisterEngine(network.NewNetworkEngine())
    core.RegisterEngine(registry.NewRegistryEngine())
    core.RegisterEngine(octopus.NewEventOctopusEngine())

    core.RegisterEngine(logic.NewConsentLogicEngine())
    core.RegisterEngine(consent.NewConsentStoreEngine())
    core.RegisterEngine(validation.NewValidationEngine())
    core.RegisterEngine(auth.NewAuthEngine())
    core.RegisterEngine(bridge.NewConsentBridgeClientEngine())
}

func injectConfig(cfg *core.NutsGlobalConfig) {
    // loop through configs and call viper.Get prepended with engine ConfigKey, inject value into struct
    for _, e := range core.EngineCtl.Engines {
        if err := cfg.InjectIntoEngine(e); err != nil {
            logrus.Fatal(err)
        }
    }
}

func configureEngines() {
    for _, e := range core.EngineCtl.Engines {
        // only if Engine is dynamically configurable
        if e.Configure != nil {
            if err := e.Configure(); err != nil {
                logrus.Fatal(err)
            }
        }
    }
}

func addFlagSets(cmd *cobra.Command, cfg *core.NutsGlobalConfig) {
    for _, e := range core.EngineCtl.Engines {
        cfg.RegisterFlags(cmd, e)
    }
}

func startEngines() {
    for _, e := range core.EngineCtl.Engines {
        if e.Start != nil {
            if err := e.Start(); err != nil {
                logrus.Fatal(err)
            }
        }
    }
}

func shutdownEngines() {
    for _, e := range core.EngineCtl.Engines {
        if e.Shutdown != nil {
            if err := e.Shutdown(); err != nil {
                logrus.Error(err)
            }
        }
    }
}