Skip to content

Commit

Permalink
Merge pull request #414 from prarit/new_config_layout
Browse files Browse the repository at this point in the history
New config layout

This changeset converts the existing HCL formatted config files to TOML, and moves them into their own global .config/lab and local .git/lab directories.  There are no changes to the default behaviour of the config files themselves.
  • Loading branch information
prarit authored Sep 6, 2020
2 parents eae04b7 + 6d8163f commit 084623b
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 217 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ os:
- linux

go:
- 1.13.x
- 1.15.x

# use containers which run faster and have cache
sudo: false
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Head to the [releases](https://github.com/zaquestion/lab/releases) page and down
### Source

Required
* [Go 1.13+](https://golang.org/doc/install)
* [Go 1.15+](https://golang.org/doc/install)

```
git clone git@github.com:zaquestion/lab
Expand All @@ -89,11 +89,11 @@ instance. There are several ways to provide this information to `lab`:
1. environment variables: `LAB_CORE_HOST`, `LAB_CORE_TOKEN`;
2. environment variables: `CI_PROJECT_URL`, `CI_JOB_TOKEN`;
- Note: these are meant for when `lab` is running within a GitLab CI pipeline
3. directory-specific configuration file in [HashiCorp configuration language (HCL)](https://github.com/hashicorp/hcl): `./lab.hcl`;
4. user-specific configuration file in HCL: `~/.config/lab.hcl`.
3. directory-specific configuration file in [Tom's Obvious, Minimal Language (TOML)](https://github.com/toml-lang/toml): `./lab.toml`;
4. user-specific configuration file in HCL: `~/.config/lab/lab.toml`.

These are checked in order. If no suitable config values are found, `lab` will
prompt for your GitLab information and save it into `~/.config/lab.hcl`.
prompt for your GitLab information and save it into `~/.config/lab/lab.toml`.
For example:
```
$ lab
Expand Down
4 changes: 2 additions & 2 deletions cmd/issue_show.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,12 @@ func printDiscussions(discussions []*gitlab.Discussion, since string, issueNum i
NewAccessTime := time.Now().UTC()

// default path for metadata config file
metadatafile := ".git/lab/show_metadata.hcl"
metadatafile := ".git/lab/show_metadata.toml"

viper.Reset()
viper.AddConfigPath(".git/lab")
viper.SetConfigName("show_metadata")
viper.SetConfigType("hcl")
viper.SetConfigType("toml")
// write data
if _, ok := viper.ReadInConfig().(viper.ConfigFileNotFoundError); ok {
if _, err := os.Stat(".git/lab"); os.IsNotExist(err) {
Expand Down
4 changes: 2 additions & 2 deletions cmd/mr_show.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,12 @@ func printMRDiscussions(discussions []*gitlab.Discussion, since string, mrNum in
NewAccessTime := time.Now().UTC()

// default path for metadata config file
metadatafile := ".git/lab/show_metadata.hcl"
metadatafile := ".git/lab/show_metadata.toml"

viper.Reset()
viper.AddConfigPath(".git/lab")
viper.SetConfigName("show_metadata")
viper.SetConfigType("hcl")
viper.SetConfigType("toml")
// write data
if _, ok := viper.ReadInConfig().(viper.ConfigFileNotFoundError); ok {
if _, err := os.Stat(".git/lab"); os.IsNotExist(err) {
Expand Down
11 changes: 6 additions & 5 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,21 @@ func TestMain(m *testing.M) {
}
// Load config for non-testbinary based tests
viper.SetConfigName("lab")
viper.SetConfigType("hcl")
viper.SetConfigType("toml")
viper.AddConfigPath(".")
err = viper.ReadInConfig()
if err != nil {
log.Fatal(err)
}
c := viper.AllSettings()["core"]
config := c.([]map[string]interface{})[0]
client, _ := gitlab.NewClient(config["token"].(string), gitlab.WithBaseURL(config["host"].(string)+"/api/v4"))
host := viper.GetString("core.host")
token := viper.GetString("core.token")

client, _ := gitlab.NewClient(token, gitlab.WithBaseURL(host+"/api/v4"))
u, _, err := client.Users.CurrentUser()
if err != nil {
log.Fatal(err)
}
lab.Init(config["host"].(string), u.Username, config["token"].(string), false)
lab.Init(host, u.Username, token, false)

code := m.Run()

Expand Down
2 changes: 1 addition & 1 deletion cmd/snippet_browse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

func Test_snippetBrowse(t *testing.T) {
viper.SetConfigName("lab")
viper.SetConfigType("hcl")
viper.SetConfigType("toml")
viper.AddConfigPath("../testdata")
err := viper.ReadInConfig()
if err != nil {
Expand Down
156 changes: 156 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@ package config

import (
"bufio"
"bytes"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"path"
"strings"
"syscall"

"github.com/spf13/viper"
gitlab "github.com/xanzy/go-gitlab"
"github.com/zaquestion/lab/internal/git"
"golang.org/x/crypto/ssh/terminal"
)

Expand Down Expand Up @@ -86,3 +94,151 @@ func CI() (string, string, string) {

return ciHost, ciUser, ciToken
}

// ConvertHCLtoTOML() converts an .hcl file to a .toml file
func ConvertHCLtoTOML(oldpath string, newpath string, file string) {
oldconfig := oldpath + "/" + file + ".hcl"
newconfig := newpath + "/" + file + ".toml"

if _, err := os.Stat(oldconfig); os.IsNotExist(err) {
return
}

if _, err := os.Stat(newconfig); err == nil {
return
}

// read in the old config HCL file and write out the new TOML file
viper.Reset()
viper.SetConfigName("lab")
viper.SetConfigType("hcl")
viper.AddConfigPath(oldpath)
viper.ReadInConfig()
viper.SetConfigType("toml")
viper.WriteConfigAs(newconfig)

// delete the old config HCL file
if err := os.Remove(oldconfig); err != nil {
fmt.Println("Warning: Could not delete old config file", oldconfig)
}

// HACK
// viper HCL parsing is broken and simply translating it to a TOML file
// results in a broken toml file. The issue is that there are double
// square brackets for each entry where there should be single
// brackets. Note: this hack only works because the config file is
// simple and doesn't contain deeply embedded config entries.
text, err := ioutil.ReadFile(newconfig)
if err != nil {
log.Fatal(err)
}

text = bytes.Replace(text, []byte("[["), []byte("["), -1)
text = bytes.Replace(text, []byte("]]"), []byte("]"), -1)

if err = ioutil.WriteFile(newconfig, text, 0666); err != nil {
fmt.Println(err)
os.Exit(1)
}
// END HACK

fmt.Println("INFO: Converted old config", oldconfig, "to new config", newconfig)
}

func getUser(host, token string, skipVerify bool) string {
httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: skipVerify,
},
},
}
lab, _ := gitlab.NewClient(token, gitlab.WithHTTPClient(httpClient), gitlab.WithBaseURL(host+"/api/v4"))
u, _, err := lab.Users.CurrentUser()
if err != nil {
log.Fatal(err)
}
return u.Username
}

// LoadConfig() loads the main config file and returns a tuple of
// host, user, token, ca_file, skipVerify
func LoadConfig() (string, string, string, string, bool) {

// Attempt to auto-configure for GitLab CI.
// Always do this before reading in the config file o/w CI will end up
// with the wrong data.
host, user, token := CI()
if host != "" && user != "" && token != "" {
return host, user, token, "", false
}

// Try to find XDG_CONFIG_HOME which is declared in XDG base directory
// specification and use it's location as the config directory
home, err := os.UserHomeDir()
if err != nil {
log.Fatal(err)
}
confpath := os.Getenv("XDG_CONFIG_HOME")
if confpath == "" {
confpath = path.Join(home, ".config")
}
labconfpath := confpath + "/lab"
if _, err := os.Stat(labconfpath); os.IsNotExist(err) {
os.MkdirAll(labconfpath, 0700)
}

// Convert old hcl files to toml format.
// NO NEW FILES SHOULD BE ADDED BELOW.
ConvertHCLtoTOML(confpath, labconfpath, "lab")
ConvertHCLtoTOML(".", ".", "lab")
var labgitDir string
gitDir, err := git.GitDir()
if err == nil {
labgitDir = gitDir + "/lab"
ConvertHCLtoTOML(gitDir, labgitDir, "lab")
ConvertHCLtoTOML(labgitDir, labgitDir, "show_metadata")
}

viper.SetConfigName("lab")
viper.SetConfigType("toml")
viper.AddConfigPath(".")
viper.AddConfigPath(labconfpath)
if labgitDir != "" {
viper.AddConfigPath(labgitDir)
}

viper.SetEnvPrefix("LAB")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()

if _, ok := viper.ReadInConfig().(viper.ConfigFileNotFoundError); ok {
err := New(path.Join(labconfpath, "lab.toml"), os.Stdin)
if err != nil {
log.Fatal(err)
}

err = viper.ReadInConfig()
if err != nil {
log.Fatal(err)
}
}

host = viper.GetString("core.host")
user = viper.GetString("core.user")
token = viper.GetString("core.token")
tlsSkipVerify := viper.GetBool("tls.skip_verify")
ca_file := viper.GetString("tls.ca_file")

if host != "" && user != "" && token != "" {
return host, user, token, ca_file, tlsSkipVerify
}

user = getUser(host, token, tlsSkipVerify)
if strings.TrimSpace(os.Getenv("LAB_CORE_TOKEN")) == "" && strings.TrimSpace(os.Getenv("LAB_CORE_HOST")) == "" {
viper.Set("core.user", user)
viper.WriteConfig()
}

return host, user, token, ca_file, tlsSkipVerify
}
Loading

0 comments on commit 084623b

Please sign in to comment.