config: flatten Proxy struct (#846)

* config: flatten Proxy struct

* fix mw_test

* gofmt

* add line
This commit is contained in:
Marwan Sulaiman
2018-11-01 17:21:42 -04:00
committed by GitHub
parent c454512ba3
commit 21dcd5a388
6 changed files with 128 additions and 155 deletions
+13 -13
View File
@@ -33,28 +33,28 @@ func App(conf *config.Config) (*buffalo.App, error) {
// ENV is used to help switch settings based on where the
// application is being run. Default is "development".
ENV := conf.GoEnv
store, err := GetStorage(conf.Proxy.StorageType, conf.Storage)
store, err := GetStorage(conf.StorageType, conf.Storage)
if err != nil {
err = fmt.Errorf("error getting storage configuration (%s)", err)
return nil, err
}
if conf.Proxy.GithubToken != "" {
if conf.Proxy.NETRCPath != "" {
if conf.GithubToken != "" {
if conf.NETRCPath != "" {
fmt.Println("Cannot provide both GithubToken and NETRCPath. Only provide one.")
os.Exit(1)
}
netrcFromToken(conf.Proxy.GithubToken)
netrcFromToken(conf.GithubToken)
}
// mount .netrc to home dir
// to have access to private repos.
initializeAuthFile(conf.Proxy.NETRCPath)
initializeAuthFile(conf.NETRCPath)
// mount .hgrc to home dir
// to have access to private repos.
initializeAuthFile(conf.Proxy.HGRCPath)
initializeAuthFile(conf.HGRCPath)
logLvl, err := logrus.ParseLevel(conf.LogLevel)
if err != nil {
@@ -75,11 +75,11 @@ func App(conf *config.Config) (*buffalo.App, error) {
},
SessionName: "_athens_session",
Logger: blggr,
Addr: conf.Proxy.Port,
Addr: conf.Port,
WorkerOff: true,
Host: "http://127.0.0.1" + conf.Proxy.Port,
Host: "http://127.0.0.1" + conf.Port,
})
if prefix := conf.Proxy.PathPrefix; prefix != "" {
if prefix := conf.PathPrefix; prefix != "" {
// certain Ingress Controllers (such as GCP Load Balancer)
// can not send custom headers and therefore if the proxy
// is running behind a prefix as well as some authentication
@@ -109,7 +109,7 @@ func App(conf *config.Config) (*buffalo.App, error) {
// Automatically redirect to SSL
app.Use(forcessl.Middleware(secure.Options{
SSLRedirect: conf.Proxy.ForceSSL,
SSLRedirect: conf.ForceSSL,
SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"},
}))
@@ -124,15 +124,15 @@ func App(conf *config.Config) (*buffalo.App, error) {
if err != nil {
lggr.Fatal(err)
}
app.Use(mw.NewFilterMiddleware(mf, conf.Proxy.GlobalEndpoint))
app.Use(mw.NewFilterMiddleware(mf, conf.GlobalEndpoint))
}
// Having the hook set means we want to use it
if vHook := conf.Proxy.ValidatorHook; vHook != "" {
if vHook := conf.ValidatorHook; vHook != "" {
app.Use(mw.LogEntryMiddleware(mw.NewValidationMiddleware, lggr, vHook))
}
user, pass, ok := conf.Proxy.BasicAuth()
user, pass, ok := conf.BasicAuth()
if ok {
app.Use(basicAuth(user, pass))
}
+62 -63
View File
@@ -54,81 +54,80 @@ FilterFile = ""
# Env override: ATHENS_TIMEOUT
Timeout = 300
[Proxy]
# StorageType sets the type of storage backend the proxy will use.
# Possible values are memory, disk, mongo, gcp, minio, s3
# Defaults to memory
# Env override: ATHENS_STORAGE_TYPE
StorageType = "memory"
# StorageType sets the type of storage backend the proxy will use.
# Possible values are memory, disk, mongo, gcp, minio, s3
# Defaults to memory
# Env override: ATHENS_STORAGE_TYPE
StorageType = "memory"
# Port sets the port the proxy listens on
# Env override: PORT
Port = ":3000"
# Port sets the port the proxy listens on
# Env override: PORT
Port = ":3000"
# The endpoint for a package registry in case of a proxy cache miss
# NOTE: Currently no registries have been implemented
# Env override: ATHENS_GLOBAL_ENDPOINT
GlobalEndpoint = "http://localhost:3001"
# The endpoint for a package registry in case of a proxy cache miss
# NOTE: Currently no registries have been implemented
# Env override: ATHENS_GLOBAL_ENDPOINT
GlobalEndpoint = "http://localhost:3001"
# Username for basic auth
# Env override: BASIC_AUTH_USER
BasicAuthUser = ""
# Username for basic auth
# Env override: BASIC_AUTH_USER
BasicAuthUser = ""
# Password for basic auth
# Env override: BASIC_AUTH_PASS
BasicAuthPass = ""
# Password for basic auth
# Env override: BASIC_AUTH_PASS
BasicAuthPass = ""
# Set to true to force an SSL redirect
# Env override: PROXY_FORCE_SSL
ForceSSL = false
# Set to true to force an SSL redirect
# Env override: PROXY_FORCE_SSL
ForceSSL = false
# ValidatorHook specifies the endpoint to validate modules against
# Not used if left blank or not specified
# Env override: ATHENS_PROXY_VALIDATOR
ValidatorHook = ""
# ValidatorHook specifies the endpoint to validate modules against
# Not used if left blank or not specified
# Env override: ATHENS_PROXY_VALIDATOR
ValidatorHook = ""
# PathPrefix specifies whether the Proxy
# should have a basepath. Certain proxies and services
# are distinguished based on subdomain, while others are based
# on path prefixes.
# Env override: ATHENS_PATH_PREFIX
PathPrefix = ""
# PathPrefix specifies whether the Proxy
# should have a basepath. Certain proxies and services
# are distinguished based on subdomain, while others are based
# on path prefixes.
# Env override: ATHENS_PATH_PREFIX
PathPrefix = ""
# NETRCPath tells you where the .netrc path initially resides.
# This is so that you can mount the .netrc file to a secret location
# in the fs system and then move it ~/.netrc. In certain deployments
# like Kubernetes, we can't mount directly to ~ because it would then
# clean out whatever is already there as part of the image (such as
# .cache directory in the Go image).
# Env override: ATHENS_NETRC_PATH
NETRCPath = ""
# NETRCPath tells you where the .netrc path initially resides.
# This is so that you can mount the .netrc file to a secret location
# in the fs system and then move it ~/.netrc. In certain deployments
# like Kubernetes, we can't mount directly to ~ because it would then
# clean out whatever is already there as part of the image (such as
# .cache directory in the Go image).
# Env override: ATHENS_NETRC_PATH
NETRCPath = ""
# GithubToken can be used instead of a NETRCPath to authenticate
# the proxy to your own private repos on github. This makes it
# easier for users and for platforms like GAE to only be provided
# a Github token instead of a .netrc file. Internally, the proxy
# just create a .netrc file for you.
# Env override: ATHENS_GITHUB_TOKEN
GithubToken = ""
# GithubToken can be used instead of a NETRCPath to authenticate
# the proxy to your own private repos on github. This makes it
# easier for users and for platforms like GAE to only be provided
# a Github token instead of a .netrc file. Internally, the proxy
# just create a .netrc file for you.
# Env override: ATHENS_GITHUB_TOKEN
GithubToken = ""
# HGRCPath tells you where the .hgrc path initially resides.
# This is so that you can mount the .hgrc file to a secret location
# in the fs system and then move it ~/.hgrc. In certain deployments
# like Kubernetes, we can't mount directly to ~ because it would then
# clean out whatever is already there as part of the image (such as
# .cache directory in the Go image).
# Env override: ATHENS_HGRC_PATH
HGRCPath = ""
# HGRCPath tells you where the .hgrc path initially resides.
# This is so that you can mount the .hgrc file to a secret location
# in the fs system and then move it ~/.hgrc. In certain deployments
# like Kubernetes, we can't mount directly to ~ because it would then
# clean out whatever is already there as part of the image (such as
# .cache directory in the Go image).
# Env override: ATHENS_HGRC_PATH
HGRCPath = ""
# TraceExporterURL is the URL to which Athens populates distributed tracing
# information such as Jaeger. In Stackdriver, use this as the GCP ProjectID.
# Env override: ATHENS_TRACE_EXPORTER_URL
TraceExporterURL = ""
# TraceExporterURL is the URL to which Athens populates distributed tracing
# information such as Jaeger. In Stackdriver, use this as the GCP ProjectID.
# Env override: ATHENS_TRACE_EXPORTER_URL
TraceExporterURL = ""
# TraceExporter is the service to which the data collected by OpenCensus can be exported to.
# Possible values are: jaeger, datadog, and stackdriver.
# Env overide: ATHENS_TRACE_EXPORTER
TraceExporter = ""
# TraceExporter is the service to which the data collected by OpenCensus can be exported to.
# Possible values are: jaeger, datadog, and stackdriver.
# Env overide: ATHENS_TRACE_EXPORTER
TraceExporter = ""
[Storage]
# Only storage backends that are specified in Proxy.StorageType are required here
+20 -1
View File
@@ -24,10 +24,29 @@ type Config struct {
FilterFile string `envconfig:"ATHENS_FILTER_FILE"`
TraceExporterURL string `envconfig:"ATHENS_TRACE_EXPORTER_URL"`
TraceExporter string `envconfig:"ATHENS_TRACE_EXPORTER"`
Proxy *ProxyConfig
StorageType string `validate:"required" envconfig:"ATHENS_STORAGE_TYPE"`
GlobalEndpoint string `envconfig:"ATHENS_GLOBAL_ENDPOINT"` // This feature is not yet implemented
Port string `envconfig:"ATHENS_PORT" default:":3000"`
BasicAuthUser string `envconfig:"BASIC_AUTH_USER"`
BasicAuthPass string `envconfig:"BASIC_AUTH_PASS"`
ForceSSL bool `envconfig:"PROXY_FORCE_SSL"`
ValidatorHook string `envconfig:"ATHENS_PROXY_VALIDATOR"`
PathPrefix string `envconfig:"ATHENS_PATH_PREFIX"`
NETRCPath string `envconfig:"ATHENS_NETRC_PATH"`
GithubToken string `envconfig:"ATHENS_GITHUB_TOKEN"`
HGRCPath string `envconfig:"ATHENS_HGRC_PATH"`
Storage *StorageConfig
}
// BasicAuth returns BasicAuthUser and BasicAuthPassword
// and ok if neither of them are empty
func (c *Config) BasicAuth() (user, pass string, ok bool) {
user = c.BasicAuthUser
pass = c.BasicAuthPass
ok = user != "" && pass != ""
return user, pass, ok
}
// FilterOff returns true if the FilterFile is empty
func (c *Config) FilterOff() bool {
return c.FilterFile == ""
+30 -47
View File
@@ -14,15 +14,11 @@ import (
const exampleConfigPath = "../../config.dev.toml"
func compareConfigs(parsedConf *Config, expConf *Config, t *testing.T) {
opts := cmpopts.IgnoreTypes(StorageConfig{}, ProxyConfig{})
opts := cmpopts.IgnoreTypes(StorageConfig{})
eq := cmp.Equal(parsedConf, expConf, opts)
if !eq {
t.Errorf("Parsed Example configuration did not match expected values. Expected: %+v. Actual: %+v", expConf, parsedConf)
}
eq = cmp.Equal(parsedConf.Proxy, expConf.Proxy)
if !eq {
t.Errorf("Parsed Example Proxy configuration did not match expected values. Expected: %+v. Actual: %+v", expConf.Proxy, parsedConf.Proxy)
}
compareStorageConfigs(parsedConf.Storage, expConf.Storage, t)
}
@@ -60,26 +56,12 @@ func TestPortDefaultsCorrectly(t *testing.T) {
t.Fatalf("Env override failed: %v", err)
}
expPort := ":3000"
if conf.Proxy.Port != expPort {
t.Errorf("Port was incorrect. Got: %s, want: %s", conf.Proxy.Port, expPort)
if conf.Port != expPort {
t.Errorf("Port was incorrect. Got: %s, want: %s", conf.Port, expPort)
}
}
func TestEnvOverrides(t *testing.T) {
expProxy := ProxyConfig{
StorageType: "minio",
GlobalEndpoint: "mytikas.gomods.io",
Port: ":7000",
BasicAuthUser: "testuser",
BasicAuthPass: "testpass",
ForceSSL: true,
ValidatorHook: "testhook.io",
PathPrefix: "prefix",
NETRCPath: "/test/path/.netrc",
HGRCPath: "/test/path/.hgrc",
}
expConf := &Config{
GoEnv: "production",
GoGetWorkers: 10,
@@ -91,8 +73,17 @@ func TestEnvOverrides(t *testing.T) {
TimeoutConf: TimeoutConf{
Timeout: 30,
},
Proxy: &expProxy,
Storage: &StorageConfig{},
StorageType: "minio",
GlobalEndpoint: "mytikas.gomods.io",
Port: ":7000",
BasicAuthUser: "testuser",
BasicAuthPass: "testpass",
ForceSSL: true,
ValidatorHook: "testhook.io",
PathPrefix: "prefix",
NETRCPath: "/test/path/.netrc",
HGRCPath: "/test/path/.hgrc",
Storage: &StorageConfig{},
}
envVars := getEnvMap(expConf)
@@ -186,7 +177,6 @@ func TestParseExampleConfig(t *testing.T) {
// initialize all struct pointers so we get all applicable env variables
emptyConf := &Config{
Proxy: &ProxyConfig{},
Storage: &StorageConfig{
CDN: &CDNConfig{},
Disk: &DiskConfig{},
@@ -209,14 +199,6 @@ func TestParseExampleConfig(t *testing.T) {
globalTimeout := 300
expProxy := &ProxyConfig{
StorageType: "memory",
GlobalEndpoint: "http://localhost:3001",
Port: ":3000",
BasicAuthUser: "",
BasicAuthPass: "",
}
expStorage := &StorageConfig{
CDN: &CDNConfig{
Endpoint: "cdn.example.com",
@@ -275,8 +257,12 @@ func TestParseExampleConfig(t *testing.T) {
TimeoutConf: TimeoutConf{
Timeout: 300,
},
Proxy: expProxy,
Storage: expStorage,
StorageType: "memory",
GlobalEndpoint: "http://localhost:3001",
Port: ":3000",
BasicAuthUser: "",
BasicAuthPass: "",
Storage: expStorage,
}
absPath, err := filepath.Abs(exampleConfigPath)
@@ -306,19 +292,16 @@ func getEnvMap(config *Config) map[string]string {
"ATHENS_TRACE_EXPORTER": config.TraceExporterURL,
}
proxy := config.Proxy
if proxy != nil {
envVars["ATHENS_STORAGE_TYPE"] = proxy.StorageType
envVars["ATHENS_GLOBAL_ENDPOINT"] = proxy.GlobalEndpoint
envVars["ATHENS_PORT"] = proxy.Port
envVars["BASIC_AUTH_USER"] = proxy.BasicAuthUser
envVars["BASIC_AUTH_PASS"] = proxy.BasicAuthPass
envVars["PROXY_FORCE_SSL"] = strconv.FormatBool(proxy.ForceSSL)
envVars["ATHENS_PROXY_VALIDATOR"] = proxy.ValidatorHook
envVars["ATHENS_PATH_PREFIX"] = proxy.PathPrefix
envVars["ATHENS_NETRC_PATH"] = proxy.NETRCPath
envVars["ATHENS_HGRC_PATH"] = proxy.HGRCPath
}
envVars["ATHENS_STORAGE_TYPE"] = config.StorageType
envVars["ATHENS_GLOBAL_ENDPOINT"] = config.GlobalEndpoint
envVars["ATHENS_PORT"] = config.Port
envVars["BASIC_AUTH_USER"] = config.BasicAuthUser
envVars["BASIC_AUTH_PASS"] = config.BasicAuthPass
envVars["PROXY_FORCE_SSL"] = strconv.FormatBool(config.ForceSSL)
envVars["ATHENS_PROXY_VALIDATOR"] = config.ValidatorHook
envVars["ATHENS_PATH_PREFIX"] = config.PathPrefix
envVars["ATHENS_NETRC_PATH"] = config.NETRCPath
envVars["ATHENS_HGRC_PATH"] = config.HGRCPath
storage := config.Storage
if storage != nil {
-25
View File
@@ -1,25 +0,0 @@
package config
// ProxyConfig specifies the properties required to run the proxy
type ProxyConfig struct {
StorageType string `validate:"required" envconfig:"ATHENS_STORAGE_TYPE"`
GlobalEndpoint string `envconfig:"ATHENS_GLOBAL_ENDPOINT"` // This feature is not yet implemented
Port string `envconfig:"ATHENS_PORT" default:":3000"`
BasicAuthUser string `envconfig:"BASIC_AUTH_USER"`
BasicAuthPass string `envconfig:"BASIC_AUTH_PASS"`
ForceSSL bool `envconfig:"PROXY_FORCE_SSL"`
ValidatorHook string `envconfig:"ATHENS_PROXY_VALIDATOR"`
PathPrefix string `envconfig:"ATHENS_PATH_PREFIX"`
NETRCPath string `envconfig:"ATHENS_NETRC_PATH"`
GithubToken string `envconfig:"ATHENS_GITHUB_TOKEN"`
HGRCPath string `envconfig:"ATHENS_HGRC_PATH"`
}
// BasicAuth returns BasicAuthUser and BasicAuthPassword
// and ok if neither of them are empty
func (p *ProxyConfig) BasicAuth() (user, pass string, ok bool) {
user = p.BasicAuthUser
pass = p.BasicAuthPass
ok = user != "" && pass != ""
return user, pass, ok
}
+3 -6
View File
@@ -70,16 +70,13 @@ func Test_FilterMiddleware(t *testing.T) {
if err != nil {
t.Fatalf("Unable to parse config file: %s", err.Error())
}
if conf.Proxy == nil {
t.Fatalf("No Proxy configuration in test config")
}
// Test with a filter file not existing
app, err := middlewareFilterApp("nofsfile", conf.Proxy.GlobalEndpoint)
app, err := middlewareFilterApp("nofsfile", conf.GlobalEndpoint)
r.Nil(app, "app should be nil when a file not exisiting")
r.Error(err, "Expected error when a file not existing on the filesystem is given")
app, err = middlewareFilterApp(filter.Name(), conf.Proxy.GlobalEndpoint)
app, err = middlewareFilterApp(filter.Name(), conf.GlobalEndpoint)
r.NoError(err, "app should be succesfully created in the test")
w := willie.New(app)
@@ -88,7 +85,7 @@ func Test_FilterMiddleware(t *testing.T) {
for _, path := range paths {
res := w.Request(path).Get()
r.Equal(303, res.Code)
r.Equal(conf.Proxy.GlobalEndpoint+"/github.com/gomods/athens/@v/list/", res.HeaderMap.Get("Location"))
r.Equal(conf.GlobalEndpoint+"/github.com/gomods/athens/@v/list/", res.HeaderMap.Get("Location"))
}
// Excluded, expects a 403