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