Skip to content

Commit

Permalink
config: Convert config files from HCL to TOML
Browse files Browse the repository at this point in the history
Switch to using TOML format for the config files as the first step
of rehauling the Config setup.  TOML provides better viper support and is
closer to the standard git config file format.

HCL format is broken in viper and requires a small hack to convert double
square brackets to single square brackets in the viper TOML file format.

The test code extensively uses HCL and employs several viper HCL
workarounds.  The test code has been modified to remove HCL code and those
workarounds.

Before this change the ~/.config/lab.hcl contains

"core" = {
  "host" = "https://gitlab.com"

  "token" = "abcdef12345"

  "user" = "prarit"
}

After this change the ~/.config/lab/lab.toml contains

[core]
  host = "https://gitlab.com"
  token = "abcdef12345"
  user = "prarit"

Also move the new config files into their own directories in
~/.config and the local .git.

Convert config files from HCL to TOML and move them into their own
~/.config/lab and .git/lab/ directories.

Signed-off-by: Prarit Bhargava <[email protected]>
  • Loading branch information
prarit committed Sep 4, 2020
1 parent eae04b7 commit 44d164e
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 44 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
58 changes: 58 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package config

import (
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"net/url"
"os"
"strings"
Expand Down Expand Up @@ -86,3 +89,58 @@ 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"

_, err := os.Stat(oldconfig)
if os.IsNotExist(err) {
fmt.Println("oldfile not found", oldconfig)
return
}

_, err = os.Stat(newconfig)
if err == nil {
fmt.Println("newfile found", newconfig)
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
err = os.Remove(oldconfig)
if 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)
}
28 changes: 14 additions & 14 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestNewConfig(t *testing.T) {
readPassword = oldreadPassword
}()

err := New(path.Join(testconf, "lab.hcl"), &buf)
err := New(path.Join(testconf, "lab.toml"), &buf)
if err != nil {
t.Fatal(err)
}
Expand All @@ -58,7 +58,7 @@ func TestNewConfig(t *testing.T) {
assert.Contains(t, out, "Enter GitLab host (default: https://gitlab.com): ")
assert.Contains(t, out, "Create a token here: https://gitlab.zaquestion.io/profile/personal_access_tokens\nEnter default GitLab token (scope: api):")

cfg, err := os.Open(path.Join(testconf, "lab.hcl"))
cfg, err := os.Open(path.Join(testconf, "lab.toml"))
if err != nil {
t.Fatal(err)
}
Expand All @@ -67,11 +67,11 @@ func TestNewConfig(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, `"core" = {
"host" = "https://gitlab.zaquestion.io"
"token" = "abcde12345"
}`, string(cfgData))
assert.Equal(t, `
[core]
host = "https://gitlab.zaquestion.io"
token = "abcde12345"
`, string(cfgData))
})
os.RemoveAll(testconf)
viper.Reset()
Expand Down Expand Up @@ -105,7 +105,7 @@ func TestNewConfigHostOverride(t *testing.T) {
}()

var buf bytes.Buffer
err := New(path.Join(testconf, "lab.hcl"), &buf)
err := New(path.Join(testconf, "lab.toml"), &buf)
if err != nil {
t.Fatal(err)
}
Expand All @@ -126,7 +126,7 @@ func TestNewConfigHostOverride(t *testing.T) {
assert.NotContains(t, out, "Enter GitLab host")
assert.Contains(t, out, "Create a token here: https://gitlab2.zaquestion.io/profile/personal_access_tokens\nEnter default GitLab token (scope: api):")

cfg, err := os.Open(path.Join(testconf, "lab.hcl"))
cfg, err := os.Open(path.Join(testconf, "lab.toml"))
if err != nil {
t.Fatal(err)
}
Expand All @@ -135,11 +135,11 @@ func TestNewConfigHostOverride(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, `"core" = {
"host" = "https://gitlab2.zaquestion.io"
"token" = "abcde12345"
}`, string(cfgData))
assert.Equal(t, `
[core]
host = "https://gitlab2.zaquestion.io"
token = "abcde12345"
`, string(cfgData))
})
os.RemoveAll(testconf)
viper.Reset()
Expand Down
10 changes: 5 additions & 5 deletions internal/gitlab/gitlab_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ func TestMain(m *testing.M) {
}

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]
host := viper.GetString("core.host")
token := viper.GetString("core.token")

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

Init(config["host"].(string), u.Username, config["token"].(string), false)
Init(host, u.Username, token, false)

code := m.Run()

Expand Down
28 changes: 20 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,29 @@ func loadConfig() (string, string, string, bool) {
if confpath == "" {
confpath = path.Join(home, ".config")
}
if _, err := os.Stat(confpath); os.IsNotExist(err) {
os.Mkdir(confpath, 0700)
labconfpath := confpath+"/lab"
if _, err := os.Stat(labconfpath); os.IsNotExist(err) {
os.MkdirAll(labconfpath, 0700)
}

viper.SetConfigName("lab")
viper.SetConfigType("hcl")
viper.AddConfigPath(".")
viper.AddConfigPath(confpath)
// convert old hcl files to toml format

config.ConvertHCLtoTOML(".", ".", "lab")
config.ConvertHCLtoTOML(confpath, labconfpath, "lab")
var labgitDir string
gitDir, err := git.GitDir()
if err == nil {
viper.AddConfigPath(gitDir)
labgitDir = gitDir+"/lab"
config.ConvertHCLtoTOML(gitDir, labgitDir, "lab")
config.ConvertHCLtoTOML(labgitDir, labgitDir, "show_metadata")
}

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

viper.SetEnvPrefix("LAB")
Expand All @@ -66,7 +78,7 @@ func loadConfig() (string, string, string, bool) {
}

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

Expand Down
4 changes: 0 additions & 4 deletions testdata/lab.hcl

This file was deleted.

3 changes: 3 additions & 0 deletions testdata/lab.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[core]
host = "https://gitlab.com"
token = "uDz6czYV412zK-xC5mUu"

0 comments on commit 44d164e

Please sign in to comment.