Skip to content

Commit

Permalink
add option to specify config.yaml (#30)
Browse files Browse the repository at this point in the history
* add option to specify config.yaml
* remove config flags. Use config file or environment variables
* let viper manage the environment variables
* Added table for readme; Set sensible defaults
* dump config settings

Co-authored-by: Jordan Neufeld <[email protected]>
Co-authored-by: Jordan Neufeld <[email protected]>
  • Loading branch information
3 people authored Nov 4, 2020
1 parent 1d554b3 commit f87f532
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 47 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.env
.env_local
.env.unset
main
tmp
./solidfire-exporter
Expand Down
46 changes: 38 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,50 @@ Binaries can be downloaded from [Github releases](https://github.com/mjavier2k/s
### Usage

```
./solidfire_exporter -u $SOLIDFIRE_USER -p $SOLIDFIRE_PASSWORD -e $SOLIDFIRE_ENDPOINT
./solidfire_exporter --config config.yaml
```

```
Usage of solidfire-exporter:
-l, --listenPort int Port for the exporter to listen on. May also be set by environment variable SOLIDFIRE_PORT. (default 9987)
-u, --username string User with which to authenticate to the Solidfire API. May also be set by environment variable SOLIDFIRE_USER. (default "my_solidfire_user")
-p, --password string Password with which to authenticate to the Solidfire API. May also be set by environment variable SOLIDFIRE_PASS. (default "my_solidfire_password")
-e, --endpoint string Endpoint for the Solidfire API. May also be set by environment variable SOLIDFIRE_RPC_ENDPOINT. (default "https://192.168.1.2/json-rpc/11.3")
-i, --insecure Whether to disable TLS validation when calling the Solidfire API. May also be set by environment variable INSECURE_SKIP_VERIFY.
-t, --timeout int HTTP Client timeout (in seconds) per call to Solidfire API. (default 30)
-c, --config string Specify configuration filename. (default: config.yaml)
```

__NOTE__: The account for __SOLIDFIRE_USER__ must have administrator access to the solidfire cluster so that QOS data will show up.

### Configuration

| Yaml Configuration Option | CLI Flag | Environment Variable | Default | Example | Description |
| ------------------------- | -------- | ------------------------- | ------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| client.username | N/A | SOLIDFIRE_CLIENT_USERNAME | "" | myUsername | User with which to authenticate to the Solidfire API. NOTE: User must have administrator access to be able to query QOS data. |
| client.password | N/A | SOLIDFIRE_CLIENT_PASSWORD | "" | myPassword | Password with which to authenticate to the Solidfire API. |
| client.endpoint | N/A | SOLIDFIRE_CLIENT_ENDPOINT | https://127.0.0.1/json-rpc/11.3 | http://192.168.12.10/json-rpc/11.3 | HTTP(s) endpoint of the Solidfire API. |
| client.insecure | N/A | SOLIDFIRE_CLIENT_INSECURE | false | true | Disables TLS validation when calling Solidfire API. Useful for bypassing self-signed certificates in testing. |
| client.timeout | N/A | SOLIDFIRE_CLIENT_TIMEOUT | 30 | 75 | Timeout in seconds per call to the Solidfire API. |
| listen.address | N/A | SOLIDFIRE_LISTEN_ADDRESS | 0.0.0.0:9987 | 192.168.4.2:13987 | IP address and port where the http server of this exporter should listen |
| N/A | -c | SOLIDFIRE_CONFIG | config.yaml | mySolidfireConfig.yaml | Path to configuration file |

1) Using config.yaml

```
listen:
address: 127.0.0.1:9987
client:
endpoint: https://192.168.1.2/json-rpc/11.3
username: mySolidfireUsername
password: mySolidfirePassword
insecure: false
timeout: 130
```

2) Using environment variables. These option takes precedence if config.yaml is also specified.

