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  }