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

Updated the documentation, fixed flag and configuration handling (viper) #64

Merged
merged 1 commit into from
Jun 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,28 @@ The following options can be configured when starting the exporter (with default
```
./telescopes --help
Usage of ./telescopes:
-listen-address string
The address to listen on for HTTP requests. (default ":9090")
-log-level string
log level (default "info")
-product-info-renewal-interval duration
Duration (in go syntax) between renewing the ec2 product info. Example: 2h30m (default 24h0m0s)
-prometheus-address string
http address of a Prometheus instance that has AWS spot price metrics via banzaicloud/spot-price-exporter. If empty, the recommender will use current spot prices queried directly from the AWS API.

--dev-mode development mode, if true token based authentication is disabled, false by default
--gce-api-key string GCE API key to use for getting SKUs
--gce-project-id string GCE project ID to use
--help print usage
--listen-address string the address the telescope listens to HTTP requests. (default ":9090")
--log-level string log level (default "info")
--product-info-renewal-interval duration duration (in go syntax) between renewing the product information. Example: 2h30m (default 24h0m0s)
--prometheus-address string http address of a Prometheus instance that has AWS spot price metrics via banzaicloud/spot-price-exporter. If empty, the recommender will use current spot prices queried directly from the AWS API.
--prometheus-query string advanced configuration: change the query used to query spot price info from Prometheus. (default "avg_over_time(aws_spot_current_price{region=\"%s\", product_description=\"Linux/UNIX\"}[1w])")
--provider strings cloud providers to be used for recommendation (default [ec2,gce])
--token-signing-key string string representing a shared secret with the token emitter component
--vault-address string the vault address for authentication token management, not used in development mode
```

## API calls

*For a complete OpenAPI 3.0 documentation, check out this [URL](https://editor.swagger.io/?url=https://raw.githubusercontent.com/banzaicloud/telescopes/master/docs/openapi/recommender.yaml).*

> We have recently added Oauth2 (bearer) token based authentication to the `telescope` which is enabled by default. In order for this to work, the application needs to be connected to a component (eg.: http://github.com/banzaicloud/pipeline) capable to emit the `bearer token` The connection is made through a `vault` instance (which' address must be specified by the --vault-address flag) The --token-signing-key also must be specified in this case (this is a string secret that is shared with the token emitter component)

*The authentication can be switched off by starting the application in development mode (--dev-mode flag) - please note that other functionality can also be affected!*

#### `POST: api/v1/recommender/:provider/:region/cluster`

This endpoint returns a recommended cluster layout on a specific provider in a specific region, that contains on-demand and spot priced node pools.
Expand All @@ -67,7 +74,7 @@ This endpoint returns a recommended cluster layout on a specific provider in a s
**`cURL` example**

```
curl -sX POST -d '{"sumCpu": 100, "sumMem":200, "sumGpu":0, "minNodes":10, "maxNodes":30, "sameSize":true, "onDemandPct":30, "zones":[]}' "localhost:9092/api/v1/recommender/ec2/eu-west-1/cluster" | jq .
curl -sX -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJodHRwczovL3BpcGVsaW5lLmJhbnphaWNsb3VkLmNvbSIsImp0aSI6IjUxMWE1ODQyLWYxMmUtNDk1NC04YTg2LTVjNmUyOWRmZTg5YiIsImlhdCI6MTUyODE5MTM0MSwiaXNzIjoiaHR0cHM6Ly9iYW56YWljbG91ZC5jb20vIiwic3ViIjoiMSIsInNjb3BlIjoiYXBpOmludm9rZSIsInR5cGUiOiJ1c2VyIiwidGV4dCI6ImxwdXNrYXMifQ.azhx0MbuLp7vQ1XmwPYrOqFG5vWZVh-hkzmHig8nnvs' \POST -d '{"sumCpu": 100, "sumMem":200, "sumGpu":0, "minNodes":10, "maxNodes":30, "sameSize":true, "onDemandPct":30, "zones":[]}' "localhost:9092/api/v1/recommender/ec2/eu-west-1/cluster" | jq .
```
**Sample response:**
```
Expand Down
49 changes: 34 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/gin-gonic/gin"
flag "github.com/spf13/pflag"
"os"
"strings"
)

const (
Expand All @@ -41,6 +42,7 @@ const (
providerFlag = "provider"
devModeFlag = "dev-mode"
tokenSigningKeyFlag = "token-signing-key"
tokenSigningKeyAlias = "tokensigningkey"
vaultAddrAlias = "vault_addr"
vaultAddrFlag = "vault-address"
helpFlag = "help"
Expand All @@ -55,23 +57,25 @@ const (

var (
// env vars required by the application
cfgEnvVars = []string{tokenSigningKeyFlag, vaultAddrAlias}
cfgEnvVars = []string{tokenSigningKeyFlag, vaultAddrFlag}
)

// defineFlags defines supported flags and makes them available for viper
func defineFlags() {
flag.String(logLevelFlag, "info", "log level")
flag.String(listenAddressFlag, ":9090", "The address to listen on for HTTP requests.")
flag.Duration(prodInfRenewalIntervalFlag, 24*time.Hour, "Duration (in go syntax) between renewing the ec2 product info. Example: 2h30m")
flag.String(prometheusAddressFlag, "", "http address of a Prometheus instance that has AWS spot price metrics via banzaicloud/spot-price-exporter. If empty, the recommender will use current spot prices queried directly from the AWS API.")
flag.String(prometheusQueryFlag, "avg_over_time(aws_spot_current_price{region=\"%s\", product_description=\"Linux/UNIX\"}[1w])", "advanced configuration: change the query used to query spot price info from Prometheus.")
flag.Bool(devModeFlag, false, "advanced configuration - development mode, no auth")
flag.String(listenAddressFlag, ":9090", "the address the telescope listens to HTTP requests.")
flag.Duration(prodInfRenewalIntervalFlag, 24*time.Hour, "duration (in go syntax) between renewing the product information. Example: 2h30m")
flag.String(prometheusAddressFlag, "", "http address of a Prometheus instance that has AWS spot "+
"price metrics via banzaicloud/spot-price-exporter. If empty, the recommender will use current spot prices queried directly from the AWS API.")
flag.String(prometheusQueryFlag, "avg_over_time(aws_spot_current_price{region=\"%s\", product_description=\"Linux/UNIX\"}[1w])",
"advanced configuration: change the query used to query spot price info from Prometheus.")
flag.Bool(devModeFlag, false, "development mode, if true token based authentication is disabled, false by default")
flag.String(gceProjectIdFlag, "", "GCE project ID to use")
flag.String(gceApiKeyFlag, "", "GCE API key to use for getting SKUs")
flag.StringSlice(providerFlag, []string{recommender.Ec2, recommender.Gce}, "Providers that will be used with the recommender.")
flag.String(tokenSigningKeyFlag, "", "The token signing key for the authentication process")
flag.String(vaultAddrFlag, "", "The vault address for authentication token management")
flag.Bool(helpFlag, false, "prints this help")
flag.StringSlice(providerFlag, []string{recommender.Ec2, recommender.Gce}, "cloud providers to be used for recommendation")
flag.String(tokenSigningKeyFlag, "", "string representing a shared secret with the token emitter component")
flag.String(vaultAddrFlag, "", "the vault address for authentication token management, not used in development mode")
flag.Bool(helpFlag, false, "print usage")
}

// bindFlags binds parsed flags into viper
Expand Down Expand Up @@ -105,9 +109,6 @@ func init() {
// set configuration defaults
viper.SetDefault(cfgAppRole, defaultAppRole)

// set configuration aliases
viper.RegisterAlias("vault_addr", vaultAddrFlag)

}

// ensureCfg ensures that the application configuration is available
Expand All @@ -122,9 +123,27 @@ func ensureCfg() {
// read the env var value
if nil == viper.Get(envVar) {
flag.Usage()
log.Fatalf("application is missing configuration: %s \n %s", envVar)
log.Fatalf("application is missing configuration: %s", envVar)
}
}

// translating flags to aliases for supporting legacy env vars
sitchFlagsToAliases()

}

// sitchFlagsToAliases sets the environment variables required by legacy components from application flags
// todo investigate if there's a better way for this
func sitchFlagsToAliases() {
// vault signing token hack / need to support legacy components (vault, auth)
os.Setenv(strings.ToUpper(vaultAddrAlias), viper.GetString(vaultAddrFlag))
os.Setenv(strings.ToUpper(tokenSigningKeyAlias), viper.GetString(tokenSigningKeyFlag))
viper.BindEnv(vaultAddrAlias)
viper.BindEnv(tokenSigningKeyAlias)
log.Debugf("%s : %s", vaultAddrFlag, viper.Get(vaultAddrFlag))
log.Debugf("%s : %s", tokenSigningKeyFlag, viper.Get(tokenSigningKeyFlag))
log.Debugf("%s : %s", vaultAddrAlias, viper.Get(vaultAddrAlias))
log.Debugf("%s : %s", tokenSigningKeyAlias, viper.Get(tokenSigningKeyAlias))
}

func main() {
Expand Down Expand Up @@ -157,7 +176,7 @@ func main() {
// enable authentication if not dev-mode
if !viper.GetBool(devModeFlag) {
log.Debug("enable authentication")
signingKey := viper.GetString(tokenSigningKeyFlag)
signingKey := viper.GetString(tokenSigningKeyAlias)
appRole := viper.GetString(cfgAppRole)

routeHandler.EnableAuth(router, appRole, signingKey)
Expand Down