```
export SOLIDFIRE_CLIENT_USERNAME="mySolidfireUsername"
export SOLIDFIRE_CLIENT_PASSWORD="mySolidfirePassword"
export SOLIDFIRE_LISTEN_ADDRESS="127.0.0.1:9987"
export SOLIDFIRE_CLIENT_ENDPOINT="https://10.10.10.10/json-rpc/11.3"
export SOLIDFIRE_CLIENT_INSECURE=true
export SOLIDFIRE_CLIENT_TIMEOUT=30
```

### Prometheus Configuration

Expand Down
56 changes: 34 additions & 22 deletions cmd/solidfire-exporter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package main
import (
"fmt"
"net/http"
"os"
"path/filepath"
"strings"

log "github.com/amoghe/distillog"
"github.com/mjavier2k/solidfire-exporter/pkg/prom"
Expand All @@ -20,43 +21,54 @@ var (
)

func init() {
flag.CommandLine.SortFlags = false
flag.IntP(solidfire.ListenPortFlag, "l", 9987, fmt.Sprintf("Port for the exporter to listen on. May also be set by environment variable %v.", solidfire.ListenPortFlagEnv))
flag.StringP(solidfire.UsernameFlag, "u", "my_solidfire_user", fmt.Sprintf("User with which to authenticate to the Solidfire API. May also be set by environment variable %v.", solidfire.UsernameFlagEnv))
flag.StringP(solidfire.PasswordFlag, "p", "my_solidfire_password", fmt.Sprintf("Password with which to authenticate to the Solidfire API. May also be set by environment variable %v.", solidfire.PasswordFlagEnv))
flag.StringP(solidfire.EndpointFlag, "e", "https://192.168.1.2/json-rpc/11.3", fmt.Sprintf("Endpoint for the Solidfire API. May also be set by environment variable %v.", solidfire.EndpointFlagEnv))
flag.BoolP(solidfire.InsecureSSLFlag, "i", false, fmt.Sprintf("Whether to disable TLS validation when calling the Solidfire API. May also be set by environment variable %v.", solidfire.InsecureSSLFlagEnv))
flag.Int64P(solidfire.HTTPClientTimeoutFlag, "t", 30, fmt.Sprintf("HTTP Client timeout (in seconds) per call to Solidfire API."))
flag.CommandLine.SortFlags = true
flag.StringP(solidfire.ConfigFile, "c", solidfire.DefaultConfigFile, fmt.Sprintf("Specify configuration filename."))
flag.Parse()
viper.BindPFlags(flag.CommandLine)

// extracts the filename from the config filename passed on --config flag (e.g /etc/solidfire-exporter/config.yaml)
viper.SetConfigName(filepath.Base(viper.GetString(solidfire.ConfigFile)))
viper.SetConfigType("yaml")
// extracts the directory path from the config filename passed on --config flag (e.g /etc/solidfire-exporter/config.yaml)
viper.AddConfigPath(filepath.Dir(viper.GetString(solidfire.ConfigFile)))
viper.AddConfigPath(".")

// PORT environment variable takes precedence in order to be backwards-compatible
if legacyPort, legacyPortFlagExists := os.LookupEnv("PORT"); legacyPortFlagExists {
viper.BindEnv(solidfire.ListenPortFlag, "PORT")
log.Warningf("Found environment variable PORT=%v, skipping lookup of %v", legacyPort, solidfire.ListenPortFlagEnv)
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
log.Infof("No config file found.")
}
} else {
viper.BindEnv(solidfire.ListenPortFlag, solidfire.ListenPortFlagEnv)
log.Infof("Found configuration file on %v ", viper.GetViper().ConfigFileUsed())
}

viper.BindEnv(solidfire.UsernameFlag, solidfire.UsernameFlagEnv)
viper.BindEnv(solidfire.PasswordFlag, solidfire.PasswordFlagEnv)
viper.BindEnv(solidfire.EndpointFlag, solidfire.EndpointFlagEnv)
viper.BindEnv(solidfire.InsecureSSLFlag, solidfire.InsecureSSLFlagEnv)
viper.BindPFlags(flag.CommandLine)
viper.SetDefault(solidfire.ListenAddress, solidfire.DefaultListenAddress)
viper.SetDefault(solidfire.Endpoint, solidfire.DefaultEndpoint)
viper.SetDefault(solidfire.HTTPClientTimeout, solidfire.DefaultHTTPClientTimeout)

viper.AutomaticEnv()
viper.SetEnvPrefix("SOLIDFIRE")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
}
func main() {
log.Infof("Version: %v", sha1ver)
log.Infof("Built: %v", buildTime)
listenAddr := fmt.Sprintf("0.0.0.0:%v", viper.GetInt(solidfire.ListenPortFlag))
listenAddress := fmt.Sprintf("%v", viper.GetString(solidfire.ListenAddress))
solidfireExporter, _ := prom.NewCollector()
prometheus.MustRegister(solidfireExporter)
http.Handle("/metrics", promhttp.Handler())
log.Infof("Booted and listening on %v/metrics\n", listenAddr)

for _, key := range viper.AllKeys() {
value := viper.Get(key)
if key == solidfire.Password {
value = "[REDACTED]"
}
log.Infof("Config setting found for %s: %v", key, value)
}
log.Infof("Booted and listening on %v/metrics\n", listenAddress)
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "UP")
})

