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

add option to specify config.yaml #30

Merged
merged 15 commits into from
Nov 4, 2020
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