-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ability of full configuration via env variables
Implements #1
- Loading branch information
Showing
6 changed files
with
245 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
type Config struct { | ||
GitLab struct { | ||
URL string `yaml:"url"` | ||
Token string `yaml:"token"` | ||
} `yaml:"gitlab"` | ||
Slack struct { | ||
WebhookURL string `yaml:"webhook_url"` | ||
} `yaml:"slack"` | ||
Projects []ConfigProject | ||
Groups []ConfigGroup | ||
} | ||
|
||
type ConfigGroup struct { | ||
ID int `yaml:"id"` | ||
} | ||
|
||
type ConfigProject struct { | ||
ID int `yaml:"id"` | ||
} | ||
|
||
type Env interface { | ||
Getenv(key string) string | ||
} | ||
|
||
type OsEnv struct{} | ||
|
||
func (e *OsEnv) Getenv(key string) string { | ||
return os.Getenv(key) | ||
} | ||
|
||
func loadConfig(env Env) (*Config, error) { | ||
configPath := env.Getenv("CONFIG_PATH") | ||
if configPath == "" { | ||
configPath = "config.yaml" | ||
} | ||
|
||
config := &Config{} | ||
var err error | ||
|
||
if _, err := os.Stat(configPath); err == nil { | ||
config, err = readConfig(configPath) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error reading configuration file: %v\n", err) | ||
} | ||
} | ||
|
||
if env := env.Getenv("PROJECTS"); env != "" { | ||
config.Projects, err = parseIDsAsConfigProjects(env) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error parsing PROJECTS environment variable: %v\n", err) | ||
} | ||
} | ||
|
||
if env := env.Getenv("GROUPS"); env != "" { | ||
config.Groups, err = parseIDsAsConfigGroups(env) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error parsing GROUPS environment variable: %v\n", err) | ||
} | ||
} | ||
|
||
gitlabURL := env.Getenv("GITLAB_URL") | ||
if gitlabURL != "" { | ||
config.GitLab.URL = gitlabURL | ||
} | ||
if config.GitLab.URL == "" { | ||
config.GitLab.URL = "https://gitlab.com" | ||
} | ||
|
||
gitlabToken := env.Getenv("GITLAB_TOKEN") | ||
if gitlabToken != "" { | ||
config.GitLab.Token = gitlabToken | ||
} | ||
if config.GitLab.Token == "" { | ||
return nil, fmt.Errorf("GITLAB_TOKEN environment variable is required") | ||
} | ||
|
||
slackWebhookURL := env.Getenv("SLACK_WEBHOOK_URL") | ||
if slackWebhookURL != "" { | ||
config.Slack.WebhookURL = slackWebhookURL | ||
} | ||
if config.Slack.WebhookURL == "" { | ||
return nil, fmt.Errorf("SLACK_WEBHOOK_URL environment variable is required") | ||
} | ||
|
||
if len(config.Projects) == 0 && len(config.Groups) == 0 { | ||
return nil, fmt.Errorf("Neither groups nor projects were provided") | ||
} | ||
|
||
return config, nil | ||
} | ||
|
||
func parseIDsAsConfigProjects(env string) ([]ConfigProject, error) { | ||
ids, err := parseIDs(env) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var projects []ConfigProject | ||
for _, id := range ids { | ||
projects = append(projects, ConfigProject{ID: id}) | ||
} | ||
|
||
return projects, nil | ||
} | ||
|
||
func parseIDsAsConfigGroups(env string) ([]ConfigGroup, error) { | ||
ids, err := parseIDs(env) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var groups []ConfigGroup | ||
for _, id := range ids { | ||
groups = append(groups, ConfigGroup{ID: id}) | ||
} | ||
|
||
return groups, nil | ||
} | ||
|
||
func parseIDs(env string) ([]int, error) { | ||
var ids []int | ||
for _, idStr := range strings.Split(env, ",") { | ||
id, err := strconv.Atoi(idStr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
ids = append(ids, id) | ||
} | ||
return ids, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
gitlab: | ||
url: https://gitlab.example.com | ||
token: abcdef1234567890 | ||
slack: | ||
webhook_url: https://hooks.slack.com/services/your-slack-webhook-url | ||
projects: | ||
- id: 123 | ||
- id: 456 | ||
groups: | ||
- id: 1 | ||
- id: 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package main | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
type MockEnv struct { | ||
values map[string]string | ||
} | ||
|
||
func (e *MockEnv) Getenv(key string) string { | ||
return e.values[key] | ||
} | ||
|
||
func TestLoadConfig(t *testing.T) { | ||
// Test default values and required environment variables | ||
t.Run("missing required env variables", func(t *testing.T) { | ||
env := &MockEnv{values: map[string]string{}} | ||
_, err := loadConfig(env) | ||
assert.Error(t, err) | ||
assert.Contains(t, err.Error(), "GITLAB_TOKEN environment variable is required") | ||
}) | ||
|
||
t.Run("default GitLab URL", func(t *testing.T) { | ||
env := &MockEnv{values: map[string]string{ | ||
"GITLAB_TOKEN": "token", | ||
"SLACK_WEBHOOK_URL": "webhook", | ||
"CONFIG_PATH": "NONEXISTING.yaml", | ||
"PROJECTS": "1,2,3", | ||
}} | ||
|
||
config, err := loadConfig(env) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "https://gitlab.com", config.GitLab.URL) | ||
}) | ||
|
||
// Test overriding default values with environment variables | ||
t.Run("env variables overriding defaults", func(t *testing.T) { | ||
env := &MockEnv{values: map[string]string{ | ||
"GITLAB_URL": "https://gitlab.example.com", | ||
"GITLAB_TOKEN": "token", | ||
"SLACK_WEBHOOK_URL": "webhook", | ||
"CONFIG_PATH": "NONEXISTING.yaml", | ||
"PROJECTS": "1,2,3", | ||
}} | ||
|
||
config, err := loadConfig(env) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "https://gitlab.example.com", config.GitLab.URL) | ||
assert.Equal(t, []ConfigProject{ | ||
{ID: 1}, | ||
{ID: 2}, | ||
{ID: 3}, | ||
}, config.Projects) | ||
}) | ||
|
||
// Test loading config from file | ||
t.Run("loading from config file", func(t *testing.T) { | ||
env := &MockEnv{values: map[string]string{ | ||
"CONFIG_PATH": "config.test.yaml", | ||
}} | ||
|
||
config, err := loadConfig(env) | ||
assert.NoError(t, err) | ||
|
||
assert.Equal(t, "https://gitlab.example.com", config.GitLab.URL) | ||
assert.Equal(t, "abcdef1234567890", config.GitLab.Token) | ||
assert.Equal(t, "https://hooks.slack.com/services/your-slack-webhook-url", config.Slack.WebhookURL) | ||
assert.Equal(t, []ConfigProject{ | ||
{ID: 123}, | ||
{ID: 456}, | ||
}, config.Projects) | ||
assert.Equal(t, []ConfigGroup{ | ||
{ID: 1}, | ||
{ID: 2}, | ||
}, config.Groups) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters