Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor setup config #3605

Closed
wants to merge 8 commits into from
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
32 changes: 32 additions & 0 deletions src/jetstream/datastore/20190521212700_ConfigSchema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package datastore

import (
"database/sql"

"bitbucket.org/liamstask/goose/lib/goose"
)

func init() {
RegisterMigration(20190521212700, "ConfigSchema", func(txn *sql.Tx, conf *goose.DBConf) error {
configTable := "CREATE TABLE IF NOT EXISTS config ("
configTable += " groupName VARCHAR(255) NOT NULL, "
configTable += " name VARCHAR(255) NOT NULL, "
configTable += " value VARCHAR(255) NOT NULL,"
configTable += " last_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP);"

_, err := txn.Exec(configTable)
if err != nil {
return err
}

// Add a marker to the new table so that later we know we need to migrate the old data to the new table
addMarker := "INSERT INTO config (groupName, name, value) VALUES ('system', '__CONFIG_MIGRATION_NEEDED', 'true')"

_, err = txn.Exec(addMarker)
if err != nil {
return err
}

return nil
})
}
28 changes: 19 additions & 9 deletions src/jetstream/datastore/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,31 @@ func GetConnection(dc DatabaseConfig, env *env.VarSet) (*sql.DB, error) {

// GetSQLLiteConnection returns an SQLite DB Connection
func GetSQLLiteConnection(sqliteKeepDB bool) (*sql.DB, error) {
return GetSQLLiteConnectionWithPath(SQLiteDatabaseFile, sqliteKeepDB)
}

// GetSQLLiteConnectionWithPath returns an SQLite DB Connection
func GetSQLLiteConnectionWithPath(databaseFile string, sqliteKeepDB bool) (*sql.DB, error) {
if !sqliteKeepDB {
os.Remove(SQLiteDatabaseFile)
os.Remove(databaseFile)
}

db, err := sql.Open("sqlite3", SQLiteDatabaseFile)
db, err := sql.Open("sqlite3", databaseFile)
if err != nil {
return nil, err
}

conf := CreateFakeSQLiteGooseDriver()
err = ApplyMigrations(conf, db)
if err != nil {
return nil, err
}

return db, nil
}

// CreateFakeSQLiteGooseDriver creates a fake Goose Driver for SQLite
func CreateFakeSQLiteGooseDriver() *goose.DBConf {
// Create fake goose db conf object for SQLite
d := goose.DBDriver{
Name: "sqlite3",
Expand All @@ -171,13 +187,7 @@ func GetSQLLiteConnection(sqliteKeepDB bool) (*sql.DB, error) {
conf := &goose.DBConf{
Driver: d,
}

err = ApplyMigrations(conf, db)
if err != nil {
return nil, err
}

return db, nil
return conf
}

func buildConnectionString(dc DatabaseConfig) string {
Expand Down
14 changes: 10 additions & 4 deletions src/jetstream/datastore/datastore_migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,35 @@ type StratosMigration func(txn *sql.Tx, conf *goose.DBConf) error

// RegisterMigration registers a migration step. This should be called from an init() function
func RegisterMigration(version int64, name string, f StratosMigration) {
migrationSteps = append(migrationSteps, stratosMigrationStep{
migrationSteps = append(migrationSteps, StratosMigrationStep{
Version: version,
Name: name,
Apply: f,
})
}

type stratosMigrationStep struct {
// StratosMigrationStep represents a migaration step
type StratosMigrationStep struct {
Version int64
Name string
Apply StratosMigration
}

var migrationSteps []stratosMigrationStep
var migrationSteps []StratosMigrationStep

// GetOrderedMigrations returns an order list of migrations to run
func GetOrderedMigrations() []stratosMigrationStep {
func GetOrderedMigrations() []StratosMigrationStep {
sort.Slice(migrationSteps, func(i, j int) bool {
return migrationSteps[i].Version < migrationSteps[j].Version
})
return migrationSteps
}

// SetMigrations replces the current list of migrations - used only by tests internally
func SetMigrations(steps []StratosMigrationStep) {
migrationSteps = steps
}

// ApplyMigrations will perform the migrations
func ApplyMigrations(conf *goose.DBConf, db *sql.DB) error {
current, err := goose.EnsureDBVersion(conf, db)
Expand Down
92 changes: 46 additions & 46 deletions src/jetstream/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ func getEnvironmentLookup() *env.VarSet {
// Make environment lookup
envLookup := env.NewVarSet()

// Environment variables directly set trump all others
// Config database store topmost priority
envLookup.AppendSource(console_config.ConfigLookup)

// Environment variables
envLookup.AppendSource(os.LookupEnv)

// If running in CloudFoundry, fallback to a user provided service (if set)
Expand Down Expand Up @@ -142,12 +145,15 @@ func main() {

if isUpgrading {
log.Info("Upgrade in progress (lock file detected) ... waiting for lock file to be removed ...")
start(portalConfig, &portalProxy{env: envLookup}, &setupMiddleware{}, true)
start(portalConfig, &portalProxy{env: envLookup}, false, true)
}
// Grab the Console Version from the executable
portalConfig.ConsoleVersion = appVersion
log.Infof("Stratos Version: %s", portalConfig.ConsoleVersion)

// Initialize an empty config for the console - initially not setup
portalConfig.ConsoleConfig = new(interfaces.ConsoleConfig)

// Initialize the HTTP client
initializeHTTPClients(portalConfig.HTTPClientTimeoutInSecs, portalConfig.HTTPClientTimeoutMutatingInSecs, portalConfig.HTTPConnectionTimeoutInSecs)
log.Info("HTTP client initialized.")
Expand Down Expand Up @@ -239,7 +245,7 @@ func main() {
}()

// Initialise configuration
addSetupMiddleware, err := initialiseConsoleConfiguration(portalProxy)
needSetupMiddleware, err := initialiseConsoleConfiguration(portalProxy)
if err != nil {
log.Infof("Failed to initialise console config due to: %s", err)
return
Expand Down Expand Up @@ -271,7 +277,7 @@ func main() {
portalProxy.StoreDiagnostics()

// Start the back-end
if err := start(portalProxy.Config, portalProxy, addSetupMiddleware, false); err != nil {
if err := start(portalProxy.Config, portalProxy, needSetupMiddleware, false); err != nil {
log.Fatalf("Unable to start: %v", err)
}
log.Info("Unable to start Stratos JetStream backend")
Expand All @@ -289,62 +295,57 @@ func (portalProxy *portalProxy) GetPlugin(name string) interface{} {
return plugin
}

func initialiseConsoleConfiguration(portalProxy *portalProxy) (*setupMiddleware, error) {
func initialiseConsoleConfiguration(portalProxy *portalProxy) (bool, error) {

addSetupMiddleware := new(setupMiddleware)
addSetupMiddleware := false
consoleRepo, err := console_config.NewPostgresConsoleConfigRepository(portalProxy.DatabaseConnectionPool)
if err != nil {
log.Errorf("Unable to intialise Stratos backend config due to: %+v", err)
log.Errorf("Unable to initialize Stratos backend config due to: %+v", err)
return addSetupMiddleware, err
}
isInitialised, err := consoleRepo.IsInitialised()

if err != nil || !isInitialised {
// Exception occurred when trying to determine
// if its initialised or instance isn't initialised,
// will attempt to initialise it from the env vars.

consoleConfig, err := portalProxy.initialiseConsoleConfig(consoleRepo)
if err != nil {
log.Warnf("Failed to initialise Stratos config due to: %+v", err)
// Do this BEFORE we load the config from the database, so env var lookup at this stage
// looks at environment variables etc but NOT the database
// Migrate data from old setup table to new config table (if needed)
err = console_config.MigrateSetupData(portalProxy, consoleRepo)
if err != nil {
log.Warnf("Unable to initialize config environment provider: %+v", err)
}

addSetupMiddleware.addSetup = true
addSetupMiddleware.consoleRepo = consoleRepo
log.Info("Will add `setup` route and middleware")
// Load config stored in the database
err = console_config.InitializeConfEnvProvider(consoleRepo)
if err != nil {
log.Warnf("Unable to load configuration from database: %+v", err)
}

} else {
showStratosConfig(consoleConfig)
portalProxy.Config.ConsoleConfig = consoleConfig
setSSOFromConfig(portalProxy, consoleConfig)
}
// Now that the config DB is an env provider, we can just use the env to fetch the setup values
consoleConfig, err := portalProxy.initialiseConsoleConfig(portalProxy.Env())
if err != nil {
// Could not read config - this should not happen - so abort if it does
log.Fatalf("Unable to load console config; %+v", err)
}

} else if err == nil && isInitialised {
consoleConfig, err := consoleRepo.GetConsoleConfig()
if err != nil {
log.Infof("Instance is initialised, but console_config table may contain junk data! %+v", err)
}
// We dynamically determine if we need to enter setup mode based on the configuration
// We need: UAA Endpoint and Console Admin Scope
if !consoleConfig.IsSetupComplete() {
addSetupMiddleware = true
log.Info("Will add `setup` route and middleware")
} else {
showStratosConfig(consoleConfig)
portalProxy.Config.ConsoleConfig = consoleConfig
setSSOFromConfig(portalProxy, consoleConfig)
portalProxy.Config.SSOLogin = consoleConfig.UseSSO
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The gate on SSO_LOGIN has been lost. Is this checked later on or not needed now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you expand what you mean by gate?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, in the removed setSSOFromConfig, Config.SSOLogin was only set if !portalProxy.Env().IsSet("SSO_LOGIN") was true. Now it's always set. Was wondering this was a fix or omission

Copy link
Contributor Author

@nwmac nwmac Jun 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a fix - previously these two somewhat competed - now they are backed by the same env var

}

return addSetupMiddleware, nil
}

func setSSOFromConfig(portalProxy *portalProxy, configuration *interfaces.ConsoleConfig) {
// For SSO, override the value loaded from the config file, so that this is what we use
if !portalProxy.Env().IsSet("SSO_LOGIN") {
portalProxy.Config.SSOLogin = configuration.UseSSO
}
}

func showStratosConfig(config *interfaces.ConsoleConfig) {
log.Infof("Stratos is intialised with the following setup:")
log.Infof("Stratos is initialized with the following setup:")
log.Infof("... UAA Endpoint : %s", config.UAAEndpoint)
log.Infof("... Authorization Endpoint : %s", config.AuthorizationEndpoint)
log.Infof("... Console Client : %s", config.ConsoleClient)
log.Infof("... Skip SSL Validation : %t", config.SkipSSLValidation)
log.Infof("... Setup Complete : %t", config.IsSetupComplete)
log.Infof("... Setup Complete : %t", config.IsSetupComplete())
log.Infof("... Admin Scope : %s", config.ConsoleAdminScope)
log.Infof("... Use SSO Login : %t", config.UseSSO)
}
Expand Down Expand Up @@ -630,7 +631,7 @@ func initializeHTTPClients(timeout int64, timeoutMutating int64, connectionTimeo
httpClientMutatingSkipSSL.Timeout = time.Duration(timeoutMutating) * time.Second
}

func start(config interfaces.PortalConfig, p *portalProxy, addSetupMiddleware *setupMiddleware, isUpgrade bool) error {
func start(config interfaces.PortalConfig, p *portalProxy, needSetupMiddleware bool, isUpgrade bool) error {
log.Debug("start")
e := echo.New()
e.HideBanner = true
Expand Down Expand Up @@ -663,7 +664,7 @@ func start(config interfaces.PortalConfig, p *portalProxy, addSetupMiddleware *s
e.Use(bindToEnv(retryAfterUpgradeMiddleware, p.Env()))

if !isUpgrade {
p.registerRoutes(e, addSetupMiddleware)
p.registerRoutes(e, needSetupMiddleware)
}

if isUpgrade {
Expand All @@ -687,7 +688,7 @@ func start(config interfaces.PortalConfig, p *portalProxy, addSetupMiddleware *s
if engineErr != nil {
engineErrStr := fmt.Sprintf("%s", engineErr)
if !strings.Contains(engineErrStr, "Server closed") {
log.Warnf("Failed to start HTTP/S server: %v+", engineErr)
log.Warnf("Failed to start HTTP/S server: %+v", engineErr)
}
}

Expand Down Expand Up @@ -739,7 +740,7 @@ func (p *portalProxy) getHttpClient(skipSSLValidation bool, mutating bool) http.
return client
}

func (p *portalProxy) registerRoutes(e *echo.Echo, addSetupMiddleware *setupMiddleware) {
func (p *portalProxy) registerRoutes(e *echo.Echo, needSetupMiddleware bool) {
log.Debug("registerRoutes")

for _, plugin := range p.Plugins {
Expand All @@ -759,9 +760,8 @@ func (p *portalProxy) registerRoutes(e *echo.Echo, addSetupMiddleware *setupMidd
pp.Use(p.setSecureCacheContentMiddleware)

// Add middleware to block requests if unconfigured
if addSetupMiddleware.addSetup {
go p.SetupPoller(addSetupMiddleware)
e.Use(p.SetupMiddleware(addSetupMiddleware))
if needSetupMiddleware {
e.Use(p.SetupMiddleware())
pp.POST("/v1/setup", p.setupConsole)
pp.POST("/v1/setup/update", p.setupConsoleUpdate)
}
Expand Down
4 changes: 2 additions & 2 deletions src/jetstream/plugins/cfappssh/app_ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func (cfAppSsh *CFAppSSH) appSSH(c echo.Context) error {
_, r, err := ws.ReadMessage()
if err != nil {
log.Error("Error reading message from web socket")
log.Warnf("%v+", err)
log.Warnf("%+v", err)
return err
}

Expand Down Expand Up @@ -293,7 +293,7 @@ func getSSHCode(authorizeEndpoint, clientID, token string, skipSSLValidation boo

resp, err := httpClientWithoutRedirects.Do(authorizeReq)
if resp != nil {
log.Infof("%v+", resp)
log.Infof("%+v", resp)
}
if err == nil {
return "", errors.New("Authorization server did not redirect with one time code")
Expand Down
25 changes: 16 additions & 9 deletions src/jetstream/plugins/cloudfoundryhosting/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,24 @@ func ConfigInit(envLookup *env.VarSet, jetstreamConfig *interfaces.PortalConfig)
}
}
}

}

// Init creates a new CFHosting plugin
func Init(portalProxy interfaces.PortalProxy) (interfaces.StratosPlugin, error) {

// Update Database migration status depending on app instance index and SQLite
if portalProxy.Env().IsSet(VCapApplication) {
isSQLite := portalProxy.GetConfig().DatabaseProviderName == SQLiteProviderName
if !isSQLite && portalProxy.Env().IsSet("CF_INSTANCE_INDEX") {
if appInstanceIndex, ok := portalProxy.Env().Lookup("CF_INSTANCE_INDEX"); ok {
if index, err := strconv.Atoi(appInstanceIndex); err == nil {
portalProxy.SetCanPerformMigrations(index == 0)
}
}
}
}

return &CFHosting{portalProxy: portalProxy}, nil
}

Expand Down Expand Up @@ -138,7 +152,7 @@ func (ch *CFHosting) Init() error {
data := []byte(vCapApp)
err := json.Unmarshal(data, &appData)
if err != nil {
log.Fatalf("Could not get the Cloud Foundry API URL: %v+", err)
log.Fatalf("Could not get the Cloud Foundry API URL: %+v", err)
return nil
}

Expand Down Expand Up @@ -179,7 +193,7 @@ func (ch *CFHosting) Init() error {
cfEndpointSpec, _ := ch.portalProxy.GetEndpointTypeSpec("cf")
newCNSI, _, err := cfEndpointSpec.Info(appData.API, true)
if err != nil {
log.Fatalf("Could not get the info for Cloud Foundry: %v+", err)
log.Fatalf("Could not get the info for Cloud Foundry: %+v", err)
return nil
}

Expand All @@ -205,13 +219,6 @@ func (ch *CFHosting) Init() error {
// CHECK is this necessary to set here?
ch.portalProxy.GetConfig().ConsoleConfig.SkipSSLValidation = ch.portalProxy.Env().MustBool("SKIP_SSL_VALIDATION")

// Save to Console DB
err = ch.portalProxy.SaveConsoleConfig(ch.portalProxy.GetConfig().ConsoleConfig, nil)
if err != nil {
log.Fatalf("Failed to save console configuration due to %s", err)
return fmt.Errorf("Failed to save console configuration due to %s", err)
}

if !ch.portalProxy.Env().IsSet(SkipAutoRegister) {
log.Info("Setting AUTO_REG_CF_URL config to ", appData.API)
ch.portalProxy.GetConfig().AutoRegisterCFUrl = appData.API
Expand Down
Loading