github.com/hairyhenderson/gomplate/v3@v3.11.7/internal/tests/integration/datasources_consul_test.go (about) 1 //go:build !windows 2 // +build !windows 3 4 package integration 5 6 import ( 7 "strconv" 8 "testing" 9 10 vaultapi "github.com/hashicorp/vault/api" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 "gotest.tools/v3/fs" 14 "gotest.tools/v3/icmd" 15 ) 16 17 const consulRootToken = "00000000-1111-2222-3333-444455556666" 18 19 func setupDatasourcesConsulTest(t *testing.T) (string, *vaultClient) { 20 pidDir := fs.NewDir(t, "gomplate-inttests-pid") 21 t.Cleanup(pidDir.Remove) 22 23 httpPort, consulAddr := freeport(t) 24 serverPort, _ := freeport(t) 25 serfLanPort, _ := freeport(t) 26 27 tmpDir := fs.NewDir(t, "gomplate-inttests", 28 fs.WithFile( 29 "consul.json", 30 `{ 31 "log_level": "err", 32 "primary_datacenter": "dc1", 33 "acl": { 34 "enabled": true, 35 "tokens": { 36 "initial_management": "`+consulRootToken+`", 37 "default": "`+consulRootToken+`" 38 } 39 }, 40 "ports": { 41 "http": `+strconv.Itoa(httpPort)+`, 42 "server": `+strconv.Itoa(serverPort)+`, 43 "serf_lan": `+strconv.Itoa(serfLanPort)+`, 44 "serf_wan": -1, 45 "dns": -1, 46 "grpc": -1 47 }, 48 "connect": { "enabled": false } 49 }`, 50 ), 51 fs.WithFile("vault.json", `{ 52 "pid_file": "`+pidDir.Join("vault.pid")+`" 53 }`), 54 ) 55 t.Cleanup(tmpDir.Remove) 56 57 consul := icmd.Command("consul", "agent", 58 "-dev", 59 "-config-file="+tmpDir.Join("consul.json"), 60 "-pid-file="+pidDir.Join("consul.pid"), 61 ) 62 consulResult := icmd.StartCmd(consul) 63 t.Cleanup(func() { 64 err := consulResult.Cmd.Process.Kill() 65 assert.NoError(t, err) 66 67 consulResult.Cmd.Wait() 68 69 t.Logf("consul logs:\n%s\n", consulResult.Combined()) 70 71 consulResult.Assert(t, icmd.Expected{ExitCode: 0}) 72 }) 73 74 t.Logf("Fired up Consul: %v", consul) 75 76 err := waitForURL(t, "http://"+consulAddr+"/v1/status/leader") 77 require.NoError(t, err) 78 79 _, vaultClient := startVault(t) 80 81 // create a readonly policy, for use in some tests 82 aclResult := icmd.RunCmd(icmd.Command("consul", "acl", "policy", "create", 83 "-name", "readonly", 84 "-rules", `acl = "read"`, 85 "-token", consulRootToken, 86 "-http-addr", "http://"+consulAddr, 87 )) 88 aclResult.Assert(t, icmd.Success) 89 90 return consulAddr, vaultClient 91 } 92 93 func consulPut(t *testing.T, consulAddr, k, v string) { 94 result := icmd.RunCmd(icmd.Command("consul", "kv", "put", k, v), 95 func(c *icmd.Cmd) { 96 c.Env = []string{"CONSUL_HTTP_ADDR=http://" + consulAddr} 97 }) 98 result.Assert(t, icmd.Success) 99 t.Cleanup(func() { 100 result := icmd.RunCmd(icmd.Command("consul", "kv", "delete", k), 101 func(c *icmd.Cmd) { 102 c.Env = []string{"CONSUL_HTTP_ADDR=http://" + consulAddr} 103 }) 104 result.Assert(t, icmd.Success) 105 }) 106 } 107 108 func TestDatasources_Consul(t *testing.T) { 109 consulAddr, _ := setupDatasourcesConsulTest(t) 110 consulPut(t, consulAddr, "foo1", "bar") 111 112 o, e, err := cmd(t, "-d", "consul=consul://", 113 "-i", `{{(ds "consul" "foo1")}}`). 114 withEnv("CONSUL_HTTP_ADDR", "http://"+consulAddr).run() 115 assertSuccess(t, o, e, err, "bar") 116 117 consulPut(t, consulAddr, "foo2", `{"bar": "baz"}`) 118 119 o, e, err = cmd(t, "-d", "consul=consul://?type=application/json", 120 "-i", `{{(ds "consul" "foo2").bar}}`). 121 withEnv("CONSUL_HTTP_ADDR", "http://"+consulAddr).run() 122 assertSuccess(t, o, e, err, "baz") 123 124 consulPut(t, consulAddr, "foo2", `bar`) 125 126 o, e, err = cmd(t, "-d", "consul=consul://"+consulAddr, 127 "-i", `{{(ds "consul" "foo2")}}`).run() 128 assertSuccess(t, o, e, err, "bar") 129 130 consulPut(t, consulAddr, "foo3", `bar`) 131 132 o, e, err = cmd(t, "-d", "consul=consul+http://"+consulAddr, 133 "-i", `{{(ds "consul" "foo3")}}`).run() 134 assertSuccess(t, o, e, err, "bar") 135 } 136 137 func TestDatasources_Consul_ListKeys(t *testing.T) { 138 consulAddr, _ := setupDatasourcesConsulTest(t) 139 consulPut(t, consulAddr, "list-of-keys/foo1", `{"bar1": "bar1"}`) 140 consulPut(t, consulAddr, "list-of-keys/foo2", "bar2") 141 142 // Get a list of keys using the ds args 143 expectedResult := `[{"key":"foo1","value":"{\"bar1\": \"bar1\"}"},{"key":"foo2","value":"bar2"}]` 144 o, e, err := cmd(t, "-d", "consul=consul://", 145 "-i", `{{(ds "consul" "list-of-keys/") | data.ToJSON }}`). 146 withEnv("CONSUL_HTTP_ADDR", "http://"+consulAddr).run() 147 assertSuccess(t, o, e, err, expectedResult) 148 149 // Get a list of keys using the ds uri 150 expectedResult = `[{"key":"foo1","value":"{\"bar1\": \"bar1\"}"},{"key":"foo2","value":"bar2"}]` 151 o, e, err = cmd(t, "-d", "consul=consul+http://"+consulAddr+"/list-of-keys/", 152 "-i", `{{(ds "consul" ) | data.ToJSON }}`).run() 153 assertSuccess(t, o, e, err, expectedResult) 154 155 // Get a specific value from the list of Consul keys 156 expectedResult = `{"bar1": "bar1"}` 157 o, e, err = cmd(t, "-d", "consul=consul+http://"+consulAddr+"/list-of-keys/", 158 "-i", `{{ $data := ds "consul" }}{{ (index $data 0).value }}`).run() 159 assertSuccess(t, o, e, err, expectedResult) 160 } 161 162 func TestDatasources_Consul_WithVaultAuth(t *testing.T) { 163 consulAddr, v := setupDatasourcesConsulTest(t) 164 165 err := v.vc.Sys().Mount("consul/", &vaultapi.MountInput{Type: "consul"}) 166 require.NoError(t, err) 167 defer v.vc.Sys().Unmount("consul/") 168 169 _, err = v.vc.Logical().Write("consul/config/access", map[string]interface{}{ 170 "address": consulAddr, "token": consulRootToken, 171 }) 172 require.NoError(t, err) 173 _, err = v.vc.Logical().Write("consul/roles/readonly", map[string]interface{}{ 174 "policies": "readonly", 175 }) 176 require.NoError(t, err) 177 178 consulPut(t, consulAddr, "foo", "bar") 179 180 o, e, err := cmd(t, 181 "-d", "consul=consul://", 182 "-i", `{{(ds "consul" "foo")}}`). 183 withEnv("VAULT_TOKEN", vaultRootToken). 184 withEnv("VAULT_ADDR", "http://"+v.addr). 185 withEnv("CONSUL_VAULT_ROLE", "readonly"). 186 withEnv("CONSUL_HTTP_ADDR", "http://"+consulAddr). 187 run() 188 assertSuccess(t, o, e, err, "bar") 189 }