Skip to content

Commit 2d147e9

Browse files
authored
Merge pull request #71 from rgeyer/config-opts
Make config externally settable without environment variables.
2 parents 831b724 + 4bf412d commit 2d147e9

3 files changed

Lines changed: 137 additions & 70 deletions

File tree

config/config.go

Lines changed: 129 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package config
22

33
import (
4-
"fmt"
54
"io/ioutil"
5+
"net/url"
6+
"path"
67
"strings"
78

89
log "github.com/sirupsen/logrus"
@@ -15,14 +16,12 @@ import (
1516
// Config struct holds all of the runtime confgiguration for the application
1617
type Config struct {
1718
*cfg.BaseConfig
18-
APIURL string
19-
Repositories string
20-
Organisations string
21-
Users string
22-
APITokenEnv string
23-
APITokenFile string
24-
APIToken string
25-
TargetURLs []string
19+
apiUrl *url.URL
20+
repositories []string
21+
organisations []string
22+
users []string
23+
apiToken string
24+
targetURLs []string
2625
}
2726

2827
// Init populates the Config struct based on environmental runtime configuration
@@ -31,88 +30,156 @@ func Init() Config {
3130
listenPort := cfg.GetEnv("LISTEN_PORT", "9171")
3231
os.Setenv("LISTEN_PORT", listenPort)
3332
ac := cfg.Init()
34-
url := cfg.GetEnv("API_URL", "https://api.github.com")
33+
34+
appConfig := Config{
35+
&ac,
36+
nil,
37+
nil,
38+
nil,
39+
nil,
40+
"",
41+
nil,
42+
}
43+
44+
err := appConfig.SetAPIURL(cfg.GetEnv("API_URL", "https://api.github.com"))
45+
if err != nil {
46+
log.Errorf("Error initialising Configuration. Unable to parse API URL. Error: %v", err)
47+
}
3548
repos := os.Getenv("REPOS")
49+
if repos != "" {
50+
appConfig.SetRepositories(strings.Split(repos, ", "))
51+
}
3652
orgs := os.Getenv("ORGS")
53+
if orgs != "" {
54+
appConfig.SetOrganisations(strings.Split(repos, ", "))
55+
}
3756
users := os.Getenv("USERS")
57+
if users != "" {
58+
appConfig.SetUsers(strings.Split(users, ", "))
59+
}
3860
tokenEnv := os.Getenv("GITHUB_TOKEN")
3961
tokenFile := os.Getenv("GITHUB_TOKEN_FILE")
40-
token, err := getAuth(tokenEnv, tokenFile)
41-
scraped, err := getScrapeURLs(url, repos, orgs, users)
42-
43-
if err != nil {
44-
log.Errorf("Error initialising Configuration, Error: %v", err)
45-
}
46-
47-
appConfig := Config{
48-
&ac,
49-
url,
50-
repos,
51-
orgs,
52-
users,
53-
tokenEnv,
54-
tokenFile,
55-
token,
56-
scraped,
62+
if tokenEnv != "" {
63+
appConfig.SetAPIToken(tokenEnv)
64+
} else if tokenFile != "" {
65+
err = appConfig.SetAPITokenFromFile(tokenFile)
66+
if err != nil {
67+
log.Errorf("Error initialising Configuration, Error: %v", err)
68+
}
5769
}
5870

5971
return appConfig
6072
}
6173

74+
// Returns the base APIURL
75+
func (c *Config) APIURL() *url.URL {
76+
return c.apiUrl
77+
}
78+
79+
// Returns a list of all object URLs to scrape
80+
func (c *Config) TargetURLs() []string {
81+
return c.targetURLs
82+
}
83+
84+
// Returns the oauth2 token for usage in http.request
85+
func (c *Config) APIToken() string {
86+
return c.apiToken
87+
}
88+
89+
// Sets the base API URL returning an error if the supplied string is not a valid URL
90+
func (c *Config) SetAPIURL(u string) error {
91+
ur, err := url.Parse(u)
92+
c.apiUrl = ur
93+
return err
94+
}
95+
96+
// Overrides the entire list of repositories
97+
func (c *Config) SetRepositories(repos []string) {
98+
c.repositories = repos
99+
c.setScrapeURLs()
100+
}
101+
102+
// Overrides the entire list of organisations
103+
func (c *Config) SetOrganisations(orgs []string) {
104+
c.organisations = orgs
105+
c.setScrapeURLs()
106+
}
107+
108+
// Overrides the entire list of users
109+
func (c *Config) SetUsers(users []string) {
110+
c.users = users
111+
c.setScrapeURLs()
112+
}
113+
114+
// SetAPIToken accepts a string oauth2 token for usage in http.request
115+
func (c *Config) SetAPIToken(token string) {
116+
c.apiToken = token
117+
}
118+
119+
// SetAPITokenFromFile accepts a file containing an oauth2 token for usage in http.request
120+
func (c *Config) SetAPITokenFromFile(tokenFile string) error {
121+
b, err := ioutil.ReadFile(tokenFile)
122+
if err != nil {
123+
return err
124+
}
125+
c.apiToken = strings.TrimSpace(string(b))
126+
return nil
127+
}
128+
62129
// Init populates the Config struct based on environmental runtime configuration
63130
// All URL's are added to the TargetURL's string array
64-
func getScrapeURLs(apiURL, repos, orgs, users string) ([]string, error) {
131+
func (c *Config) setScrapeURLs() error {
65132

66133
urls := []string{}
67134

68-
opts := "?&per_page=100" // Used to set the Github API to return 100 results per page (max)
135+
opts := map[string]string{"per_page": "100"} // Used to set the Github API to return 100 results per page (max)
69136

70-
if len(repos) == 0 && len(orgs) == 0 && len(users) == 0 {
137+
if len(c.repositories) == 0 && len(c.organisations) == 0 && len(c.users) == 0 {
71138
log.Info("No targets specified. Only rate limit endpoint will be scraped")
72139
}
73140

74141
// Append repositories to the array
75-
if repos != "" {
76-
rs := strings.Split(repos, ", ")
77-
for _, x := range rs {
78-
y := fmt.Sprintf("%s/repos/%s%s", apiURL, x, opts)
79-
urls = append(urls, y)
142+
if len(c.repositories) > 0 {
143+
for _, x := range c.repositories {
144+
y := *c.apiUrl
145+
y.Path = path.Join(y.Path, "repos", x)
146+
q := y.Query()
147+
for k, v := range opts {
148+
q.Add(k, v)
149+
}
150+
y.RawQuery = q.Encode()
151+
urls = append(urls, y.String())
80152
}
81153
}
82154

83155
// Append github orginisations to the array
84-
if orgs != "" {
85-
o := strings.Split(orgs, ", ")
86-
for _, x := range o {
87-
y := fmt.Sprintf("%s/orgs/%s/repos%s", apiURL, x, opts)
88-
urls = append(urls, y)
156+
if len(c.organisations) > 0 {
157+
for _, x := range c.organisations {
158+
y := *c.apiUrl
159+
y.Path = path.Join(y.Path, "orgs", x, "repos")
160+
q := y.Query()
161+
for k, v := range opts {
162+
q.Add(k, v)
163+
}
164+
y.RawQuery = q.Encode()
165+
urls = append(urls, y.String())
89166
}
90167
}
91168

92-
if users != "" {
93-
us := strings.Split(users, ", ")
94-
for _, x := range us {
95-
y := fmt.Sprintf("%s/users/%s/repos%s", apiURL, x, opts)
96-
urls = append(urls, y)
169+
if len(c.users) > 0 {
170+
for _, x := range c.users {
171+
y := *c.apiUrl
172+
y.Path = path.Join(y.Path, "users", x, "repos")
173+
q := y.Query()
174+
for k, v := range opts {
175+
q.Add(k, v)
176+
}
177+
y.RawQuery = q.Encode()
178+
urls = append(urls, y.String())
97179
}
98180
}
99181

100-
return urls, nil
101-
}
102-
103-
// getAuth returns oauth2 token as string for usage in http.request
104-
func getAuth(token string, tokenFile string) (string, error) {
105-
106-
if token != "" {
107-
return token, nil
108-
} else if tokenFile != "" {
109-
b, err := ioutil.ReadFile(tokenFile)
110-
if err != nil {
111-
return "", err
112-
}
113-
return strings.TrimSpace(string(b)), err
114-
115-
}
182+
c.targetURLs = urls
116183

117-
return "", nil
184+
return nil
118185
}

exporter/gather.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package exporter
33
import (
44
"encoding/json"
55
"fmt"
6+
"path"
67
"strconv"
78
"strings"
89

@@ -14,7 +15,7 @@ func (e *Exporter) gatherData() ([]*Datum, error) {
1415

1516
data := []*Datum{}
1617

17-
responses, err := asyncHTTPGets(e.TargetURLs, e.APIToken)
18+
responses, err := asyncHTTPGets(e.TargetURLs(), e.APIToken())
1819

1920
if err != nil {
2021
return data, err
@@ -54,11 +55,10 @@ func (e *Exporter) gatherData() ([]*Datum, error) {
5455
// getRates obtains the rate limit data for requests against the github API.
5556
// Especially useful when operating without oauth and the subsequent lower cap.
5657
func (e *Exporter) getRates() (*RateLimits, error) {
58+
u := *e.APIURL()
59+
u.Path = path.Join(u.Path, "rate_limit")
5760

58-
rateEndPoint := ("/rate_limit")
59-
url := fmt.Sprintf("%s%s", e.APIURL, rateEndPoint)
60-
61-
resp, err := getHTTPResponse(url, e.APIToken)
61+
resp, err := getHTTPResponse(u.String(), e.APIToken())
6262
if err != nil {
6363
return &RateLimits{}, err
6464
}
@@ -99,7 +99,7 @@ func getReleases(e *Exporter, url string, data *[]Release) {
9999
i := strings.Index(url, "?")
100100
baseURL := url[:i]
101101
releasesURL := baseURL + "/releases"
102-
releasesResponse, err := asyncHTTPGets([]string{releasesURL}, e.APIToken)
102+
releasesResponse, err := asyncHTTPGets([]string{releasesURL}, e.APIToken())
103103

104104
if err != nil {
105105
log.Errorf("Unable to obtain releases from API, Error: %s", err)
@@ -112,7 +112,7 @@ func getPRs(e *Exporter, url string, data *[]Pull) {
112112
i := strings.Index(url, "?")
113113
baseURL := url[:i]
114114
pullsURL := baseURL + "/pulls"
115-
pullsResponse, err := asyncHTTPGets([]string{pullsURL}, e.APIToken)
115+
pullsResponse, err := asyncHTTPGets([]string{pullsURL}, e.APIToken())
116116

117117
if err != nil {
118118
log.Errorf("Unable to obtain pull requests from API, Error: %s", err)

exporter/prometheus.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
2121
data := []*Datum{}
2222
var err error
2323
// Scrape the Data from Github
24-
if len(e.TargetURLs) > 0 {
24+
if len(e.TargetURLs()) > 0 {
2525
data, err = e.gatherData()
2626
if err != nil {
2727
log.Errorf("Error gathering Data from remote API: %v", err)

0 commit comments

Comments
 (0)