cloudfoundry-incubator/stratos

View on GitHub
src/jetstream/repository/console_config/psql_console_config.go

Summary

Maintainability
A
2 hrs
Test Coverage
package console_config

import (
    "database/sql"
    "errors"
    "fmt"
    "net/url"

    log "github.com/sirupsen/logrus"

    "github.com/cloudfoundry-incubator/stratos/src/jetstream/datastore"
    "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces"
)

// Legacy
var getConsoleConfig = `SELECT auth_endpoint_type, uaa_endpoint, auth_endpoint, console_admin_scope, console_client, console_client_secret, skip_ssl_validation, use_sso FROM console_config`

var deleteConsoleConfig = `DELETE FROM console_config`

// New Config Tale schema

var getConfigValue = `SELECT name, value, last_updated FROM config WHERE groupName = $1 AND name = $2`

var insertConfigValue = `INSERT INTO config (groupName, name, value) VALUES ($1, $2, $3)`

var updateConfigValue = `UPDATE config SET value=$1 WHERE groupName=$2 AND name=$3`

var deleteConfigValue = `DELETE FROM config WHERE groupName=$1 AND name=$2`

var getAllConfigValues = `SELECT name, value, last_updated FROM config WHERE groupName = $1`

// PostgresCNSIRepository is a PostgreSQL-backed ConsoleConfig repository
type ConsoleConfigRepository struct {
    db *sql.DB
}

// NewPostgresConsoleConfigRepository will create a new instance of the PostgresConsoleConfigRepository
func NewPostgresConsoleConfigRepository(dcp *sql.DB) (Repository, error) {
    return &ConsoleConfigRepository{db: dcp}, nil
}

// InitRepositoryProvider - One time init for the given DB Provider
func InitRepositoryProvider(databaseProvider string) {
    // Modify the database statements if needed, for the given database type
    getConsoleConfig = datastore.ModifySQLStatement(getConsoleConfig, databaseProvider)
    deleteConsoleConfig = datastore.ModifySQLStatement(deleteConsoleConfig, databaseProvider)

    getConfigValue = datastore.ModifySQLStatement(getConfigValue, databaseProvider)
    insertConfigValue = datastore.ModifySQLStatement(insertConfigValue, databaseProvider)
    updateConfigValue = datastore.ModifySQLStatement(updateConfigValue, databaseProvider)
    deleteConfigValue = datastore.ModifySQLStatement(deleteConfigValue, databaseProvider)
    getAllConfigValues = datastore.ModifySQLStatement(getAllConfigValues, databaseProvider)
}

// GetValue will try and get the config value for the specified key
func (c *ConsoleConfigRepository) GetValue(group, key string) (string, bool, error) {

    var (
        name        string
        value       string
        lastUpdated string
    )

    err := c.db.QueryRow(getConfigValue, group, key).Scan(&name, &value, &lastUpdated)

    switch {
    case err == sql.ErrNoRows:
        // No matching value
        return "", false, nil
    case err != nil:
        return "", false, err
    default:
        // do nothing
    }

    return value, true, nil
}

func (c *ConsoleConfigRepository) SetValue(group, name, value string) error {

    log.Debug("Config SetValue")

    _, ok, err := c.GetValue(group, name)
    if err != nil {
        return err
    }

    if !ok {
        if _, err := c.db.Exec(insertConfigValue, group, name, value); err != nil {
            msg := "Unable to INSERT config value: %v"
            log.Debugf(msg, err)
            return fmt.Errorf(msg, err)
        }
    } else {
        if _, err := c.db.Exec(updateConfigValue, value, group, name); err != nil {
            msg := "Unable to UPDATE config value: %v"
            log.Debugf(msg, err)
            return fmt.Errorf(msg, err)
        }
    }

    return nil
}

// DeleteValue deletes a value from the config table
func (c *ConsoleConfigRepository) DeleteValue(group, key string) error {
    log.Debug("Config Delete")
    if _, err := c.db.Exec(deleteConfigValue, group, key); err != nil {
        return fmt.Errorf("Unable to delete config value: %v", err)
    }

    return nil
}

// GetValues returns all values from the config table as a map
func (c *ConsoleConfigRepository) GetValues(group string) (map[string]string, error) {

    log.Debug("Config GetValues")
    rows, err := c.db.Query(getAllConfigValues, group)
    if err != nil {
        return nil, fmt.Errorf("Unable to retrieve config records: %v", err)
    }
    defer rows.Close()

    var values = make(map[string]string)

    for rows.Next() {
        var (
            name        string
            value       string
            lastUpdated string
        )

        err := rows.Scan(&name, &value, &lastUpdated)
        if err != nil {
            return nil, fmt.Errorf("Unable to scan config records: %v", err)
        }

        values[name] = value
    }

    if err = rows.Err(); err != nil {
        return nil, fmt.Errorf("Unable to get config records: %v", err)
    }

    return values, nil
}

func (c *ConsoleConfigRepository) GetConsoleConfig() (*interfaces.ConsoleConfig, error) {
    log.Debug("Get ConsoleConfig")
    rows, err := c.db.Query(getConsoleConfig)
    if err != nil {
        return nil, fmt.Errorf("Unable to retrieve console config record: %v", err)
    }
    defer rows.Close()

    rowCount := 0

    var consoleConfig *interfaces.ConsoleConfig
    for rows.Next() {
        var (
            uaaEndpoint      string
            authEndpoint     sql.NullString
            authEndpointType sql.NullString
        )
        rowCount++
        if rowCount > 1 {
            return nil, errors.New("Multiple configuration data detected")
        }

        consoleConfig = new(interfaces.ConsoleConfig)
        err := rows.Scan(&authEndpointType, &uaaEndpoint, &authEndpoint, &consoleConfig.ConsoleAdminScope, &consoleConfig.ConsoleClient,
            &consoleConfig.ConsoleClientSecret, &consoleConfig.SkipSSLValidation, &consoleConfig.UseSSO)
        if err != nil {
            return nil, fmt.Errorf("Unable to scan config record: %v", err)
        }

        if consoleConfig.UAAEndpoint, err = url.Parse(uaaEndpoint); err != nil {
            return nil, fmt.Errorf("Unable to parse UAA Endpoint: %v", err)
        }

        // Might be null if database was upgraded
        if authEndpoint.Valid {
            if consoleConfig.AuthorizationEndpoint, err = url.Parse(authEndpoint.String); err != nil {
                return nil, fmt.Errorf("Unable to parse Authorization Endpoint: %v", err)
            }
        }

        if authEndpointType.Valid {
            consoleConfig.AuthEndpointType = authEndpointType.String
        } else {
            consoleConfig.AuthEndpointType = "remote"
        }
    }

    return consoleConfig, nil
}

// DeleteConsoleConfig will delete all row(s) from the legacy config_config table
func (c *ConsoleConfigRepository) DeleteConsoleConfig() error {
    log.Debug("DeleteConsoleConfig")
    if _, err := c.db.Exec(deleteConsoleConfig); err != nil {
        return fmt.Errorf("Unable to delete all data from console_config: %v", err)
    }

    return nil
}