github.com/DerekStrickland/consul@v1.4.5/command/connect/envoy/envoy_test.go (about)

     1  package envoy
     2  
     3  import (
     4  	"flag"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/hashicorp/consul/agent/xds"
    12  	"github.com/mitchellh/cli"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  var update = flag.Bool("update", false, "update golden files")
    17  
    18  func TestCatalogCommand_noTabs(t *testing.T) {
    19  	t.Parallel()
    20  	if strings.ContainsRune(New(nil).Help(), '\t') {
    21  		t.Fatal("help has tabs")
    22  	}
    23  }
    24  
    25  // testSetAndResetEnv sets the env vars passed as KEY=value strings in the
    26  // current ENV and returns a func() that will undo it's work at the end of the
    27  // test for use with defer.
    28  func testSetAndResetEnv(t *testing.T, env []string) func() {
    29  	old := make(map[string]*string)
    30  	for _, e := range env {
    31  		pair := strings.SplitN(e, "=", 2)
    32  		current := os.Getenv(pair[0])
    33  		if current != "" {
    34  			old[pair[0]] = &current
    35  		} else {
    36  			// save it as a nil so we know to remove again
    37  			old[pair[0]] = nil
    38  		}
    39  		os.Setenv(pair[0], pair[1])
    40  	}
    41  	// Return a func that will reset to old values
    42  	return func() {
    43  		for k, v := range old {
    44  			if v == nil {
    45  				os.Unsetenv(k)
    46  			} else {
    47  				os.Setenv(k, *v)
    48  			}
    49  		}
    50  	}
    51  }
    52  
    53  // This tests the args we use to generate the template directly because they
    54  // encapsulate all the argument and default handling code which is where most of
    55  // the logic is. We also allow generating golden files but only for cases that
    56  // pass the test of having their template args generated as expected.
    57  func TestGenerateConfig(t *testing.T) {
    58  	cases := []struct {
    59  		Name     string
    60  		Flags    []string
    61  		Env      []string
    62  		WantArgs templateArgs
    63  		WantErr  string
    64  	}{
    65  		{
    66  			Name:    "no-args",
    67  			Flags:   []string{},
    68  			Env:     []string{},
    69  			WantErr: "No proxy ID specified",
    70  		},
    71  		{
    72  			Name:  "defaults",
    73  			Flags: []string{"-proxy-id", "test-proxy"},
    74  			Env:   []string{},
    75  			WantArgs: templateArgs{
    76  				ProxyCluster:          "test-proxy",
    77  				ProxyID:               "test-proxy",
    78  				AgentAddress:          "127.0.0.1",
    79  				AgentPort:             "8502", // Note this is the gRPC port
    80  				AdminBindAddress:      "127.0.0.1",
    81  				AdminBindPort:         "19000",
    82  				LocalAgentClusterName: xds.LocalAgentClusterName,
    83  			},
    84  		},
    85  		{
    86  			Name: "grpc-addr-flag",
    87  			Flags: []string{"-proxy-id", "test-proxy",
    88  				"-grpc-addr", "localhost:9999"},
    89  			Env: []string{},
    90  			WantArgs: templateArgs{
    91  				ProxyCluster: "test-proxy",
    92  				ProxyID:      "test-proxy",
    93  				// Should resolve IP, note this might not resolve the same way
    94  				// everywhere which might make this test brittle but not sure what else
    95  				// to do.
    96  				AgentAddress:          "127.0.0.1",
    97  				AgentPort:             "9999",
    98  				AdminBindAddress:      "127.0.0.1",
    99  				AdminBindPort:         "19000",
   100  				LocalAgentClusterName: xds.LocalAgentClusterName,
   101  			},
   102  		},
   103  		{
   104  			Name:  "grpc-addr-env",
   105  			Flags: []string{"-proxy-id", "test-proxy"},
   106  			Env: []string{
   107  				"CONSUL_GRPC_ADDR=localhost:9999",
   108  			},
   109  			WantArgs: templateArgs{
   110  				ProxyCluster: "test-proxy",
   111  				ProxyID:      "test-proxy",
   112  				// Should resolve IP, note this might not resolve the same way
   113  				// everywhere which might make this test brittle but not sure what else
   114  				// to do.
   115  				AgentAddress:          "127.0.0.1",
   116  				AgentPort:             "9999",
   117  				AdminBindAddress:      "127.0.0.1",
   118  				AdminBindPort:         "19000",
   119  				LocalAgentClusterName: xds.LocalAgentClusterName,
   120  			},
   121  		},
   122  		// TODO(banks): all the flags/env manipulation cases
   123  	}
   124  
   125  	for _, tc := range cases {
   126  		t.Run(tc.Name, func(t *testing.T) {
   127  			require := require.New(t)
   128  
   129  			ui := cli.NewMockUi()
   130  			c := New(ui)
   131  
   132  			defer testSetAndResetEnv(t, tc.Env)()
   133  
   134  			// Run the command
   135  			args := append([]string{"-bootstrap"}, tc.Flags...)
   136  			code := c.Run(args)
   137  			if tc.WantErr == "" {
   138  				require.Equal(0, code, ui.ErrorWriter.String())
   139  			} else {
   140  				require.Equal(1, code, ui.ErrorWriter.String())
   141  				require.Contains(ui.ErrorWriter.String(), tc.WantErr)
   142  				return
   143  			}
   144  
   145  			// Verify we handled the env and flags right first to get correct template
   146  			// args.
   147  			got, err := c.templateArgs()
   148  			require.NoError(err) // Error cases should have returned above
   149  			require.Equal(&tc.WantArgs, got)
   150  
   151  			// Actual template output goes to stdout direct to avoid prefix in UI, so
   152  			// generate it again here to assert on.
   153  			actual, err := c.generateConfig()
   154  			require.NoError(err)
   155  
   156  			// If we got the arg handling write, verify output
   157  			golden := filepath.Join("testdata", tc.Name+".golden")
   158  			if *update {
   159  				ioutil.WriteFile(golden, actual, 0644)
   160  			}
   161  
   162  			expected, err := ioutil.ReadFile(golden)
   163  			require.NoError(err)
   164  			require.Equal(string(expected), string(actual))
   165  		})
   166  	}
   167  }