mirror of
https://github.com/gomods/athens
synced 2026-02-03 11:00:32 +00:00
config: flatten Proxy struct (#846)
* config: flatten Proxy struct * fix mw_test * gofmt * add line
This commit is contained in:
+13
-13
@@ -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
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user