err := http.ListenAndServe(listenAddr, nil)
err := http.ListenAndServe(listenAddress, nil)
if err != nil {
log.Errorln(err)
}
Expand Down
8 changes: 8 additions & 0 deletions config.yaml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
listen:
address: 127.0.0.1:9987
client:
endpoint: https://192.168.1.2/json-rpc/11.3
username: mySolidfireUsername
password: mySolidfirePassword
insecure: false
timeout: 130
12 changes: 6 additions & 6 deletions pkg/solidfire/solidfire.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ import (
func NewSolidfireClient() *Client {
log.Infof("initializing new solidfire client")

insecure := viper.GetBool(InsecureSSLFlag)
insecure := viper.GetBool(InsecureSSL)
if insecure {
log.Warningln("TLS certificate verification is currently disabled - This is not recommended.")
}

log.Infoln("RPC Server:", viper.GetString(EndpointFlag))
log.Infoln("RPC Server:", viper.GetString(Endpoint))

tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure},
}
return &Client{
HttpClient: &http.Client{
Transport: tr,
Timeout: time.Duration(viper.GetInt64(HTTPClientTimeoutFlag)) * time.Second,
Timeout: time.Duration(viper.GetInt64(HTTPClientTimeout)) * time.Second,
},
Username: viper.GetString(UsernameFlag),
Password: viper.GetString(PasswordFlag),
RPCEndpoint: viper.GetString(EndpointFlag),
Username: viper.GetString(Username),
Password: viper.GetString(Password),
RPCEndpoint: viper.GetString(Endpoint),
}
}

Expand Down
26 changes: 15 additions & 11 deletions pkg/solidfire/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@ import (
)

var (
ListenPortFlag = "listenPort"
UsernameFlag = "username"
PasswordFlag = "password"
EndpointFlag = "endpoint"
InsecureSSLFlag = "insecure"
HTTPClientTimeoutFlag = "timeout"
ListenPortFlagEnv = "SOLIDFIRE_PORT"
UsernameFlagEnv = "SOLIDFIRE_USER"
PasswordFlagEnv = "SOLIDFIRE_PASS"
EndpointFlagEnv = "SOLIDFIRE_RPC_ENDPOINT"
InsecureSSLFlagEnv = "INSECURE_SKIP_VERIFY"
ListenAddress = "listen.address"
DefaultListenAddress = "0.0.0.0:9987"

Username = "client.username"
Password = "client.password"

Endpoint = "client.endpoint"
DefaultEndpoint = "http://127.0.0.1/json-rpc/11.3"
InsecureSSL = "client.insecure"

HTTPClientTimeout = "client.timeout"
DefaultHTTPClientTimeout = 30

ConfigFile = "config"
DefaultConfigFile = "config.yaml"
)

type Client struct {
Expand Down

0 comments on commit f87f532

Please sign in to comment.