Skip to content

Commit

Permalink
Initial code commit
Browse files Browse the repository at this point in the history
  • Loading branch information
amaloy committed Sep 8, 2018
1 parent 374c09d commit add57f9
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# trickster2grafana

Reads origins from a [Trickster](https://github.com/Comcast/trickster) configuration file and POSTs respective datasources to Grafana.

Useful when you have a [multi-origin](https://github.com/Comcast/trickster/blob/master/docs/multi-origin.mdP) Trickster configuration so you don't have to create several Grafana datasources manually.

Only supports the HTTP Pathing multi-origin strategy at this time.

## Example
```
trickster2grafana -grafana-key <your-api-key> -grafana-url http://grafana:3000 -trickster-conf /etc/trickster/trickster.conf -trickster-url http://trickster:9090
```
32 changes: 32 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"flag"
"os"
)

// Contains application configuration
type config struct {
tricksterConf string
tricksterURL string
grafanaURL string
grafanaKey string
}

func (c *config) loadFromFlags() {
f := flag.NewFlagSet(applicationName, flag.ExitOnError)
f.StringVar(&c.tricksterConf, "trickster-conf", "", "Path to the Trickster conf file")
f.StringVar(&c.tricksterURL, "trickster-url", "", "Base URL for accessing Trickster")
f.StringVar(&c.grafanaURL, "grafana-url", "", "Grafana API URL")
f.StringVar(&c.grafanaKey, "grafana-key", "", "Grafana API key")
f.Parse(os.Args[1:])

// Validate
if len(c.tricksterConf) == 0 ||
len(c.tricksterURL) == 0 ||
len(c.grafanaURL) == 0 ||
len(c.grafanaKey) == 0 {
f.Usage()
os.Exit(2)
}
}
57 changes: 57 additions & 0 deletions grafana.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package main

import (
"fmt"

"github.com/grafana-tools/sdk"
)

func grafanaPostDatasources(c *config, resolvedValues []*resolved) error {
fmt.Println()
fmt.Printf("Going to create these Grafana datasources on %s :", c.grafanaURL)
fmt.Println()
fmt.Println()
for _, r := range resolvedValues {
fmt.Printf(" NAME: %s URL: %s", r.id, r.url)
fmt.Println()
}
fmt.Println()
fmt.Println("Is this OK? Press enter to continue or Ctrl-C to abort...")
fmt.Scanln()

grafana := sdk.NewClient(c.grafanaURL, c.grafanaKey, sdk.DefaultHTTPClient)
existingDatasources, err := grafana.GetAllDatasources()
if err != nil {
return err
}

for _, r := range resolvedValues {
fmt.Printf("%s... ", r.id)

exists := false
for _, ds := range existingDatasources {
if ds.Name == r.id {
exists = true
break
}
}
if exists {
fmt.Print("Already exists, skipping")
} else {
var newDS sdk.Datasource
newDS.Name = r.id
newDS.Type = "prometheus"
newDS.URL = r.url
newDS.Access = "proxy"
msg, err := grafana.CreateDatasource(newDS)
if err != nil {
return err
}
fmt.Printf(*msg.Message)
}
fmt.Println()
}

fmt.Println("Done!")
return nil
}
31 changes: 31 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

const (
applicationName = "trickster2grafana"
applicationVersion = "0.0.1"
)

func main() {
// Load config from flags
config := new(config)
config.loadFromFlags()

// Load Trickster config
tricksterConfig := new(tricksterConfig)
err := tricksterConfig.loadFile(config.tricksterConf)
if err != nil {
panic(err)
}

// Get resolved values
resolvedValues, err := resolveHTTPPathing(config, tricksterConfig)
if err != nil {
panic(err)
}

// Send to Grafana
err = grafanaPostDatasources(config, resolvedValues)
if err != nil {
panic(err)
}
}
31 changes: 31 additions & 0 deletions resolve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"net/url"
"path"
)

// resolved contains values that are ready for output (e.g. to Grafana)
type resolved struct {
id string
url string
}

// Resolve for Tricker's HTTP Pathing multi-origin strategy
func resolveHTTPPathing(c *config, tc *tricksterConfig) ([]*resolved, error) {
all := make([]*resolved, 0)
for origin := range tc.Origins {
r := new(resolved)
r.id = origin

u, err := url.Parse(c.tricksterURL)
if err != nil {
return nil, err
}
u.Path = path.Join(u.Path, r.id)
r.url = u.String()

all = append(all, r)
}
return all, nil
}
22 changes: 22 additions & 0 deletions trickster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

import (
"github.com/BurntSushi/toml"
)

type tricksterConfig struct {
Origins map[string]prometheusOriginConfig `toml:"origins"`
}

type prometheusOriginConfig struct {
OriginURL string `toml:"origin_url"`
APIPath string `toml:"api_path"`
IgnoreNoCacheHeader bool `toml:"ignore_no_cache_header"`
MaxValueAgeSecs int64 `toml:"max_value_age_secs"`
FastForwardDisable bool `toml:"fast_forward_disable"`
}

func (c *tricksterConfig) loadFile(path string) error {
_, err := toml.DecodeFile(path, &c)
return err
}

0 comments on commit add57f9

Please sign in to comment.