github.com/wuhuizuo/gomplate@v3.5.0+incompatible/tests/integration/datasources_consul_test.go (about) 1 //+build integration 2 //+build !windows 3 4 package integration 5 6 import ( 7 "encoding/base64" 8 "io/ioutil" 9 "os" 10 "os/user" 11 "path" 12 "strconv" 13 14 . "gopkg.in/check.v1" 15 16 "github.com/gotestyourself/gotestyourself/fs" 17 "github.com/gotestyourself/gotestyourself/icmd" 18 vaultapi "github.com/hashicorp/vault/api" 19 ) 20 21 type ConsulDatasourcesSuite struct { 22 tmpDir *fs.Dir 23 pidDir *fs.Dir 24 consulAddr string 25 consulResult *icmd.Result 26 vaultAddr string 27 vaultResult *icmd.Result 28 } 29 30 var _ = Suite(&ConsulDatasourcesSuite{}) 31 32 const consulRootToken = "00000000-1111-2222-3333-444455556666" 33 34 func (s *ConsulDatasourcesSuite) SetUpSuite(c *C) { 35 s.pidDir = fs.NewDir(c, "gomplate-inttests-pid") 36 s.tmpDir = fs.NewDir(c, "gomplate-inttests", 37 fs.WithFile( 38 "consul.json", 39 `{"acl_datacenter": "dc1", "acl_master_token": "`+consulRootToken+`"}`, 40 ), 41 fs.WithFile("vault.json", `{ 42 "pid_file": "`+s.pidDir.Join("vault.pid")+`" 43 }`), 44 ) 45 var port int 46 port, s.consulAddr = freeport() 47 consul := icmd.Command("consul", "agent", 48 "-dev", 49 "-config-file="+s.tmpDir.Join("consul.json"), 50 "-log-level=err", 51 "-http-port="+strconv.Itoa(port), 52 "-pid-file="+s.pidDir.Join("consul.pid"), 53 ) 54 s.consulResult = icmd.StartCmd(consul) 55 56 c.Logf("Fired up Consul: %v", consul) 57 58 err := waitForURL(c, "http://"+s.consulAddr+"/v1/status/leader") 59 handle(c, err) 60 61 s.startVault(c) 62 } 63 64 func (s *ConsulDatasourcesSuite) startVault(c *C) { 65 // rename any existing token so it doesn't get overridden 66 u, _ := user.Current() 67 homeDir := u.HomeDir 68 tokenFile := path.Join(homeDir, ".vault-token") 69 info, err := os.Stat(tokenFile) 70 if err == nil && info.Mode().IsRegular() { 71 os.Rename(tokenFile, path.Join(homeDir, ".vault-token.bak")) 72 } 73 74 _, s.vaultAddr = freeport() 75 vault := icmd.Command("vault", "server", 76 "-dev", 77 "-dev-root-token-id="+vaultRootToken, 78 "-log-level=err", 79 "-dev-listen-address="+s.vaultAddr, 80 "-config="+s.tmpDir.Join("vault.json"), 81 ) 82 s.vaultResult = icmd.StartCmd(vault) 83 84 c.Logf("Fired up Vault: %v", vault) 85 86 err = waitForURL(c, "http://"+s.vaultAddr+"/v1/sys/health") 87 handle(c, err) 88 } 89 90 func killByPidFile(pidFile string) error { 91 p, err := ioutil.ReadFile(pidFile) 92 if err != nil { 93 return err 94 } 95 pid, err := strconv.Atoi(string(p)) 96 if err != nil { 97 return err 98 } 99 process, err := os.FindProcess(pid) 100 if err != nil { 101 return err 102 } 103 err = process.Kill() 104 return err 105 } 106 107 func (s *ConsulDatasourcesSuite) TearDownSuite(c *C) { 108 defer s.tmpDir.Remove() 109 defer s.pidDir.Remove() 110 111 err := killByPidFile(s.pidDir.Join("vault.pid")) 112 handle(c, err) 113 114 err = killByPidFile(s.pidDir.Join("consul.pid")) 115 handle(c, err) 116 117 // restore old vault token if it was backed up 118 u, _ := user.Current() 119 homeDir := u.HomeDir 120 tokenFile := path.Join(homeDir, ".vault-token.bak") 121 info, err := os.Stat(tokenFile) 122 if err == nil && info.Mode().IsRegular() { 123 os.Rename(tokenFile, path.Join(homeDir, ".vault-token")) 124 } 125 } 126 127 func (s *ConsulDatasourcesSuite) consulPut(c *C, k, v string) { 128 result := icmd.RunCmd(icmd.Command("consul", "kv", "put", k, v), 129 func(c *icmd.Cmd) { 130 c.Env = []string{"CONSUL_HTTP_ADDR=http://" + s.consulAddr} 131 }) 132 result.Assert(c, icmd.Success) 133 } 134 135 func (s *ConsulDatasourcesSuite) consulDelete(c *C, k string) { 136 result := icmd.RunCmd(icmd.Command("consul", "kv", "delete", k), 137 func(c *icmd.Cmd) { 138 c.Env = []string{"CONSUL_HTTP_ADDR=http://" + s.consulAddr} 139 }) 140 result.Assert(c, icmd.Success) 141 } 142 143 func (s *ConsulDatasourcesSuite) TestConsulDatasource(c *C) { 144 s.consulPut(c, "foo1", "bar") 145 defer s.consulDelete(c, "foo1") 146 result := icmd.RunCmd(icmd.Command(GomplateBin, 147 "-d", "consul=consul://", 148 "-i", `{{(ds "consul" "foo1")}}`, 149 ), func(c *icmd.Cmd) { 150 c.Env = []string{"CONSUL_HTTP_ADDR=http://" + s.consulAddr} 151 }) 152 result.Assert(c, icmd.Expected{ExitCode: 0, Out: "bar"}) 153 154 s.consulPut(c, "foo2", `{"bar": "baz"}`) 155 defer s.consulDelete(c, "foo2") 156 result = icmd.RunCmd(icmd.Command(GomplateBin, 157 "-d", "consul=consul://?type=application/json", 158 "-i", `{{(ds "consul" "foo2").bar}}`, 159 ), func(c *icmd.Cmd) { 160 c.Env = []string{"CONSUL_HTTP_ADDR=http://" + s.consulAddr} 161 }) 162 result.Assert(c, icmd.Expected{ExitCode: 0, Out: "baz"}) 163 164 s.consulPut(c, "foo2", `bar`) 165 defer s.consulDelete(c, "foo2") 166 result = icmd.RunCmd(icmd.Command(GomplateBin, 167 "-d", "consul=consul://"+s.consulAddr, 168 "-i", `{{(ds "consul" "foo2")}}`, 169 )) 170 result.Assert(c, icmd.Expected{ExitCode: 0, Out: "bar"}) 171 172 s.consulPut(c, "foo3", `bar`) 173 defer s.consulDelete(c, "foo3") 174 result = icmd.RunCmd(icmd.Command(GomplateBin, 175 "-d", "consul=consul+http://"+s.consulAddr, 176 "-i", `{{(ds "consul" "foo3")}}`, 177 )) 178 result.Assert(c, icmd.Expected{ExitCode: 0, Out: "bar"}) 179 } 180 181 func (s *ConsulDatasourcesSuite) TestConsulDatasourceListKeys(c *C) { 182 s.consulPut(c, "list-of-keys/foo1", `{"bar1": "bar1"}`) 183 s.consulPut(c, "list-of-keys/foo2", "bar2") 184 defer s.consulDelete(c, "list-of-keys") 185 186 // Get a list of keys using the ds args 187 result := icmd.RunCmd(icmd.Command(GomplateBin, 188 "-d", "consul=consul://", 189 "-i", `{{(ds "consul" "list-of-keys/") | data.ToJSON }}`, 190 ), func(c *icmd.Cmd) { 191 c.Env = []string{"CONSUL_HTTP_ADDR=http://" + s.consulAddr} 192 }) 193 expectedResult := `[{"key":"foo1","value":"{\"bar1\": \"bar1\"}"},{"key":"foo2","value":"bar2"}]` 194 result.Assert(c, icmd.Expected{ExitCode: 0, Out: expectedResult}) 195 196 // Get a list of keys using the ds uri 197 result = icmd.RunCmd(icmd.Command(GomplateBin, 198 "-d", "consul=consul+http://"+s.consulAddr+"/list-of-keys/", 199 "-i", `{{(ds "consul" ) | data.ToJSON }}`, 200 )) 201 expectedResult = `[{"key":"foo1","value":"{\"bar1\": \"bar1\"}"},{"key":"foo2","value":"bar2"}]` 202 result.Assert(c, icmd.Expected{ExitCode: 0, Out: expectedResult}) 203 204 // Get a specific value from the list of Consul keys 205 result = icmd.RunCmd(icmd.Command(GomplateBin, 206 "-d", "consul=consul+http://"+s.consulAddr+"/list-of-keys/", 207 "-i", `{{ $data := (ds "consul") }} {{ (index $data 0).value }}`, 208 )) 209 expectedResult = `{"bar1": "bar1"}` 210 result.Assert(c, icmd.Expected{ExitCode: 0, Out: expectedResult}) 211 } 212 213 func (s *ConsulDatasourcesSuite) TestConsulWithVaultAuth(c *C) { 214 v, err := createVaultClient(s.vaultAddr, vaultRootToken) 215 handle(c, err) 216 217 err = v.vc.Sys().Mount("consul/", &vaultapi.MountInput{Type: "consul"}) 218 handle(c, err) 219 defer v.vc.Sys().Unmount("consul/") 220 221 _, err = v.vc.Logical().Write("consul/config/access", map[string]interface{}{ 222 "address": s.consulAddr, "token": consulRootToken, 223 }) 224 handle(c, err) 225 policy := base64.StdEncoding.EncodeToString([]byte(`key "" { policy = "read" }`)) 226 _, err = v.vc.Logical().Write("consul/roles/readonly", map[string]interface{}{"policy": policy}) 227 handle(c, err) 228 229 s.consulPut(c, "foo", "bar") 230 defer s.consulDelete(c, "foo") 231 result := icmd.RunCmd(icmd.Command(GomplateBin, 232 "-d", "consul=consul://", 233 "-i", `{{(ds "consul" "foo")}}`, 234 ), func(c *icmd.Cmd) { 235 c.Env = []string{ 236 "VAULT_TOKEN=" + vaultRootToken, 237 "VAULT_ADDR=http://" + s.vaultAddr, 238 "CONSUL_VAULT_ROLE=readonly", 239 "CONSUL_HTTP_ADDR=http://" + s.consulAddr, 240 } 241 }) 242 result.Assert(c, icmd.Expected{ExitCode: 0, Out: "bar"}) 243 }