Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consul #159

Merged
merged 20 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -663,7 +663,7 @@ func main() {
| providers/vault | `vault.Provider(vault.Config{})` | Hashicorp Vault provider |
| providers/appconfig | `vault.AppConfig(appconfig.Config{})` | AWS AppConfig provider |
| providers/etcd | `etcd.Provider(etcd.Config{})` | CNCF etcd provider |
|
| providers/consul | `consul.Provider(consul.Config{})` | Hashicorp Consul provider |

### Bundled parsers

Expand Down
10 changes: 10 additions & 0 deletions examples/read-consul/data.json
@@ -0,0 +1,10 @@
{
"parent1": "father",
"parent2": "mother",
"child1": "Alex",
"child2": "Julia",
"child3": "Michael",
"child4": "Natalie",
"child5": "Rosalind",
"child6": "Tim"
}
27 changes: 27 additions & 0 deletions examples/read-consul/koanfconsul.sh
@@ -0,0 +1,27 @@
consul agent -dev &

exitcode=1
iterations=0

while [ $exitcode -ne 0 ]
do
consul members
exitcode=$?

sleep 1
((iterations++))

if [ $iterations -gt 5 ]; then
break
fi
done

if [ $exitcode -eq 0 ]; then
echo -e "\nTest program running..."
go run main.go
echo -e "\nShutdown..."
consul leave
else
echo "Consul server is inavailable."
consul leave
fi
299 changes: 299 additions & 0 deletions examples/read-consul/main.go
@@ -0,0 +1,299 @@
package main

import (
"fmt"
"log"
"os/exec"
"strings"

"github.com/hashicorp/consul/api"
"github.com/knadh/koanf"
"github.com/knadh/koanf/parsers/json"
"github.com/knadh/koanf/providers/consul"
"github.com/knadh/koanf/providers/file"
)

var (
kData = koanf.New(".")
kReq = koanf.New(".")
kCheck = koanf.New(".")
)

func main() {
if err := kData.Load(file.Provider("data.json"), json.Parser()); err != nil {
log.Fatalf("error loading config: %v", err)
}

cli, err := api.NewClient(api.DefaultConfig())
if err != nil {
log.Fatalf("error creating client: %v", err)
}

kv := cli.KV()

keysData := kData.Keys()
for _, key := range keysData {
newPair := &api.KVPair{Key: key, Value: []byte(kData.String(key))}
_, err = kv.Put(newPair, nil)

if err != nil {
log.Printf("Couldn't put key.")
}
}

// Single key/value.
var (
sKey string = "single_key"
sVal string = "single_val"
)

newPair := &api.KVPair{Key: sKey, Value: []byte(sVal)}
_, err = kv.Put(newPair, nil)

if err != nil {
log.Printf("Couldn't put key.")
}

provider := consul.Provider(consul.Config{
Key: sKey,
Recurse: false,
Detailed: false,
Cfg: api.DefaultConfig(),
})

if err := kCheck.Load(provider, nil); err != nil {
log.Fatalf("error loading config: %v", err)
}

if len(kCheck.Keys()) != 1 {
fmt.Printf("Single key: FAILED\n")
return
}

if strings.Compare(sKey, kCheck.Keys()[0]) != 0 {
fmt.Printf("Single key: key comparison FAILED\n")
return
}

if strings.Compare(sVal, kCheck.String(kCheck.Keys()[0])) != 0 {
fmt.Printf("Single key: value comparison FAILED\n")
return
}

fmt.Printf("\nSingle key test passed.\n")
kCheck.Delete("")

// first request test
// analog of the command:
// consul kv get -recurse parent

if err := kReq.Load(file.Provider("req1.json"), json.Parser()); err != nil {
log.Fatalf("error loading config: %v", err)
}

provider = consul.Provider(consul.Config{
Key: "parent",
Recurse: true,
Detailed: false,
Cfg: api.DefaultConfig(),
})

if err := kCheck.Load(provider, nil); err != nil {
log.Fatalf("error loading config: %v", err)
}

keysReq := kReq.Keys()
keysCheck := kCheck.Keys()

if len(keysReq) != len(keysCheck) {
fmt.Printf("First request: keys FAILED\n")
return
}

for i := 0; i < len(keysReq); i++ {
if strings.Compare(keysReq[i], keysCheck[i]) != 0 {
fmt.Printf("First request: key comparison FAILED\n")
return
}

if strings.Compare(kReq.String(keysReq[i]), kCheck.String(keysCheck[i])) != 0 {
fmt.Printf("First request: value comparison FAILED\n")
return
}
}

fmt.Printf("First request test passed.\n")
kReq.Delete("")
kCheck.Delete("")

// second request test
// analog of the command:
// consul kv get -recurse child

if err := kReq.Load(file.Provider("req2.json"), json.Parser()); err != nil {
log.Fatalf("error loading config: %v", err)
}

provider = consul.Provider(consul.Config{
Key: "child",
Recurse: true,
Detailed: false,
Cfg: api.DefaultConfig(),
})

if err := kCheck.Load(provider, nil); err != nil {
log.Fatalf("error loading config: %v", err)
}

keysReq = kReq.Keys()
keysCheck = kCheck.Keys()

if len(keysReq) != len(keysCheck) {
fmt.Printf("Second request: keys FAILED\n")
return
}

for i := 0; i < len(keysReq); i++ {
if strings.Compare(keysReq[i], keysCheck[i]) != 0 {
}

if strings.Compare(kReq.String(keysReq[i]), kCheck.String(keysCheck[i])) != 0 {
fmt.Printf("Second request: value comparison FAILED\n")
return
}
}

fmt.Printf("Second request test passed.\n")
kCheck.Delete("")

// adding metainformation: age (flags)
newPair = &api.KVPair{Key: "parent1", Flags: uint64(42), Value: []byte("father")}
_, err = kv.Put(newPair, nil)
if err != nil {
log.Printf("Couldn't put key with flags.")
}

// Single key detailed test.
// analog of the command:
// consul kv get -detailed parent1

sKey = "parent1"
sFlags := uint64(42)
sVal = "father"

provider = consul.Provider(consul.Config{
Key: sKey,
Recurse: false,
Detailed: true,
Cfg: api.DefaultConfig(),
})

if err := kCheck.Load(provider, nil); err != nil {
fmt.Printf("error loading config: %v", err)
return
}

if sFlags != uint64(kCheck.Int64("parent1.Flags")) {
fmt.Printf("Single detailed key: flags (metadata: age) comparison FAILED\n")
return
}

if strings.Compare(sVal, kCheck.String("parent1.Value")) != 0 {
fmt.Printf("Single detailed key: value comparison FAILED\n")
return
}

fmt.Printf("\nDetailed single key test passed.\n")

kCheck.Delete("")

// Detailed request (recurse) test.
// analog of the command:
// consul kv get -detailed -recurse parent

sKey = "parent"

provider = consul.Provider(consul.Config{
Key: sKey,
Recurse: true,
Detailed: true,
Cfg: api.DefaultConfig(),
})

if err := kCheck.Load(provider, nil); err != nil {
fmt.Printf("error loading config: %v", err)
return
}

if sFlags != uint64(kCheck.Int64("parent1.Flags")) {
fmt.Printf("Single detailed key: flags (metadata: age) comparison FAILED\n")
return
}

if strings.Compare(sVal, kCheck.String("parent1.Value")) != 0 {
fmt.Printf("Single key: value comparison FAILED\n")
return
}

sFlags = uint64(0)
sVal = "mother"

if sFlags != uint64(kCheck.Int64("parent2.Flags")) {
fmt.Printf("Single detailed key: flags (metadata: age) comparison FAILED\n")
return
}

if strings.Compare(sVal, kCheck.String("parent2.Value")) != 0 {
fmt.Printf("Single key: value comparison FAILED\n")
return
}

fmt.Printf("\nDetailed request (recurse) test passed.\n")

kCheck.Delete("")

// Watch test

sKey = "parent"
provider = consul.Provider(consul.Config{
Key: sKey,
Recurse: true,
Detailed: false,
Cfg: api.DefaultConfig(),
})

// Getting the old value
kCheck.Load(provider, nil)
oldVal := kCheck.String("parent1")

changedC := make(chan string, 1)

provider.Watch(func(event interface{}, err error) {
if err != nil {
fmt.Printf("Unexpected error: %v", err)
return
}

kCheck.Load(provider, nil)
// skip the first call
if strings.Compare(oldVal, kCheck.String("parent1")) != 0 {
changedC <- kCheck.String("parent1")
}
})

// changing
var newVal string = "dad"
cmd := exec.Command("consul", "kv", "put", "parent1", newVal)
err = cmd.Run()
if err != nil {
log.Fatal(err)
}

if strings.Compare(newVal, <-changedC) != 0 {
fmt.Printf("Watch failed: new value comparison FAILED\n")
return
}
fmt.Printf("Watch test passed.\n")

fmt.Printf("ALL TESTS PASSED\n")
}
4 changes: 4 additions & 0 deletions examples/read-consul/req1.json
@@ -0,0 +1,4 @@
{
"parent1": "father",
"parent2": "mother"
}
8 changes: 8 additions & 0 deletions examples/read-consul/req2.json
@@ -0,0 +1,8 @@
{
"child1": "Alex",
"child2": "Julia",
"child3": "Michael",
"child4": "Natalie",
"child5": "Rosalind",
"child6": "Tim"
}
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -10,6 +10,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/sts v1.7.2
github.com/fatih/structs v1.1.0
github.com/fsnotify/fsnotify v1.4.9
github.com/hashicorp/consul/api v1.13.0
github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/vault/api v1.0.4
github.com/joho/godotenv v1.3.0
Expand Down